]> git.tdb.fi Git - libs/net.git/blob - source/client.cpp
Rename data to content in Message
[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         if(event_disp && sock)
40                 event_disp->remove(*sock);
41         event_disp=ed;
42         if(event_disp && sock)
43                 event_disp->add(*sock);
44 }
45
46 void Client::start_request(const Request &r)
47 {
48         if(request)
49                 throw InvalidState("Already processing a request");
50
51         RefPtr<Net::SockAddr> addr=Net::resolve(r.get_header("host")+":"+r.get_header("x-port"));
52
53         delete sock;
54         sock=new Net::StreamSocket(addr->get_family());
55         sock->set_block(false);
56
57         sock->signal_data_available.connect(sigc::mem_fun(this, &Client::data_available));
58         sock->signal_connect_finished.connect(sigc::mem_fun(this, &Client::connect_finished));
59         if(event_disp)
60                 event_disp->add(*sock);
61
62         sock->connect(*addr);
63
64         request=new Request(r);
65
66         delete response;
67         response=0;
68         in_buf.clear();
69 }
70
71 const Response *Client::get_url(const std::string &url)
72 {
73         start_request(Request::from_url(url));
74         wait_response();
75         return response;
76 }
77
78 void Client::tick()
79 {
80         if(!request)
81                 return;
82
83         while(IO::PollEvent ev=IO::poll(*sock, sock->get_events(), Time::zero))
84                 sock->event(ev);
85
86         if(response && response->get_complete())
87         {
88                 signal_response_complete.emit(*response);
89
90                 delete sock;
91                 sock=0;
92                 delete request;
93                 request=0;
94         }
95 }
96
97 void Client::wait_response()
98 {
99         while(!response || !response->get_complete())
100                 tick();
101 }
102
103 void Client::abort()
104 {
105         delete sock;
106         sock=0;
107         delete request;
108         request=0;
109 }
110
111 void Client::connect_finished(int err)
112 {
113         if(err)
114         {
115                 signal_socket_error.emit(err);
116
117                 sock->close();
118                 delete request;
119                 request=0;
120         }
121         else
122                 sock->write(request->str());
123 }
124
125 void Client::data_available()
126 {
127         char rbuf[4096];
128         unsigned len=sock->read(rbuf, sizeof(rbuf));
129         in_buf.append(rbuf, len);
130
131         if(!response)
132         {
133                 if(in_buf.find("\r\n\r\n")!=string::npos || in_buf.find("\n\n")!=string::npos)
134                 {
135                         response=new Response(Response::parse(in_buf));
136                         response->set_user_data(request->get_user_data());
137                         in_buf=string();
138                 }
139         }
140         else
141         {
142                 len=response->parse_content(in_buf);
143                 in_buf.erase(0, len);
144         }
145
146         if(response && response->get_complete())
147         {
148                 signal_response_complete.emit(*response);
149
150                 sock->close();
151                 delete request;
152                 request=0;
153         }
154 }
155
156 } // namespace Http
157 } // namespace Msp