X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;ds=sidebyside;f=source%2Fhttp%2Fclient.cpp;fp=source%2Fhttp%2Fclient.cpp;h=0729544a7ce0686754f721e8e6dee3e30cd7c40e;hb=cf8d2e48581eeb8f1b83e8c48321a0bc2ffa6d83;hp=0000000000000000000000000000000000000000;hpb=d683ca0964182e9579838fec8d7d100eeabddee0;p=libs%2Fnet.git diff --git a/source/http/client.cpp b/source/http/client.cpp new file mode 100644 index 0000000..0729544 --- /dev/null +++ b/source/http/client.cpp @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include "client.h" +#include "request.h" +#include "response.h" + +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) +{ + if(event_disp && sock) + event_disp->remove(*sock); + event_disp = ed; + if(event_disp && sock) + event_disp->add(*sock); +} + +void Client::start_request(const Request &r) +{ + if(request) + throw InvalidState("Already processing a request"); + + 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); + + 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); + + request = new Request(r); + if(!user_agent.empty()) + request->set_header("User-Agent", user_agent); + + delete response; + response = 0; + in_buf.clear(); +} + +const Response *Client::get_url(const std::string &url) +{ + start_request(Request::from_url(url)); + wait_response(); + return response; +} + +void Client::tick() +{ + if(!request) + return; + + while(IO::PollEvent ev = IO::poll(*sock, sock->get_events(), Time::zero)) + sock->event(ev); + + if(response && response->is_complete()) + { + signal_response_complete.emit(*response); + + delete sock; + sock = 0; + delete request; + request = 0; + } +} + +void Client::wait_response() +{ + while(request && (!response || !response->is_complete())) + tick(); +} + +void Client::abort() +{ + delete sock; + sock = 0; + delete request; + request = 0; +} + +void Client::connect_finished(const exception *err) +{ + if(err) + { + signal_socket_error.emit(err); + + delete request; + request = 0; + } + else + sock->write(request->str()); +} + +void Client::data_available() +{ + char rbuf[4096]; + unsigned len; + try + { + len = sock->read(rbuf, sizeof(rbuf)); + } + catch(const exception &e) + { + signal_socket_error.emit(&e); + return; + } + + if(!len) + return; + in_buf.append(rbuf, len); + + if(!response) + { + 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->set_user_data(request->get_user_data()); + in_buf = string(); + } + } + else + { + len = response->parse_content(in_buf); + in_buf.erase(0, len); + } + + if(response && response->is_complete()) + { + signal_response_complete.emit(*response); + + delete request; + request = 0; + } +} + +} // namespace Http +} // namespace Msp