X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fhttp%2Fclient.cpp;h=1c4c953e5d5d5fb31b3243e13a2fa6d728d12a33;hb=HEAD;hp=3d14b04e59d45b22889d8c699eab428829a16ea5;hpb=add5c00b0b8a184c35473c20a65fa676525cf3f8;p=libs%2Fnet.git diff --git a/source/http/client.cpp b/source/http/client.cpp index 3d14b04..1c4c953 100644 --- a/source/http/client.cpp +++ b/source/http/client.cpp @@ -1,7 +1,7 @@ -#include -#include -#include #include "client.h" +#include +#include +#include #include "request.h" #include "response.h" @@ -10,19 +10,8 @@ using namespace std; namespace Msp { namespace Http { -Client::Client(): - sock(0), - event_disp(0), - user_agent("libmsphttp/0.1"), - request(0), - response(0) -{ } - Client::~Client() { - delete sock; - delete request; - delete response; } void Client::use_event_dispatcher(IO::EventDispatcher *ed) @@ -34,41 +23,47 @@ void Client::use_event_dispatcher(IO::EventDispatcher *ed) event_disp->add(*sock); } -void Client::start_request(const Request &r) +void Client::use_resolver(Net::Resolver *r) { - if(request) - throw client_busy(); + if(resolver) + resolve_listener.reset(); - string host = r.get_header("Host"); - if(host.find(':')==string::npos) - host += ":80"; - RefPtr addr = Net::resolve(host); - - delete sock; - sock = new Net::StreamSocket(addr->get_family()); - sock->set_block(false); + resolver = r; + if(resolver) + resolve_listener = make_unique(*this); +} - sock->signal_data_available.connect(sigc::mem_fun(this, &Client::data_available)); - sock->signal_connect_finished.connect(sigc::mem_fun(this, &Client::connect_finished)); - if(event_disp) - event_disp->add(*sock); +void Client::start_request(const Request &r) +{ + if(request) + throw invalid_state("already processing a request"); - sock->connect(*addr); + sock.reset(); - request = new Request(r); + request = make_unique(r); if(!user_agent.empty()) request->set_header("User-Agent", user_agent); - delete response; - response = 0; + response.reset(); in_buf.clear(); + + string host = r.get_header("Host"); + if(host.find(':')==string::npos) + host += ":80"; + if(resolver) + resolve_tag = resolver->resolve(host); + else + { + unique_ptr addr(Net::resolve(host)); + address_resolved(resolve_tag, *addr); + } } const Response *Client::get_url(const std::string &url) { start_request(Request::from_url(url)); wait_response(); - return response; + return response.get(); } void Client::tick() @@ -83,10 +78,8 @@ void Client::tick() { signal_response_complete.emit(*response); - delete sock; - sock = 0; - delete request; - request = 0; + sock.reset(); + request.reset(); } } @@ -98,23 +91,64 @@ void Client::wait_response() void Client::abort() { - delete sock; - sock = 0; - delete request; - request = 0; + sock.reset(); + request.reset(); +} + +void Client::address_resolved(unsigned tag, const Net::SockAddr &addr) +{ + if(tag!=resolve_tag) + return; + resolve_tag = 0; + + sock = make_unique(addr.get_family()); + sock->set_block(false); + + sock->signal_data_available.connect(sigc::mem_fun(this, &Client::data_available)); + sock->signal_connect_finished.connect(sigc::mem_fun(this, &Client::connect_finished)); + if(event_disp) + event_disp->add(*sock); + + sock->connect(addr); +} + +void Client::resolve_failed(unsigned tag, const exception &err) +{ + if(tag!=resolve_tag) + return; + resolve_tag = 0; + + request.reset(); + + if(signal_socket_error.empty()) + throw err; + signal_socket_error.emit(err); } void Client::connect_finished(const exception *err) { if(err) { - signal_socket_error.emit(err); + request.reset(); - delete request; - request = 0; + if(signal_socket_error.empty()) + throw *err; + signal_socket_error.emit(*err); } else - sock->write(request->str()); + { + try + { + sock->write(request->str()); + } + catch(const exception &e) + { + if(signal_socket_error.empty()) + throw; + signal_socket_error.emit(e); + return; + } + } } void Client::data_available() @@ -127,7 +161,9 @@ void Client::data_available() } catch(const exception &e) { - signal_socket_error.emit(&e); + if(signal_socket_error.empty()) + throw; + signal_socket_error.emit(e); return; } @@ -139,7 +175,7 @@ void Client::data_available() { if(in_buf.find("\r\n\r\n")!=string::npos || in_buf.find("\n\n")!=string::npos) { - response = new Response(Response::parse(in_buf)); + response = make_unique(Response::parse(in_buf)); response->set_user_data(request->get_user_data()); in_buf = string(); } @@ -154,10 +190,27 @@ void Client::data_available() { signal_response_complete.emit(*response); - delete request; - request = 0; + request.reset(); } } + +Client::ResolveListener::ResolveListener(Client &c): + client(c) +{ + client.resolver->signal_address_resolved.connect(sigc::mem_fun(this, &ResolveListener::address_resolved)); + client.resolver->signal_resolve_failed.connect(sigc::mem_fun(this, &ResolveListener::resolve_failed)); +} + +void Client::ResolveListener::address_resolved(unsigned tag, const Net::SockAddr &addr) +{ + client.address_resolved(tag, addr); +} + +void Client::ResolveListener::resolve_failed(unsigned tag, const exception &err) +{ + client.resolve_failed(tag, err); +} + } // namespace Http } // namespace Msp