+++ /dev/null
-#include <msp/core/except.h>
-#include <msp/core/refptr.h>
-#include <msp/net/resolve.h>
-#include <msp/time/units.h>
-#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<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);
-
- 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