User | Revision | Line number | New contents of line |
donatien |
0:7aca7353eebf
|
1
|
/* HTTPClient.cpp */
|
donatien |
0:7aca7353eebf
|
2
|
/*
|
donatien |
0:7aca7353eebf
|
3
|
Copyright (C) 2012 ARM Limited.
|
donatien |
0:7aca7353eebf
|
4
|
|
donatien |
0:7aca7353eebf
|
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
donatien |
0:7aca7353eebf
|
6
|
this software and associated documentation files (the "Software"), to deal in
|
donatien |
0:7aca7353eebf
|
7
|
the Software without restriction, including without limitation the rights to
|
donatien |
0:7aca7353eebf
|
8
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
donatien |
0:7aca7353eebf
|
9
|
of the Software, and to permit persons to whom the Software is furnished to do
|
donatien |
0:7aca7353eebf
|
10
|
so, subject to the following conditions:
|
donatien |
0:7aca7353eebf
|
11
|
|
donatien |
0:7aca7353eebf
|
12
|
The above copyright notice and this permission notice shall be included in all
|
donatien |
0:7aca7353eebf
|
13
|
copies or substantial portions of the Software.
|
donatien |
0:7aca7353eebf
|
14
|
|
donatien |
0:7aca7353eebf
|
15
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
donatien |
0:7aca7353eebf
|
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
donatien |
0:7aca7353eebf
|
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
donatien |
0:7aca7353eebf
|
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
donatien |
0:7aca7353eebf
|
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
donatien |
0:7aca7353eebf
|
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
donatien |
0:7aca7353eebf
|
21
|
SOFTWARE.
|
donatien |
0:7aca7353eebf
|
22
|
*/
|
donatien |
0:7aca7353eebf
|
23
|
|
donatien |
0:7aca7353eebf
|
24
|
#define __DEBUG__ 4 //Maximum verbosity
|
donatien |
0:7aca7353eebf
|
25
|
#ifndef __MODULE__
|
donatien |
0:7aca7353eebf
|
26
|
#define __MODULE__ "HTTPClient.cpp"
|
donatien |
0:7aca7353eebf
|
27
|
#endif
|
donatien |
0:7aca7353eebf
|
28
|
|
donatien |
0:7aca7353eebf
|
29
|
#include "core/fwk.h"
|
donatien |
0:7aca7353eebf
|
30
|
|
donatien |
0:7aca7353eebf
|
31
|
#include "HTTPClient.h"
|
donatien |
0:7aca7353eebf
|
32
|
|
donatien |
0:7aca7353eebf
|
33
|
#define HTTP_REQUEST_TIMEOUT 30000
|
donatien |
0:7aca7353eebf
|
34
|
#define HTTP_PORT 80
|
donatien |
0:7aca7353eebf
|
35
|
|
donatien |
0:7aca7353eebf
|
36
|
#define CHUNK_SIZE 256
|
donatien |
0:7aca7353eebf
|
37
|
|
donatien |
0:7aca7353eebf
|
38
|
#include <cstring>
|
donatien |
0:7aca7353eebf
|
39
|
|
donatien |
0:7aca7353eebf
|
40
|
HTTPClient::HTTPClient() :
|
donatien |
0:7aca7353eebf
|
41
|
m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
|
donatien |
0:7aca7353eebf
|
42
|
{
|
donatien |
0:7aca7353eebf
|
43
|
|
donatien |
0:7aca7353eebf
|
44
|
}
|
donatien |
0:7aca7353eebf
|
45
|
|
donatien |
0:7aca7353eebf
|
46
|
HTTPClient::~HTTPClient()
|
donatien |
0:7aca7353eebf
|
47
|
{
|
donatien |
0:7aca7353eebf
|
48
|
|
donatien |
0:7aca7353eebf
|
49
|
}
|
donatien |
0:7aca7353eebf
|
50
|
|
donatien |
0:7aca7353eebf
|
51
|
#if 0
|
donatien |
0:7aca7353eebf
|
52
|
void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
|
donatien |
0:7aca7353eebf
|
53
|
{
|
donatien |
0:7aca7353eebf
|
54
|
m_basicAuthUser = user;
|
donatien |
0:7aca7353eebf
|
55
|
m_basicAuthPassword = password;
|
donatien |
0:7aca7353eebf
|
56
|
}
|
donatien |
0:7aca7353eebf
|
57
|
#endif
|
donatien |
0:7aca7353eebf
|
58
|
|
donatien |
0:7aca7353eebf
|
59
|
int HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, uint32_t timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
|
donatien |
0:7aca7353eebf
|
60
|
{
|
donatien |
0:7aca7353eebf
|
61
|
return connect(url, HTTP_GET, NULL, pDataIn, timeout);
|
donatien |
0:7aca7353eebf
|
62
|
}
|
donatien |
0:7aca7353eebf
|
63
|
|
donatien |
0:7aca7353eebf
|
64
|
int HTTPClient::get(const char* url, char* result, size_t maxResultLen, uint32_t timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
|
donatien |
0:7aca7353eebf
|
65
|
{
|
donatien |
0:7aca7353eebf
|
66
|
HTTPText str(result, maxResultLen);
|
donatien |
0:7aca7353eebf
|
67
|
return get(url, &str, timeout);
|
donatien |
0:7aca7353eebf
|
68
|
}
|
donatien |
0:7aca7353eebf
|
69
|
|
donatien |
0:7aca7353eebf
|
70
|
int HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, uint32_t timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
|
donatien |
0:7aca7353eebf
|
71
|
{
|
donatien |
0:7aca7353eebf
|
72
|
return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
|
donatien |
0:7aca7353eebf
|
73
|
}
|
donatien |
0:7aca7353eebf
|
74
|
|
donatien |
0:7aca7353eebf
|
75
|
int HTTPClient::getHTTPResponseCode()
|
donatien |
0:7aca7353eebf
|
76
|
{
|
donatien |
0:7aca7353eebf
|
77
|
return m_httpResponseCode;
|
donatien |
0:7aca7353eebf
|
78
|
}
|
donatien |
0:7aca7353eebf
|
79
|
|
donatien |
0:7aca7353eebf
|
80
|
|
donatien |
0:7aca7353eebf
|
81
|
int HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, uint32_t timeout) //Execute request
|
donatien |
0:7aca7353eebf
|
82
|
{
|
donatien |
0:7aca7353eebf
|
83
|
m_httpResponseCode = 0; //Invalidate code
|
donatien |
0:7aca7353eebf
|
84
|
m_timeout = timeout;
|
donatien |
0:7aca7353eebf
|
85
|
|
donatien |
0:7aca7353eebf
|
86
|
char scheme[8];
|
donatien |
0:7aca7353eebf
|
87
|
uint16_t port;
|
donatien |
0:7aca7353eebf
|
88
|
char host[32];
|
donatien |
0:7aca7353eebf
|
89
|
char path[64];
|
donatien |
0:7aca7353eebf
|
90
|
//First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?)
|
donatien |
0:7aca7353eebf
|
91
|
int ret = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
|
donatien |
0:7aca7353eebf
|
92
|
if(ret != OK)
|
donatien |
0:7aca7353eebf
|
93
|
{
|
donatien |
0:7aca7353eebf
|
94
|
ERR("parseURL returned %d", ret);
|
donatien |
0:7aca7353eebf
|
95
|
return ret;
|
donatien |
0:7aca7353eebf
|
96
|
}
|
donatien |
0:7aca7353eebf
|
97
|
|
donatien |
0:7aca7353eebf
|
98
|
if(port == 0) //TODO do handle HTTPS->443
|
donatien |
0:7aca7353eebf
|
99
|
{
|
donatien |
0:7aca7353eebf
|
100
|
port = 80;
|
donatien |
0:7aca7353eebf
|
101
|
}
|
donatien |
0:7aca7353eebf
|
102
|
|
donatien |
0:7aca7353eebf
|
103
|
DBG("Scheme: %s", scheme);
|
donatien |
0:7aca7353eebf
|
104
|
DBG("Host: %s", host);
|
donatien |
0:7aca7353eebf
|
105
|
DBG("Port: %d", port);
|
donatien |
0:7aca7353eebf
|
106
|
DBG("Path: %s", path);
|
donatien |
0:7aca7353eebf
|
107
|
|
donatien |
0:7aca7353eebf
|
108
|
//Now populate structure
|
donatien |
0:7aca7353eebf
|
109
|
std::memset(&m_serverAddr, 0, sizeof(struct sockaddr_in));
|
donatien |
0:7aca7353eebf
|
110
|
|
donatien |
0:7aca7353eebf
|
111
|
//Resolve DNS if needed
|
donatien |
0:7aca7353eebf
|
112
|
|
donatien |
0:7aca7353eebf
|
113
|
DBG("Resolving DNS address or populate hard-coded IP address");
|
donatien |
0:7aca7353eebf
|
114
|
struct hostent *server = socket::gethostbyname(host);
|
donatien |
0:7aca7353eebf
|
115
|
if(server == NULL)
|
donatien |
0:7aca7353eebf
|
116
|
{
|
donatien |
0:7aca7353eebf
|
117
|
return NET_NOTFOUND; //Fail
|
donatien |
0:7aca7353eebf
|
118
|
}
|
donatien |
0:7aca7353eebf
|
119
|
memcpy((char*)&m_serverAddr.sin_addr.s_addr, (char*)server->h_addr_list[0], server->h_length);
|
donatien |
0:7aca7353eebf
|
120
|
|
donatien |
0:7aca7353eebf
|
121
|
m_serverAddr.sin_family = AF_INET;
|
donatien |
0:7aca7353eebf
|
122
|
m_serverAddr.sin_port = htons(port);
|
donatien |
0:7aca7353eebf
|
123
|
|
donatien |
0:7aca7353eebf
|
124
|
//Create socket
|
donatien |
0:7aca7353eebf
|
125
|
DBG("Creating socket");
|
donatien |
0:7aca7353eebf
|
126
|
m_sock = socket::socket(AF_INET, SOCK_STREAM, 0); //UDP socket
|
donatien |
0:7aca7353eebf
|
127
|
if (m_sock < 0)
|
donatien |
0:7aca7353eebf
|
128
|
{
|
donatien |
0:7aca7353eebf
|
129
|
ERR("Could not create socket");
|
donatien |
0:7aca7353eebf
|
130
|
return NET_OOM;
|
donatien |
0:7aca7353eebf
|
131
|
}
|
donatien |
0:7aca7353eebf
|
132
|
DBG("Handle is %d", m_sock);
|
donatien |
0:7aca7353eebf
|
133
|
|
donatien |
0:7aca7353eebf
|
134
|
//Connect it
|
donatien |
0:7aca7353eebf
|
135
|
DBG("Connecting socket to %s:%d", inet_ntoa(m_serverAddr.sin_addr), ntohs(m_serverAddr.sin_port));
|
donatien |
0:7aca7353eebf
|
136
|
ret = socket::connect(m_sock, (const struct sockaddr *)&m_serverAddr, sizeof(m_serverAddr));
|
donatien |
0:7aca7353eebf
|
137
|
if (ret < 0)
|
donatien |
0:7aca7353eebf
|
138
|
{
|
donatien |
0:7aca7353eebf
|
139
|
socket::close(m_sock);
|
donatien |
0:7aca7353eebf
|
140
|
ERR("Could not connect");
|
donatien |
0:7aca7353eebf
|
141
|
return NET_CONN;
|
donatien |
0:7aca7353eebf
|
142
|
}
|
donatien |
0:7aca7353eebf
|
143
|
|
donatien |
0:7aca7353eebf
|
144
|
//Send request
|
donatien |
0:7aca7353eebf
|
145
|
DBG("Sending request");
|
donatien |
0:7aca7353eebf
|
146
|
char line[128];
|
donatien |
0:7aca7353eebf
|
147
|
const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":"";
|
donatien |
0:7aca7353eebf
|
148
|
snprintf(line, sizeof(line), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request
|
donatien |
0:7aca7353eebf
|
149
|
ret = send(line);
|
donatien |
0:7aca7353eebf
|
150
|
if(ret)
|
donatien |
0:7aca7353eebf
|
151
|
{
|
donatien |
0:7aca7353eebf
|
152
|
socket::close(m_sock);
|
donatien |
0:7aca7353eebf
|
153
|
ERR("Could not write request");
|
donatien |
0:7aca7353eebf
|
154
|
return NET_CONN;
|
donatien |
0:7aca7353eebf
|
155
|
}
|
donatien |
0:7aca7353eebf
|
156
|
|
donatien |
0:7aca7353eebf
|
157
|
//Send all headers
|
donatien |
0:7aca7353eebf
|
158
|
|
donatien |
0:7aca7353eebf
|
159
|
//Send default headers
|
donatien |
0:7aca7353eebf
|
160
|
DBG("Sending headers");
|
donatien |
0:7aca7353eebf
|
161
|
if( (method == HTTP_POST) && (pDataOut != NULL) )
|
donatien |
0:7aca7353eebf
|
162
|
{
|
donatien |
0:7aca7353eebf
|
163
|
if( pDataOut->getIsChunked() )
|
donatien |
0:7aca7353eebf
|
164
|
{
|
donatien |
0:7aca7353eebf
|
165
|
ret = send("Transfer-Encoding: chunked\r\n");
|
donatien |
0:7aca7353eebf
|
166
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
167
|
}
|
donatien |
0:7aca7353eebf
|
168
|
else
|
donatien |
0:7aca7353eebf
|
169
|
{
|
donatien |
0:7aca7353eebf
|
170
|
snprintf(line, sizeof(line), "Content-Length: %d\r\n", pDataOut->getDataLen());
|
donatien |
0:7aca7353eebf
|
171
|
ret = send(line);
|
donatien |
0:7aca7353eebf
|
172
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
173
|
}
|
donatien |
0:7aca7353eebf
|
174
|
char type[48];
|
donatien |
0:7aca7353eebf
|
175
|
if( pDataOut->getDataType(type, 48) == OK )
|
donatien |
0:7aca7353eebf
|
176
|
{
|
donatien |
0:7aca7353eebf
|
177
|
snprintf(line, sizeof(line), "Content-Type: %s\r\n", type);
|
donatien |
0:7aca7353eebf
|
178
|
ret = send(line);
|
donatien |
0:7aca7353eebf
|
179
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
180
|
}
|
donatien |
0:7aca7353eebf
|
181
|
}
|
donatien |
0:7aca7353eebf
|
182
|
|
donatien |
0:7aca7353eebf
|
183
|
//Close headers
|
donatien |
0:7aca7353eebf
|
184
|
DBG("Headers sent");
|
donatien |
0:7aca7353eebf
|
185
|
ret = send("\r\n");
|
donatien |
0:7aca7353eebf
|
186
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
187
|
|
donatien |
0:7aca7353eebf
|
188
|
char buf[CHUNK_SIZE];
|
donatien |
0:7aca7353eebf
|
189
|
size_t trfLen;
|
donatien |
0:7aca7353eebf
|
190
|
|
donatien |
0:7aca7353eebf
|
191
|
//Send data (if POST)
|
donatien |
0:7aca7353eebf
|
192
|
if( (method == HTTP_POST) && (pDataOut != NULL) )
|
donatien |
0:7aca7353eebf
|
193
|
{
|
donatien |
0:7aca7353eebf
|
194
|
DBG("Sending data");
|
donatien |
0:7aca7353eebf
|
195
|
while(true)
|
donatien |
0:7aca7353eebf
|
196
|
{
|
donatien |
0:7aca7353eebf
|
197
|
size_t writtenLen = 0;
|
donatien |
0:7aca7353eebf
|
198
|
pDataOut->read(buf, CHUNK_SIZE, &trfLen);
|
donatien |
0:7aca7353eebf
|
199
|
if( pDataOut->getIsChunked() )
|
donatien |
0:7aca7353eebf
|
200
|
{
|
donatien |
0:7aca7353eebf
|
201
|
//Write chunk header
|
donatien |
0:7aca7353eebf
|
202
|
snprintf(line, sizeof(line), "%X\r\n", trfLen); //In hex encoding
|
donatien |
0:7aca7353eebf
|
203
|
ret = send(line);
|
donatien |
0:7aca7353eebf
|
204
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
205
|
}
|
donatien |
0:7aca7353eebf
|
206
|
else if( trfLen == 0 )
|
donatien |
0:7aca7353eebf
|
207
|
{
|
donatien |
0:7aca7353eebf
|
208
|
break;
|
donatien |
0:7aca7353eebf
|
209
|
}
|
donatien |
0:7aca7353eebf
|
210
|
if( trfLen != 0 )
|
donatien |
0:7aca7353eebf
|
211
|
{
|
donatien |
0:7aca7353eebf
|
212
|
ret = send(buf, trfLen);
|
donatien |
0:7aca7353eebf
|
213
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
214
|
}
|
donatien |
0:7aca7353eebf
|
215
|
|
donatien |
0:7aca7353eebf
|
216
|
if( pDataOut->getIsChunked() )
|
donatien |
0:7aca7353eebf
|
217
|
{
|
donatien |
0:7aca7353eebf
|
218
|
ret = send("\r\n"); //Chunk-terminating CRLF
|
donatien |
0:7aca7353eebf
|
219
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
220
|
}
|
donatien |
0:7aca7353eebf
|
221
|
else
|
donatien |
0:7aca7353eebf
|
222
|
{
|
donatien |
0:7aca7353eebf
|
223
|
writtenLen += trfLen;
|
donatien |
0:7aca7353eebf
|
224
|
if( writtenLen >= pDataOut->getDataLen() )
|
donatien |
0:7aca7353eebf
|
225
|
{
|
donatien |
0:7aca7353eebf
|
226
|
break;
|
donatien |
0:7aca7353eebf
|
227
|
}
|
donatien |
0:7aca7353eebf
|
228
|
}
|
donatien |
0:7aca7353eebf
|
229
|
|
donatien |
0:7aca7353eebf
|
230
|
if( trfLen == 0 )
|
donatien |
0:7aca7353eebf
|
231
|
{
|
donatien |
0:7aca7353eebf
|
232
|
break;
|
donatien |
0:7aca7353eebf
|
233
|
}
|
donatien |
0:7aca7353eebf
|
234
|
}
|
donatien |
0:7aca7353eebf
|
235
|
|
donatien |
0:7aca7353eebf
|
236
|
}
|
donatien |
0:7aca7353eebf
|
237
|
|
donatien |
0:7aca7353eebf
|
238
|
//Receive response
|
donatien |
0:7aca7353eebf
|
239
|
DBG("Receiving response");
|
donatien |
0:7aca7353eebf
|
240
|
ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
|
donatien |
0:7aca7353eebf
|
241
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
242
|
|
donatien |
0:7aca7353eebf
|
243
|
buf[trfLen] = '\0';
|
donatien |
0:7aca7353eebf
|
244
|
|
donatien |
0:7aca7353eebf
|
245
|
char* crlfPtr = strstr(buf, "\r\n");
|
donatien |
0:7aca7353eebf
|
246
|
if(crlfPtr == NULL)
|
donatien |
0:7aca7353eebf
|
247
|
{
|
donatien |
0:7aca7353eebf
|
248
|
goto prtclerr;
|
donatien |
0:7aca7353eebf
|
249
|
}
|
donatien |
0:7aca7353eebf
|
250
|
|
donatien |
0:7aca7353eebf
|
251
|
int crlfPos = crlfPtr - buf;
|
donatien |
0:7aca7353eebf
|
252
|
buf[crlfPos] = '\0';
|
donatien |
0:7aca7353eebf
|
253
|
|
donatien |
0:7aca7353eebf
|
254
|
//Parse HTTP response
|
donatien |
0:7aca7353eebf
|
255
|
if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 )
|
donatien |
0:7aca7353eebf
|
256
|
{
|
donatien |
0:7aca7353eebf
|
257
|
//Cannot match string, error
|
donatien |
0:7aca7353eebf
|
258
|
ERR("Not a correct HTTP answer : %s\n", buf);
|
donatien |
0:7aca7353eebf
|
259
|
goto prtclerr;
|
donatien |
0:7aca7353eebf
|
260
|
}
|
donatien |
0:7aca7353eebf
|
261
|
|
donatien |
0:7aca7353eebf
|
262
|
if(m_httpResponseCode != 200)
|
donatien |
0:7aca7353eebf
|
263
|
{
|
donatien |
0:7aca7353eebf
|
264
|
//Cannot match string, error
|
donatien |
0:7aca7353eebf
|
265
|
WARN("Response code %d", m_httpResponseCode);
|
donatien |
0:7aca7353eebf
|
266
|
goto prtclerr;
|
donatien |
0:7aca7353eebf
|
267
|
}
|
donatien |
0:7aca7353eebf
|
268
|
|
donatien |
0:7aca7353eebf
|
269
|
DBG("Reading headers");
|
donatien |
0:7aca7353eebf
|
270
|
|
donatien |
0:7aca7353eebf
|
271
|
memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
|
donatien |
0:7aca7353eebf
|
272
|
trfLen -= (crlfPos + 2);
|
donatien |
0:7aca7353eebf
|
273
|
|
donatien |
0:7aca7353eebf
|
274
|
size_t recvContentLength = 0;
|
donatien |
0:7aca7353eebf
|
275
|
bool recvChunked = false;
|
donatien |
0:7aca7353eebf
|
276
|
//Now get headers
|
donatien |
0:7aca7353eebf
|
277
|
while( true )
|
donatien |
0:7aca7353eebf
|
278
|
{
|
donatien |
0:7aca7353eebf
|
279
|
crlfPtr = strstr(buf, "\r\n");
|
donatien |
0:7aca7353eebf
|
280
|
if(crlfPtr == NULL)
|
donatien |
0:7aca7353eebf
|
281
|
{
|
donatien |
0:7aca7353eebf
|
282
|
if( trfLen < CHUNK_SIZE - 1 )
|
donatien |
0:7aca7353eebf
|
283
|
{
|
donatien |
0:7aca7353eebf
|
284
|
size_t newTrfLen;
|
donatien |
0:7aca7353eebf
|
285
|
ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
|
donatien |
0:7aca7353eebf
|
286
|
trfLen += newTrfLen;
|
donatien |
0:7aca7353eebf
|
287
|
buf[trfLen] = '\0';
|
donatien |
0:7aca7353eebf
|
288
|
DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
|
donatien |
0:7aca7353eebf
|
289
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
290
|
continue;
|
donatien |
0:7aca7353eebf
|
291
|
}
|
donatien |
0:7aca7353eebf
|
292
|
else
|
donatien |
0:7aca7353eebf
|
293
|
{
|
donatien |
0:7aca7353eebf
|
294
|
goto prtclerr;
|
donatien |
0:7aca7353eebf
|
295
|
}
|
donatien |
0:7aca7353eebf
|
296
|
}
|
donatien |
0:7aca7353eebf
|
297
|
|
donatien |
0:7aca7353eebf
|
298
|
crlfPos = crlfPtr - buf;
|
donatien |
0:7aca7353eebf
|
299
|
|
donatien |
0:7aca7353eebf
|
300
|
if(crlfPos == 0) //End of headers
|
donatien |
0:7aca7353eebf
|
301
|
{
|
donatien |
0:7aca7353eebf
|
302
|
DBG("Headers read");
|
donatien |
0:7aca7353eebf
|
303
|
memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
|
donatien |
0:7aca7353eebf
|
304
|
trfLen -= 2;
|
donatien |
0:7aca7353eebf
|
305
|
break;
|
donatien |
0:7aca7353eebf
|
306
|
}
|
donatien |
0:7aca7353eebf
|
307
|
|
donatien |
0:7aca7353eebf
|
308
|
buf[crlfPos] = '\0';
|
donatien |
0:7aca7353eebf
|
309
|
|
donatien |
0:7aca7353eebf
|
310
|
char key[32];
|
donatien |
0:7aca7353eebf
|
311
|
char value[32];
|
donatien |
0:7aca7353eebf
|
312
|
|
donatien |
0:7aca7353eebf
|
313
|
key[31] = '\0';
|
donatien |
0:7aca7353eebf
|
314
|
value[31] = '\0';
|
donatien |
0:7aca7353eebf
|
315
|
|
donatien |
0:7aca7353eebf
|
316
|
int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
|
donatien |
0:7aca7353eebf
|
317
|
if ( n == 2 )
|
donatien |
0:7aca7353eebf
|
318
|
{
|
donatien |
0:7aca7353eebf
|
319
|
DBG("Read header : %s: %s\n", key, value);
|
donatien |
0:7aca7353eebf
|
320
|
if( !strcmp(key, "Content-Length") )
|
donatien |
0:7aca7353eebf
|
321
|
{
|
donatien |
0:7aca7353eebf
|
322
|
sscanf(value, "%d", &recvContentLength);
|
donatien |
0:7aca7353eebf
|
323
|
pDataIn->setDataLen(recvContentLength);
|
donatien |
0:7aca7353eebf
|
324
|
}
|
donatien |
0:7aca7353eebf
|
325
|
else if( !strcmp(key, "Transfer-Encoding") )
|
donatien |
0:7aca7353eebf
|
326
|
{
|
donatien |
0:7aca7353eebf
|
327
|
if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") )
|
donatien |
0:7aca7353eebf
|
328
|
{
|
donatien |
0:7aca7353eebf
|
329
|
recvChunked = true;
|
donatien |
0:7aca7353eebf
|
330
|
pDataIn->setIsChunked(true);
|
donatien |
0:7aca7353eebf
|
331
|
}
|
donatien |
0:7aca7353eebf
|
332
|
}
|
donatien |
0:7aca7353eebf
|
333
|
else if( !strcmp(key, "Content-Type") )
|
donatien |
0:7aca7353eebf
|
334
|
{
|
donatien |
0:7aca7353eebf
|
335
|
pDataIn->setDataType(value);
|
donatien |
0:7aca7353eebf
|
336
|
}
|
donatien |
0:7aca7353eebf
|
337
|
|
donatien |
0:7aca7353eebf
|
338
|
memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
|
donatien |
0:7aca7353eebf
|
339
|
trfLen -= (crlfPos + 2);
|
donatien |
0:7aca7353eebf
|
340
|
|
donatien |
0:7aca7353eebf
|
341
|
}
|
donatien |
0:7aca7353eebf
|
342
|
else
|
donatien |
0:7aca7353eebf
|
343
|
{
|
donatien |
0:7aca7353eebf
|
344
|
ERR("Could not parse header");
|
donatien |
0:7aca7353eebf
|
345
|
goto prtclerr;
|
donatien |
0:7aca7353eebf
|
346
|
}
|
donatien |
0:7aca7353eebf
|
347
|
|
donatien |
0:7aca7353eebf
|
348
|
}
|
donatien |
0:7aca7353eebf
|
349
|
|
donatien |
0:7aca7353eebf
|
350
|
//Receive data
|
donatien |
0:7aca7353eebf
|
351
|
DBG("Receiving data");
|
donatien |
0:7aca7353eebf
|
352
|
while(true)
|
donatien |
0:7aca7353eebf
|
353
|
{
|
donatien |
0:7aca7353eebf
|
354
|
size_t readLen = 0;
|
donatien |
0:7aca7353eebf
|
355
|
|
donatien |
0:7aca7353eebf
|
356
|
if( recvChunked )
|
donatien |
0:7aca7353eebf
|
357
|
{
|
donatien |
0:7aca7353eebf
|
358
|
//Read chunk header
|
donatien |
0:7aca7353eebf
|
359
|
crlfPos=0;
|
donatien |
0:7aca7353eebf
|
360
|
for(crlfPos++; crlfPos < trfLen - 2; crlfPos++)
|
donatien |
0:7aca7353eebf
|
361
|
{
|
donatien |
0:7aca7353eebf
|
362
|
if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' )
|
donatien |
0:7aca7353eebf
|
363
|
{
|
donatien |
0:7aca7353eebf
|
364
|
break;
|
donatien |
0:7aca7353eebf
|
365
|
}
|
donatien |
0:7aca7353eebf
|
366
|
}
|
donatien |
0:7aca7353eebf
|
367
|
if(crlfPos >= trfLen - 2) //Try to read more
|
donatien |
0:7aca7353eebf
|
368
|
{
|
donatien |
0:7aca7353eebf
|
369
|
if( trfLen < CHUNK_SIZE )
|
donatien |
0:7aca7353eebf
|
370
|
{
|
donatien |
0:7aca7353eebf
|
371
|
size_t newTrfLen;
|
donatien |
0:7aca7353eebf
|
372
|
ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
|
donatien |
0:7aca7353eebf
|
373
|
trfLen += newTrfLen;
|
donatien |
0:7aca7353eebf
|
374
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
375
|
continue;
|
donatien |
0:7aca7353eebf
|
376
|
}
|
donatien |
0:7aca7353eebf
|
377
|
else
|
donatien |
0:7aca7353eebf
|
378
|
{
|
donatien |
0:7aca7353eebf
|
379
|
goto prtclerr;
|
donatien |
0:7aca7353eebf
|
380
|
}
|
donatien |
0:7aca7353eebf
|
381
|
}
|
donatien |
0:7aca7353eebf
|
382
|
buf[crlfPos] = '\0';
|
donatien |
0:7aca7353eebf
|
383
|
int n = sscanf(buf, "%x", &readLen);
|
donatien |
0:7aca7353eebf
|
384
|
if(n!=1)
|
donatien |
0:7aca7353eebf
|
385
|
{
|
donatien |
0:7aca7353eebf
|
386
|
ERR("Could not read chunk length");
|
donatien |
0:7aca7353eebf
|
387
|
goto prtclerr;
|
donatien |
0:7aca7353eebf
|
388
|
}
|
donatien |
0:7aca7353eebf
|
389
|
|
donatien |
0:7aca7353eebf
|
390
|
memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
|
donatien |
0:7aca7353eebf
|
391
|
trfLen -= (crlfPos + 2);
|
donatien |
0:7aca7353eebf
|
392
|
|
donatien |
0:7aca7353eebf
|
393
|
if( readLen == 0 )
|
donatien |
0:7aca7353eebf
|
394
|
{
|
donatien |
0:7aca7353eebf
|
395
|
//Last chunk
|
donatien |
0:7aca7353eebf
|
396
|
break;
|
donatien |
0:7aca7353eebf
|
397
|
}
|
donatien |
0:7aca7353eebf
|
398
|
}
|
donatien |
0:7aca7353eebf
|
399
|
else
|
donatien |
0:7aca7353eebf
|
400
|
{
|
donatien |
0:7aca7353eebf
|
401
|
readLen = recvContentLength;
|
donatien |
0:7aca7353eebf
|
402
|
}
|
donatien |
0:7aca7353eebf
|
403
|
|
donatien |
0:7aca7353eebf
|
404
|
DBG("Retrieving %d bytes", readLen);
|
donatien |
0:7aca7353eebf
|
405
|
|
donatien |
0:7aca7353eebf
|
406
|
do
|
donatien |
0:7aca7353eebf
|
407
|
{
|
donatien |
0:7aca7353eebf
|
408
|
pDataIn->write(buf, MIN(trfLen, readLen));
|
donatien |
0:7aca7353eebf
|
409
|
if( trfLen > readLen )
|
donatien |
0:7aca7353eebf
|
410
|
{
|
donatien |
0:7aca7353eebf
|
411
|
memmove(buf, &buf[readLen], trfLen - readLen);
|
donatien |
0:7aca7353eebf
|
412
|
trfLen -= readLen;
|
donatien |
0:7aca7353eebf
|
413
|
readLen = 0;
|
donatien |
0:7aca7353eebf
|
414
|
}
|
donatien |
0:7aca7353eebf
|
415
|
else
|
donatien |
0:7aca7353eebf
|
416
|
{
|
donatien |
0:7aca7353eebf
|
417
|
readLen -= trfLen;
|
donatien |
0:7aca7353eebf
|
418
|
}
|
donatien |
0:7aca7353eebf
|
419
|
|
donatien |
0:7aca7353eebf
|
420
|
if(readLen)
|
donatien |
0:7aca7353eebf
|
421
|
{
|
donatien |
0:7aca7353eebf
|
422
|
ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
|
donatien |
0:7aca7353eebf
|
423
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
424
|
}
|
donatien |
0:7aca7353eebf
|
425
|
} while(readLen);
|
donatien |
0:7aca7353eebf
|
426
|
|
donatien |
0:7aca7353eebf
|
427
|
if( recvChunked )
|
donatien |
0:7aca7353eebf
|
428
|
{
|
donatien |
0:7aca7353eebf
|
429
|
if(trfLen < 2)
|
donatien |
0:7aca7353eebf
|
430
|
{
|
donatien |
0:7aca7353eebf
|
431
|
size_t newTrfLen;
|
donatien |
0:7aca7353eebf
|
432
|
//Read missing chars to find end of chunk
|
donatien |
0:7aca7353eebf
|
433
|
ret = recv(buf, 2 - trfLen, CHUNK_SIZE, &newTrfLen);
|
donatien |
0:7aca7353eebf
|
434
|
if(ret != OK) goto connerr;
|
donatien |
0:7aca7353eebf
|
435
|
trfLen += newTrfLen;
|
donatien |
0:7aca7353eebf
|
436
|
}
|
donatien |
0:7aca7353eebf
|
437
|
if( (buf[0] != '\r') || (buf[1] != '\n') )
|
donatien |
0:7aca7353eebf
|
438
|
{
|
donatien |
0:7aca7353eebf
|
439
|
ERR("Format error");
|
donatien |
0:7aca7353eebf
|
440
|
goto prtclerr;
|
donatien |
0:7aca7353eebf
|
441
|
}
|
donatien |
0:7aca7353eebf
|
442
|
memmove(buf, &buf[2], trfLen - 2);
|
donatien |
0:7aca7353eebf
|
443
|
trfLen -= 2;
|
donatien |
0:7aca7353eebf
|
444
|
}
|
donatien |
0:7aca7353eebf
|
445
|
else
|
donatien |
0:7aca7353eebf
|
446
|
{
|
donatien |
0:7aca7353eebf
|
447
|
break;
|
donatien |
0:7aca7353eebf
|
448
|
}
|
donatien |
0:7aca7353eebf
|
449
|
|
donatien |
0:7aca7353eebf
|
450
|
}
|
donatien |
0:7aca7353eebf
|
451
|
|
donatien |
0:7aca7353eebf
|
452
|
socket::close(m_sock);
|
donatien |
0:7aca7353eebf
|
453
|
DBG("Completed HTTP transaction");
|
donatien |
0:7aca7353eebf
|
454
|
|
donatien |
0:7aca7353eebf
|
455
|
return OK;
|
donatien |
0:7aca7353eebf
|
456
|
|
donatien |
0:7aca7353eebf
|
457
|
connerr:
|
donatien |
0:7aca7353eebf
|
458
|
socket::close(m_sock);
|
donatien |
0:7aca7353eebf
|
459
|
ERR("Connection error (%d)", ret);
|
donatien |
0:7aca7353eebf
|
460
|
return NET_CONN;
|
donatien |
0:7aca7353eebf
|
461
|
|
donatien |
0:7aca7353eebf
|
462
|
prtclerr:
|
donatien |
0:7aca7353eebf
|
463
|
socket::close(m_sock);
|
donatien |
0:7aca7353eebf
|
464
|
ERR("Protocol error");
|
donatien |
0:7aca7353eebf
|
465
|
return NET_PROTOCOL;
|
donatien |
0:7aca7353eebf
|
466
|
|
donatien |
0:7aca7353eebf
|
467
|
}
|
donatien |
0:7aca7353eebf
|
468
|
|
donatien |
0:7aca7353eebf
|
469
|
int HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure
|
donatien |
0:7aca7353eebf
|
470
|
{
|
donatien |
0:7aca7353eebf
|
471
|
DBG("Trying to read between %d and %d bytes", minLen, maxLen);
|
donatien |
0:7aca7353eebf
|
472
|
size_t readLen = 0;
|
donatien |
0:7aca7353eebf
|
473
|
while(readLen < minLen)
|
donatien |
0:7aca7353eebf
|
474
|
{
|
donatien |
0:7aca7353eebf
|
475
|
//Wait for socket to be readable
|
donatien |
0:7aca7353eebf
|
476
|
//Creating FS set
|
donatien |
0:7aca7353eebf
|
477
|
fd_set socksSet;
|
donatien |
0:7aca7353eebf
|
478
|
FD_ZERO(&socksSet);
|
donatien |
0:7aca7353eebf
|
479
|
FD_SET(m_sock, &socksSet);
|
donatien |
0:7aca7353eebf
|
480
|
struct timeval t_val;
|
donatien |
0:7aca7353eebf
|
481
|
t_val.tv_sec = m_timeout / 1000;
|
donatien |
0:7aca7353eebf
|
482
|
t_val.tv_usec = (m_timeout - (t_val.tv_sec * 1000)) * 1000;
|
donatien |
0:7aca7353eebf
|
483
|
int ret = socket::select(FD_SETSIZE, &socksSet, NULL, NULL, &t_val);
|
donatien |
0:7aca7353eebf
|
484
|
if(ret <= 0 || !FD_ISSET(m_sock, &socksSet))
|
donatien |
0:7aca7353eebf
|
485
|
{
|
donatien |
0:7aca7353eebf
|
486
|
WARN("Timeout");
|
donatien |
0:7aca7353eebf
|
487
|
return NET_TIMEOUT; //Timeout
|
donatien |
0:7aca7353eebf
|
488
|
}
|
donatien |
0:7aca7353eebf
|
489
|
|
donatien |
0:7aca7353eebf
|
490
|
ret = socket::recv(m_sock, buf + readLen, maxLen - readLen, 0);
|
donatien |
0:7aca7353eebf
|
491
|
if( ret > 0)
|
donatien |
0:7aca7353eebf
|
492
|
{
|
donatien |
0:7aca7353eebf
|
493
|
readLen += ret;
|
donatien |
0:7aca7353eebf
|
494
|
continue;
|
donatien |
0:7aca7353eebf
|
495
|
}
|
donatien |
0:7aca7353eebf
|
496
|
else if( ret == 0 )
|
donatien |
0:7aca7353eebf
|
497
|
{
|
donatien |
0:7aca7353eebf
|
498
|
WARN("Connection was closed by server");
|
donatien |
0:7aca7353eebf
|
499
|
return NET_CLOSED; //Connection was closed by server
|
donatien |
0:7aca7353eebf
|
500
|
}
|
donatien |
0:7aca7353eebf
|
501
|
else
|
donatien |
0:7aca7353eebf
|
502
|
{
|
donatien |
0:7aca7353eebf
|
503
|
ERR("Connection error (recv returned %d)", ret);
|
donatien |
0:7aca7353eebf
|
504
|
return NET_CONN;
|
donatien |
0:7aca7353eebf
|
505
|
}
|
donatien |
0:7aca7353eebf
|
506
|
}
|
donatien |
0:7aca7353eebf
|
507
|
*pReadLen = readLen;
|
donatien |
0:7aca7353eebf
|
508
|
DBG("Read %d bytes", readLen);
|
donatien |
0:7aca7353eebf
|
509
|
return OK;
|
donatien |
0:7aca7353eebf
|
510
|
}
|
donatien |
0:7aca7353eebf
|
511
|
|
donatien |
0:7aca7353eebf
|
512
|
int HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure
|
donatien |
0:7aca7353eebf
|
513
|
{
|
donatien |
0:7aca7353eebf
|
514
|
if(len == 0)
|
donatien |
0:7aca7353eebf
|
515
|
{
|
donatien |
0:7aca7353eebf
|
516
|
len = strlen(buf);
|
donatien |
0:7aca7353eebf
|
517
|
}
|
donatien |
0:7aca7353eebf
|
518
|
DBG("Trying to write %d bytes", len);
|
donatien |
0:7aca7353eebf
|
519
|
size_t writtenLen = 0;
|
donatien |
0:7aca7353eebf
|
520
|
while(writtenLen < len)
|
donatien |
0:7aca7353eebf
|
521
|
{
|
donatien |
0:7aca7353eebf
|
522
|
//Wait for socket to be writeable
|
donatien |
0:7aca7353eebf
|
523
|
//Creating FS set
|
donatien |
0:7aca7353eebf
|
524
|
fd_set socksSet;
|
donatien |
0:7aca7353eebf
|
525
|
FD_ZERO(&socksSet);
|
donatien |
0:7aca7353eebf
|
526
|
FD_SET(m_sock, &socksSet);
|
donatien |
0:7aca7353eebf
|
527
|
struct timeval t_val;
|
donatien |
0:7aca7353eebf
|
528
|
t_val.tv_sec = m_timeout / 1000;
|
donatien |
0:7aca7353eebf
|
529
|
t_val.tv_usec = (m_timeout - (t_val.tv_sec * 1000)) * 1000;
|
donatien |
0:7aca7353eebf
|
530
|
int ret = socket::select(FD_SETSIZE, NULL, &socksSet, NULL, &t_val);
|
donatien |
0:7aca7353eebf
|
531
|
if(ret <= 0 || !FD_ISSET(m_sock, &socksSet))
|
donatien |
0:7aca7353eebf
|
532
|
{
|
donatien |
0:7aca7353eebf
|
533
|
WARN("Timeout");
|
donatien |
0:7aca7353eebf
|
534
|
return NET_TIMEOUT; //Timeout
|
donatien |
0:7aca7353eebf
|
535
|
}
|
donatien |
0:7aca7353eebf
|
536
|
|
donatien |
0:7aca7353eebf
|
537
|
ret = socket::send(m_sock, buf + writtenLen, len - writtenLen, 0);
|
donatien |
0:7aca7353eebf
|
538
|
if( ret > 0)
|
donatien |
0:7aca7353eebf
|
539
|
{
|
donatien |
0:7aca7353eebf
|
540
|
writtenLen += ret;
|
donatien |
0:7aca7353eebf
|
541
|
continue;
|
donatien |
0:7aca7353eebf
|
542
|
}
|
donatien |
0:7aca7353eebf
|
543
|
else if( ret == 0 )
|
donatien |
0:7aca7353eebf
|
544
|
{
|
donatien |
0:7aca7353eebf
|
545
|
WARN("Connection was closed by server");
|
donatien |
0:7aca7353eebf
|
546
|
return NET_CLOSED; //Connection was closed by server
|
donatien |
0:7aca7353eebf
|
547
|
}
|
donatien |
0:7aca7353eebf
|
548
|
else
|
donatien |
0:7aca7353eebf
|
549
|
{
|
donatien |
0:7aca7353eebf
|
550
|
ERR("Connection error (recv returned %d)", ret);
|
donatien |
0:7aca7353eebf
|
551
|
return NET_CONN;
|
donatien |
0:7aca7353eebf
|
552
|
}
|
donatien |
0:7aca7353eebf
|
553
|
}
|
donatien |
0:7aca7353eebf
|
554
|
DBG("Written %d bytes", writtenLen);
|
donatien |
0:7aca7353eebf
|
555
|
return OK;
|
donatien |
0:7aca7353eebf
|
556
|
}
|
donatien |
0:7aca7353eebf
|
557
|
|
donatien |
0:7aca7353eebf
|
558
|
int HTTPClient::parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen) //Parse URL
|
donatien |
0:7aca7353eebf
|
559
|
{
|
donatien |
0:7aca7353eebf
|
560
|
char* schemePtr = (char*) url;
|
donatien |
0:7aca7353eebf
|
561
|
char* hostPtr = (char*) strstr(url, "://");
|
donatien |
0:7aca7353eebf
|
562
|
if(hostPtr == NULL)
|
donatien |
0:7aca7353eebf
|
563
|
{
|
donatien |
0:7aca7353eebf
|
564
|
WARN("Could not find host");
|
donatien |
0:7aca7353eebf
|
565
|
return NET_INVALID; //URL is invalid
|
donatien |
0:7aca7353eebf
|
566
|
}
|
donatien |
0:7aca7353eebf
|
567
|
|
donatien |
0:7aca7353eebf
|
568
|
if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char
|
donatien |
0:7aca7353eebf
|
569
|
{
|
donatien |
0:7aca7353eebf
|
570
|
WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
|
donatien |
0:7aca7353eebf
|
571
|
return NET_TOOSMALL;
|
donatien |
0:7aca7353eebf
|
572
|
}
|
donatien |
0:7aca7353eebf
|
573
|
memcpy(scheme, schemePtr, hostPtr - schemePtr);
|
donatien |
0:7aca7353eebf
|
574
|
scheme[hostPtr - schemePtr] = '\0';
|
donatien |
0:7aca7353eebf
|
575
|
|
donatien |
0:7aca7353eebf
|
576
|
hostPtr+=3;
|
donatien |
0:7aca7353eebf
|
577
|
|
donatien |
0:7aca7353eebf
|
578
|
size_t hostLen = 0;
|
donatien |
0:7aca7353eebf
|
579
|
|
donatien |
0:7aca7353eebf
|
580
|
char* portPtr = strchr(hostPtr, ':');
|
donatien |
0:7aca7353eebf
|
581
|
if( portPtr != NULL )
|
donatien |
0:7aca7353eebf
|
582
|
{
|
donatien |
0:7aca7353eebf
|
583
|
hostLen = portPtr - hostPtr;
|
donatien |
0:7aca7353eebf
|
584
|
portPtr++;
|
donatien |
0:7aca7353eebf
|
585
|
if( sscanf(portPtr, "%hu", port) != 1)
|
donatien |
0:7aca7353eebf
|
586
|
{
|
donatien |
0:7aca7353eebf
|
587
|
WARN("Could not find port");
|
donatien |
0:7aca7353eebf
|
588
|
return NET_INVALID;
|
donatien |
0:7aca7353eebf
|
589
|
}
|
donatien |
0:7aca7353eebf
|
590
|
}
|
donatien |
0:7aca7353eebf
|
591
|
else
|
donatien |
0:7aca7353eebf
|
592
|
{
|
donatien |
0:7aca7353eebf
|
593
|
*port=0;
|
donatien |
0:7aca7353eebf
|
594
|
}
|
donatien |
0:7aca7353eebf
|
595
|
char* pathPtr = strchr(hostPtr, '/');
|
donatien |
0:7aca7353eebf
|
596
|
if( hostLen == 0 )
|
donatien |
0:7aca7353eebf
|
597
|
{
|
donatien |
0:7aca7353eebf
|
598
|
hostLen = pathPtr - hostPtr;
|
donatien |
0:7aca7353eebf
|
599
|
}
|
donatien |
0:7aca7353eebf
|
600
|
|
donatien |
0:7aca7353eebf
|
601
|
if( maxHostLen < hostLen + 1 ) //including NULL-terminating char
|
donatien |
0:7aca7353eebf
|
602
|
{
|
donatien |
0:7aca7353eebf
|
603
|
WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
|
donatien |
0:7aca7353eebf
|
604
|
return NET_TOOSMALL;
|
donatien |
0:7aca7353eebf
|
605
|
}
|
donatien |
0:7aca7353eebf
|
606
|
memcpy(host, hostPtr, hostLen);
|
donatien |
0:7aca7353eebf
|
607
|
host[hostLen] = '\0';
|
donatien |
0:7aca7353eebf
|
608
|
|
donatien |
0:7aca7353eebf
|
609
|
size_t pathLen;
|
donatien |
0:7aca7353eebf
|
610
|
char* fragmentPtr = strchr(hostPtr, '#');
|
donatien |
0:7aca7353eebf
|
611
|
if(fragmentPtr != NULL)
|
donatien |
0:7aca7353eebf
|
612
|
{
|
donatien |
0:7aca7353eebf
|
613
|
pathLen = fragmentPtr - pathPtr;
|
donatien |
0:7aca7353eebf
|
614
|
}
|
donatien |
0:7aca7353eebf
|
615
|
else
|
donatien |
0:7aca7353eebf
|
616
|
{
|
donatien |
0:7aca7353eebf
|
617
|
pathLen = strlen(pathPtr);
|
donatien |
0:7aca7353eebf
|
618
|
}
|
donatien |
0:7aca7353eebf
|
619
|
|
donatien |
0:7aca7353eebf
|
620
|
if( maxPathLen < pathLen + 1 ) //including NULL-terminating char
|
donatien |
0:7aca7353eebf
|
621
|
{
|
donatien |
0:7aca7353eebf
|
622
|
WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
|
donatien |
0:7aca7353eebf
|
623
|
return NET_TOOSMALL;
|
donatien |
0:7aca7353eebf
|
624
|
}
|
donatien |
0:7aca7353eebf
|
625
|
memcpy(path, pathPtr, pathLen);
|
donatien |
0:7aca7353eebf
|
626
|
path[pathLen] = '\0';
|
donatien |
0:7aca7353eebf
|
627
|
|
donatien |
0:7aca7353eebf
|
628
|
return OK;
|
donatien |
0:7aca7353eebf
|
629
|
}
|