]> git.tdb.fi Git - libs/net.git/blob - source/client.cpp
Initial revision
[libs/net.git] / source / client.cpp
1 /* $Id$
2
3 This file is part of libmsphttp
4 Copyright © 2008  Mikkosoft Productions, Mikko Rasa
5 Distributed under the LGPL
6 */
7
8 #include <msp/core/except.h>
9 #include <msp/core/refptr.h>
10 #include <msp/net/resolve.h>
11 #include <msp/time/units.h>
12 #include "client.h"
13 #include "request.h"
14 #include "response.h"
15
16 using namespace std;
17
18 #include <iostream>
19
20 namespace Msp {
21 namespace Http {
22
23 Client::Client():
24         sock(0),
25         event_disp(0),
26         request(0),
27         response(0)
28 { }
29
30 Client::~Client()
31 {
32         delete sock;
33         delete request;
34         delete response;
35 }
36
37 void Client::use_event_dispatcher(IO::EventDispatcher *ed)
38 {
39         event_disp=ed;
40         if(sock)
41                 event_disp->add(*sock);
42 }
43
44 void Client::start_request(const Request &r)
45 {
46         if(request)
47                 throw InvalidState("Already processing a request");
48
49         RefPtr<Net::SockAddr> addr=Net::resolve(r.get_header("host")+":"+r.get_header("x-port"));
50
51         delete sock;
52         sock=new Net::StreamSocket(addr->get_family());
53         sock->set_block(false);
54
55         sock->signal_data_available.connect(sigc::mem_fun(this, &Client::data_available));
56         sock->signal_connect_finished.connect(sigc::mem_fun(this, &Client::connect_finished));
57         if(event_disp)
58                 event_disp->add(*sock);
59
60         sock->connect(*addr);
61
62         request=new Request(r);
63
64         delete response;
65         response=0;
66         in_buf.clear();
67 }
68
69 void Client::get_url(const std::string &url)
70 {
71         start_request(Request::from_url(url));
72         wait_response();
73 }
74
75 void Client::tick()
76 {
77         if(!request)
78                 return;
79
80         while(IO::PollEvent ev=IO::poll(*sock, sock->get_events(), Time::zero))
81                 sock->event(ev);
82
83         if(response && response->get_complete())
84         {
85                 signal_response_complete.emit(*response);
86
87                 delete sock;
88                 sock=0;
89                 delete request;
90                 request=0;
91         }
92 }
93
94 void Client::wait_response()
95 {
96         while(!response || !response->get_complete())
97                 tick();
98 }
99
100 void Client::abort()
101 {
102         delete sock;
103         sock=0;
104         delete request;
105         request=0;
106 }
107
108 void Client::connect_finished(int err)
109 {
110         if(err)
111         {
112                 signal_socket_error.emit(err);
113
114                 sock->close();
115                 delete request;
116                 request=0;
117         }
118         else
119                 sock->write(request->str());
120 }
121
122 void Client::data_available()
123 {
124         char rbuf[4096];
125         unsigned len=sock->read(rbuf, sizeof(rbuf));
126         in_buf.append(rbuf, len);
127
128         if(!response)
129         {
130                 if(in_buf.find("\r\n\r\n")!=string::npos || in_buf.find("\n\n")!=string::npos)
131                 {
132                         response=new Response(Response::parse(in_buf));
133                         in_buf=string();
134                 }
135         }
136         else
137         {
138                 len=response->parse_data(in_buf);
139                 in_buf.erase(0, len);
140         }
141
142         if(response && response->get_complete())
143         {
144                 signal_response_complete.emit(*response);
145
146                 sock->close();
147                 delete request;
148                 request=0;
149         }
150 }
151
152 } // namespace Http
153 } // namespace Msp