X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fhttp%2Fclient.cpp;h=073656d184440aa225ca2774f5f98e2dafd8374b;hb=6625cf0e574406425c35d33110f8d99617e902df;hp=3d14b04e59d45b22889d8c699eab428829a16ea5;hpb=add5c00b0b8a184c35473c20a65fa676525cf3f8;p=libs%2Fnet.git diff --git a/source/http/client.cpp b/source/http/client.cpp index 3d14b04..073656d 100644 --- a/source/http/client.cpp +++ b/source/http/client.cpp @@ -1,6 +1,7 @@ +#include #include #include -#include +#include #include "client.h" #include "request.h" #include "response.h" @@ -10,14 +11,6 @@ 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; @@ -34,26 +27,26 @@ void Client::use_event_dispatcher(IO::EventDispatcher *ed) event_disp->add(*sock); } +void Client::use_resolver(Net::Resolver *r) +{ + if(resolver) + { + delete resolve_listener; + resolve_listener = 0; + } + + resolver = r; + if(resolver) + resolve_listener = new ResolveListener(*this); +} + void Client::start_request(const Request &r) { if(request) - throw client_busy(); - - string host = r.get_header("Host"); - if(host.find(':')==string::npos) - host += ":80"; - RefPtr addr = Net::resolve(host); + throw invalid_state("already processing a request"); delete sock; - sock = new Net::StreamSocket(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); + sock = 0; request = new Request(r); if(!user_agent.empty()) @@ -62,6 +55,17 @@ void Client::start_request(const Request &r) delete response; response = 0; in_buf.clear(); + + string host = r.get_header("Host"); + if(host.find(':')==string::npos) + host += ":80"; + if(resolver) + resolve_tag = resolver->resolve(host); + else + { + RefPtr addr = Net::resolve(host); + address_resolved(resolve_tag, *addr); + } } const Response *Client::get_url(const std::string &url) @@ -104,17 +108,62 @@ void Client::abort() request = 0; } +void Client::address_resolved(unsigned tag, const Net::SockAddr &addr) +{ + if(tag!=resolve_tag) + return; + resolve_tag = 0; + + sock = new Net::StreamSocket(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; + + delete request; + request = 0; + + 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); - 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 +176,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; } @@ -159,5 +210,23 @@ void Client::data_available() } } + +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