X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fhttp%2Fclient.cpp;h=705f4cb7bbd0a7e09dcdbcde3dc979e9bf0cae86;hb=5afa6e0e07b20ef58d262d69d96971df9a4be71f;hp=80815e0c9f6c33a5ced29e65cb6c82674c8b8b97;hpb=6af1bfce6dc53104c5406adef32d186384525ae3;p=libs%2Fnet.git diff --git a/source/http/client.cpp b/source/http/client.cpp index 80815e0..705f4cb 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" @@ -13,6 +14,9 @@ namespace Http { Client::Client(): sock(0), event_disp(0), + resolver(0), + resolve_listener(0), + resolve_tag(0), user_agent("libmsphttp/0.1"), request(0), response(0) @@ -34,26 +38,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 +66,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 +119,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,6 +187,8 @@ void Client::data_available() } catch(const exception &e) { + if(signal_socket_error.empty()) + throw; signal_socket_error.emit(e); return; } @@ -159,5 +221,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