Client::Client():
sock(0),
event_disp(0),
+ resolver(0),
+ resolve_listener(0),
+ resolve_tag(0),
user_agent("libmsphttp/0.1"),
request(0),
response(0)
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<Net::SockAddr> addr = Net::resolve(host);
-
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())
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<Net::SockAddr> addr = Net::resolve(host);
+ address_resolved(resolve_tag, *addr);
+ }
}
const Response *Client::get_url(const std::string &url)
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;
+
+ signal_socket_error.emit(err);
+
+ delete request;
+ request = 0;
+}
+
void Client::connect_finished(const exception *err)
{
if(err)
}
}
+
+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
#include <string>
#include <sigc++/signal.h>
#include <msp/io/eventdispatcher.h>
+#include <msp/net/resolve.h>
#include <msp/net/streamsocket.h>
namespace Msp {
sigc::signal<void, const std::exception &> signal_socket_error;
private:
+ struct ResolveListener: public sigc::trackable
+ {
+ Client &client;
+
+ ResolveListener(Client &);
+
+ void address_resolved(unsigned, const Net::SockAddr &);
+ void resolve_failed(unsigned, const std::exception &);
+ };
+
Net::StreamSocket *sock;
IO::EventDispatcher *event_disp;
+ Net::Resolver *resolver;
+ ResolveListener *resolve_listener;
+ unsigned resolve_tag;
std::string user_agent;
Request *request;
Response *response;
~Client();
void use_event_dispatcher(IO::EventDispatcher *);
+ void use_resolver(Net::Resolver *);
void set_user_agent(const std::string &);
void start_request(const Request &);
const Response *get_url(const std::string &);
const Request *get_request() const { return request; }
const Response *get_response() const { return response; }
private:
+ void address_resolved(unsigned, const Net::SockAddr &);
+ void resolve_failed(unsigned, const std::exception &);
void connect_finished(const std::exception *);
void data_available();
};