SOAPの為に修正します。
Dependents: temp_FIAP temp_FIAP_fetch tepco_demand BlueUSB_f_IEEE1888 ... more
Fork of HTTPClient by
HTTPClient.cpp
00001 /* HTTPClient.cpp */ 00002 /* Copyright (C) 2012 mbed.org, MIT License 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00005 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00006 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00007 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all copies or 00011 * substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00018 */ 00019 00020 //Debug is disabled by default 00021 #if 1 00022 //Enable debug 00023 #include <cstdio> 00024 //#define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 00025 #define DBG(x, ...) 00026 #define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 00027 #define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 00028 00029 #else 00030 //Disable debug 00031 #define DBG(x, ...) 00032 #define WARN(x, ...) 00033 #define ERR(x, ...) 00034 00035 #endif 00036 00037 #define HTTP_PORT 80 00038 00039 #define OK 0 00040 00041 #define MIN(x,y) (((x)<(y))?(x):(y)) 00042 #define MAX(x,y) (((x)>(y))?(x):(y)) 00043 00044 #define CHUNK_SIZE 256 00045 00046 #include <cstring> 00047 00048 #include "HTTPClient.h" 00049 00050 HTTPClient::HTTPClient() : 00051 m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0) 00052 { 00053 00054 } 00055 00056 HTTPClient::~HTTPClient() 00057 { 00058 00059 } 00060 00061 #if 0 00062 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification 00063 { 00064 m_basicAuthUser = user; 00065 m_basicAuthPassword = password; 00066 } 00067 #endif 00068 00069 HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00070 { 00071 return connect(url, HTTP_GET, NULL, pDataIn, timeout); 00072 } 00073 00074 HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00075 { 00076 HTTPText str(result, maxResultLen); 00077 return get(url, &str, timeout); 00078 } 00079 00080 HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00081 { 00082 return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout); 00083 } 00084 00085 HTTPResult HTTPClient::postXML(const char* url,const char* SOAPAction, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00086 { 00087 return connect(url, HTTP_POST, SOAPAction, (IHTTPDataOut*)&dataOut, pDataIn, timeout); 00088 } 00089 00090 int HTTPClient::getHTTPResponseCode() 00091 { 00092 return m_httpResponseCode; 00093 } 00094 00095 #define CHECK_CONN_ERR(ret) \ 00096 do{ \ 00097 if(ret) { \ 00098 m_sock.close(); \ 00099 ERR("Connection error (%d)", ret); \ 00100 return HTTP_CONN; \ 00101 } \ 00102 } while(0) 00103 00104 #define PRTCL_ERR() \ 00105 do{ \ 00106 m_sock.close(); \ 00107 ERR("Protocol error"); \ 00108 return HTTP_PRTCL; \ 00109 } while(0) 00110 00111 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request 00112 { 00113 m_httpResponseCode = 0; //Invalidate code 00114 m_timeout = timeout; 00115 00116 char scheme[8]; 00117 uint16_t port; 00118 char host[32]; 00119 char path[64]; 00120 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?) 00121 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); 00122 if(res != HTTP_OK) 00123 { 00124 ERR("parseURL returned %d", res); 00125 return res; 00126 } 00127 00128 if(port == 0) //TODO do handle HTTPS->443 00129 { 00130 port = 80; 00131 } 00132 00133 DBG("Scheme: %s", scheme); 00134 DBG("Host: %s", host); 00135 DBG("Port: %d", port); 00136 DBG("Path: %s", path); 00137 00138 //Connect 00139 DBG("Connecting socket to server"); 00140 int ret = m_sock.connect(host, port); 00141 if (ret < 0) 00142 { 00143 m_sock.close(); 00144 ERR("Could not connect"); 00145 return HTTP_CONN; 00146 } 00147 00148 //Send request 00149 DBG("Sending request"); 00150 char buf[CHUNK_SIZE]; 00151 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":""; 00152 snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request 00153 ret = send(buf); 00154 if(ret) 00155 { 00156 m_sock.close(); 00157 ERR("Could not write request"); 00158 return HTTP_CONN; 00159 } 00160 00161 //Send all headers 00162 00163 //Send default headers 00164 DBG("Sending headers"); 00165 if( (method == HTTP_POST) && (pDataOut != NULL) ) 00166 { 00167 if( pDataOut->getIsChunked() ) 00168 { 00169 ret = send("Transfer-Encoding: chunked\r\n"); 00170 CHECK_CONN_ERR(ret); 00171 } 00172 else 00173 { 00174 snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen()); 00175 ret = send(buf); 00176 CHECK_CONN_ERR(ret); 00177 } 00178 char type[48]; 00179 if( pDataOut->getDataType(type, 48) == HTTP_OK ) 00180 { 00181 snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type); 00182 ret = send(buf); 00183 CHECK_CONN_ERR(ret); 00184 } 00185 } 00186 00187 //Close headers 00188 DBG("Headers sent"); 00189 ret = send("\r\n"); 00190 CHECK_CONN_ERR(ret); 00191 00192 size_t trfLen; 00193 00194 //Send data (if POST) 00195 if( (method == HTTP_POST) && (pDataOut != NULL) ) 00196 { 00197 DBG("Sending data"); 00198 while(true) 00199 { 00200 size_t writtenLen = 0; 00201 pDataOut->read(buf, CHUNK_SIZE, &trfLen); 00202 if( pDataOut->getIsChunked() ) 00203 { 00204 //Write chunk header 00205 char chunkHeader[16]; 00206 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding 00207 ret = send(chunkHeader); 00208 CHECK_CONN_ERR(ret); 00209 } 00210 else if( trfLen == 0 ) 00211 { 00212 break; 00213 } 00214 if( trfLen != 0 ) 00215 { 00216 ret = send(buf, trfLen); 00217 CHECK_CONN_ERR(ret); 00218 } 00219 00220 if( pDataOut->getIsChunked() ) 00221 { 00222 ret = send("\r\n"); //Chunk-terminating CRLF 00223 CHECK_CONN_ERR(ret); 00224 } 00225 else 00226 { 00227 writtenLen += trfLen; 00228 if( writtenLen >= pDataOut->getDataLen() ) 00229 { 00230 break; 00231 } 00232 } 00233 00234 if( trfLen == 0 ) 00235 { 00236 break; 00237 } 00238 } 00239 00240 } 00241 00242 //Receive response 00243 DBG("Receiving response"); 00244 ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes 00245 CHECK_CONN_ERR(ret); 00246 00247 buf[trfLen] = '\0'; 00248 00249 char* crlfPtr = strstr(buf, "\r\n"); 00250 if(crlfPtr == NULL) 00251 { 00252 PRTCL_ERR(); 00253 } 00254 00255 int crlfPos = crlfPtr - buf; 00256 buf[crlfPos] = '\0'; 00257 00258 //Parse HTTP response 00259 if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) 00260 { 00261 //Cannot match string, error 00262 ERR("Not a correct HTTP answer : %s\n", buf); 00263 PRTCL_ERR(); 00264 } 00265 00266 if(m_httpResponseCode != 200) 00267 { 00268 //Cannot match string, error 00269 WARN("Response code %d", m_httpResponseCode); 00270 PRTCL_ERR(); 00271 } 00272 00273 DBG("Reading headers"); 00274 00275 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00276 trfLen -= (crlfPos + 2); 00277 00278 size_t recvContentLength = 0; 00279 bool recvChunked = false; 00280 //Now get headers 00281 while( true ) 00282 { 00283 crlfPtr = strstr(buf, "\r\n"); 00284 if(crlfPtr == NULL) 00285 { 00286 if( trfLen < CHUNK_SIZE - 1 ) 00287 { 00288 size_t newTrfLen; 00289 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00290 trfLen += newTrfLen; 00291 buf[trfLen] = '\0'; 00292 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); 00293 CHECK_CONN_ERR(ret); 00294 continue; 00295 } 00296 else 00297 { 00298 PRTCL_ERR(); 00299 } 00300 } 00301 00302 crlfPos = crlfPtr - buf; 00303 00304 if(crlfPos == 0) //End of headers 00305 { 00306 DBG("Headers read"); 00307 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well 00308 trfLen -= 2; 00309 break; 00310 } 00311 00312 buf[crlfPos] = '\0'; 00313 00314 char key[32]; 00315 char value[32]; 00316 00317 key[31] = '\0'; 00318 value[31] = '\0'; 00319 00320 int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value); 00321 if ( n == 2 ) 00322 { 00323 DBG("Read header : %s: %s\n", key, value); 00324 if( !strcmp(key, "Content-Length") ) 00325 { 00326 sscanf(value, "%d", &recvContentLength); 00327 pDataIn->setDataLen(recvContentLength); 00328 } 00329 else if( !strcmp(key, "Transfer-Encoding") ) 00330 { 00331 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) 00332 { 00333 recvChunked = true; 00334 pDataIn->setIsChunked(true); 00335 } 00336 } 00337 else if( !strcmp(key, "Content-Type") ) 00338 { 00339 pDataIn->setDataType(value); 00340 } 00341 00342 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00343 trfLen -= (crlfPos + 2); 00344 00345 } 00346 else 00347 { 00348 ERR("Could not parse header"); 00349 PRTCL_ERR(); 00350 } 00351 00352 } 00353 00354 //Receive data 00355 DBG("Receiving data"); 00356 while(true) 00357 { 00358 size_t readLen = 0; 00359 00360 if( recvChunked ) 00361 { 00362 //Read chunk header 00363 crlfPos=0; 00364 for(crlfPos++; crlfPos < trfLen - 2; crlfPos++) 00365 { 00366 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) 00367 { 00368 break; 00369 } 00370 } 00371 if(crlfPos >= trfLen - 2) //Try to read more 00372 { 00373 if( trfLen < CHUNK_SIZE ) 00374 { 00375 size_t newTrfLen; 00376 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00377 trfLen += newTrfLen; 00378 CHECK_CONN_ERR(ret); 00379 continue; 00380 } 00381 else 00382 { 00383 PRTCL_ERR(); 00384 } 00385 } 00386 buf[crlfPos] = '\0'; 00387 int n = sscanf(buf, "%x", &readLen); 00388 if(n!=1) 00389 { 00390 ERR("Could not read chunk length"); 00391 PRTCL_ERR(); 00392 } 00393 00394 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more 00395 trfLen -= (crlfPos + 2); 00396 00397 if( readLen == 0 ) 00398 { 00399 //Last chunk 00400 break; 00401 } 00402 } 00403 else 00404 { 00405 readLen = recvContentLength; 00406 } 00407 00408 DBG("Retrieving %d bytes", readLen); 00409 00410 do 00411 { 00412 pDataIn->write(buf, MIN(trfLen, readLen)); 00413 if( trfLen > readLen ) 00414 { 00415 memmove(buf, &buf[readLen], trfLen - readLen); 00416 trfLen -= readLen; 00417 readLen = 0; 00418 } 00419 else 00420 { 00421 readLen -= trfLen; 00422 } 00423 00424 if(readLen) 00425 { 00426 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen); 00427 CHECK_CONN_ERR(ret); 00428 } 00429 } while(readLen); 00430 00431 if( recvChunked ) 00432 { 00433 if(trfLen < 2) 00434 { 00435 size_t newTrfLen; 00436 //Read missing chars to find end of chunk 00437 ret = recv(buf, 2 - trfLen, CHUNK_SIZE, &newTrfLen); 00438 CHECK_CONN_ERR(ret); 00439 trfLen += newTrfLen; 00440 } 00441 if( (buf[0] != '\r') || (buf[1] != '\n') ) 00442 { 00443 ERR("Format error"); 00444 PRTCL_ERR(); 00445 } 00446 memmove(buf, &buf[2], trfLen - 2); 00447 trfLen -= 2; 00448 } 00449 else 00450 { 00451 break; 00452 } 00453 00454 } 00455 00456 m_sock.close(); 00457 DBG("Completed HTTP transaction"); 00458 00459 return HTTP_OK; 00460 } 00461 00462 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, const char* SOAPAction, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request 00463 { 00464 m_httpResponseCode = 0; //Invalidate code 00465 m_timeout = timeout; 00466 00467 char scheme[8]; 00468 uint16_t port; 00469 char host[100]; 00470 char path[64]; 00471 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?) 00472 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); 00473 if(res != HTTP_OK) 00474 { 00475 ERR("parseURL returned %d", res); 00476 return res; 00477 } 00478 00479 if(port == 0) //TODO do handle HTTPS->443 00480 { 00481 port = 80; 00482 } 00483 00484 DBG("Scheme: %s", scheme); 00485 DBG("Host: %s", host); 00486 DBG("Port: %d", port); 00487 DBG("Path: %s", path); 00488 DBG("SOAPAction: %s",SOAPAction); 00489 00490 //Connect 00491 DBG("Connecting socket to server"); 00492 int ret = m_sock.connect(host, port); 00493 if (ret < 0) 00494 { 00495 m_sock.close(); 00496 ERR("Could not connect"); 00497 return HTTP_CONN; 00498 } 00499 00500 //Send request 00501 DBG("Sending request"); 00502 char buf[CHUNK_SIZE]; 00503 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":""; 00504 snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request 00505 ret = send(buf); 00506 if(ret) 00507 { 00508 m_sock.close(); 00509 ERR("Could not write request"); 00510 return HTTP_CONN; 00511 } 00512 00513 //Send all headers 00514 00515 //Send default headers 00516 DBG("Sending headers"); 00517 if( (method == HTTP_POST) && (pDataOut != NULL) ) 00518 { 00519 if( pDataOut->getIsChunked() ) 00520 { 00521 ret = send("Transfer-Encoding: chunked\r\n"); 00522 CHECK_CONN_ERR(ret); 00523 } 00524 else 00525 { 00526 snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen()); 00527 ret = send(buf); 00528 CHECK_CONN_ERR(ret); 00529 } 00530 //char type[48]; 00531 //if( pDataOut->getDataType(type, 48) == HTTP_OK ) 00532 //{ 00533 snprintf(buf, sizeof(buf), "Content-Type: text/xml;charset=UTF-8\r\n"); 00534 ret = send(buf); 00535 CHECK_CONN_ERR(ret); 00536 snprintf(buf, sizeof(buf), "SOAPAction: \"%s\"\r\n", SOAPAction); 00537 ret = send(buf); 00538 CHECK_CONN_ERR(ret); 00539 //} 00540 } 00541 00542 //Close headers 00543 DBG("Headers sent"); 00544 ret = send("\r\n"); 00545 CHECK_CONN_ERR(ret); 00546 00547 size_t trfLen; 00548 00549 //Send data (if POST) 00550 if( (method == HTTP_POST) && (pDataOut != NULL) ) 00551 { 00552 DBG("Sending data"); 00553 while(true) 00554 { 00555 size_t writtenLen = 0; 00556 pDataOut->read(buf, CHUNK_SIZE, &trfLen); 00557 if( pDataOut->getIsChunked() ) 00558 { 00559 //Write chunk header 00560 char chunkHeader[16]; 00561 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding 00562 ret = send(chunkHeader); 00563 CHECK_CONN_ERR(ret); 00564 } 00565 else if( trfLen == 0 ) 00566 { 00567 break; 00568 } 00569 if( trfLen != 0 ) 00570 { 00571 ret = send(buf, trfLen); 00572 CHECK_CONN_ERR(ret); 00573 } 00574 00575 if( pDataOut->getIsChunked() ) 00576 { 00577 ret = send("\r\n"); //Chunk-terminating CRLF 00578 CHECK_CONN_ERR(ret); 00579 } 00580 else 00581 { 00582 writtenLen += trfLen; 00583 if( writtenLen >= pDataOut->getDataLen() ) 00584 { 00585 break; 00586 } 00587 } 00588 00589 if( trfLen == 0 ) 00590 { 00591 break; 00592 } 00593 } 00594 00595 } 00596 00597 //Receive response 00598 DBG("Receiving response"); 00599 ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes 00600 CHECK_CONN_ERR(ret); 00601 00602 buf[trfLen] = '\0'; 00603 00604 char* crlfPtr = strstr(buf, "\r\n"); 00605 if(crlfPtr == NULL) 00606 { 00607 PRTCL_ERR(); 00608 } 00609 00610 int crlfPos = crlfPtr - buf; 00611 buf[crlfPos] = '\0'; 00612 00613 //Parse HTTP response 00614 if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) 00615 { 00616 //Cannot match string, error 00617 ERR("Not a correct HTTP answer : %s\n", buf); 00618 PRTCL_ERR(); 00619 } 00620 00621 if(m_httpResponseCode != 200) 00622 { 00623 //Cannot match string, error 00624 WARN("Response code %d", m_httpResponseCode); 00625 PRTCL_ERR(); 00626 } 00627 00628 DBG("Reading headers"); 00629 00630 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00631 trfLen -= (crlfPos + 2); 00632 00633 size_t recvContentLength = 0; 00634 bool recvChunked = false; 00635 //Now get headers 00636 while( true ) 00637 { 00638 crlfPtr = strstr(buf, "\r\n"); 00639 if(crlfPtr == NULL) 00640 { 00641 if( trfLen < CHUNK_SIZE - 1 ) 00642 { 00643 size_t newTrfLen; 00644 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00645 trfLen += newTrfLen; 00646 buf[trfLen] = '\0'; 00647 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); 00648 CHECK_CONN_ERR(ret); 00649 continue; 00650 } 00651 else 00652 { 00653 PRTCL_ERR(); 00654 } 00655 } 00656 00657 crlfPos = crlfPtr - buf; 00658 00659 if(crlfPos == 0) //End of headers 00660 { 00661 DBG("Headers read"); 00662 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well 00663 trfLen -= 2; 00664 break; 00665 } 00666 00667 buf[crlfPos] = '\0'; 00668 00669 char key[32]; 00670 char value[32]; 00671 00672 key[31] = '\0'; 00673 value[31] = '\0'; 00674 00675 int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value); 00676 if ( n == 2 ) 00677 { 00678 DBG("Read header : %s: %s\n", key, value); 00679 if( !strcmp(key, "Content-Length") ) 00680 { 00681 sscanf(value, "%d", &recvContentLength); 00682 pDataIn->setDataLen(recvContentLength); 00683 } 00684 else if( !strcmp(key, "Transfer-Encoding") ) 00685 { 00686 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) 00687 { 00688 recvChunked = true; 00689 pDataIn->setIsChunked(true); 00690 } 00691 } 00692 else if( !strcmp(key, "Content-Type") ) 00693 { 00694 pDataIn->setDataType(value); 00695 } 00696 00697 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00698 trfLen -= (crlfPos + 2); 00699 00700 } 00701 else 00702 { 00703 ERR("Could not parse header"); 00704 PRTCL_ERR(); 00705 } 00706 00707 } 00708 00709 //Receive data 00710 DBG("Receiving data"); 00711 while(true) 00712 { 00713 size_t readLen = 0; 00714 00715 if( recvChunked ) 00716 { 00717 //Read chunk header 00718 crlfPos=0; 00719 for(crlfPos++; crlfPos < trfLen - 2; crlfPos++) 00720 { 00721 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) 00722 { 00723 break; 00724 } 00725 } 00726 if(crlfPos >= trfLen - 2) //Try to read more 00727 { 00728 if( trfLen < CHUNK_SIZE ) 00729 { 00730 size_t newTrfLen; 00731 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00732 trfLen += newTrfLen; 00733 CHECK_CONN_ERR(ret); 00734 continue; 00735 } 00736 else 00737 { 00738 PRTCL_ERR(); 00739 } 00740 } 00741 buf[crlfPos] = '\0'; 00742 int n = sscanf(buf, "%x", &readLen); 00743 if(n!=1) 00744 { 00745 ERR("Could not read chunk length"); 00746 PRTCL_ERR(); 00747 } 00748 00749 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more 00750 trfLen -= (crlfPos + 2); 00751 00752 if( readLen == 0 ) 00753 { 00754 //Last chunk 00755 break; 00756 } 00757 } 00758 else 00759 { 00760 readLen = recvContentLength; 00761 } 00762 00763 DBG("Retrieving %d bytes", readLen); 00764 00765 do 00766 { 00767 pDataIn->write(buf, MIN(trfLen, readLen)); 00768 if( trfLen > readLen ) 00769 { 00770 memmove(buf, &buf[readLen], trfLen - readLen); 00771 trfLen -= readLen; 00772 readLen = 0; 00773 } 00774 else 00775 { 00776 readLen -= trfLen; 00777 } 00778 00779 if(readLen) 00780 { 00781 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen); 00782 CHECK_CONN_ERR(ret); 00783 } 00784 } while(readLen); 00785 00786 if( recvChunked ) 00787 { 00788 if(trfLen < 2) 00789 { 00790 size_t newTrfLen; 00791 //Read missing chars to find end of chunk 00792 ret = recv(buf, 2 - trfLen, CHUNK_SIZE, &newTrfLen); 00793 CHECK_CONN_ERR(ret); 00794 trfLen += newTrfLen; 00795 } 00796 if( (buf[0] != '\r') || (buf[1] != '\n') ) 00797 { 00798 ERR("Format error"); 00799 PRTCL_ERR(); 00800 } 00801 memmove(buf, &buf[2], trfLen - 2); 00802 trfLen -= 2; 00803 } 00804 else 00805 { 00806 break; 00807 } 00808 00809 } 00810 00811 m_sock.close(); 00812 DBG("Completed HTTP transaction"); 00813 00814 return HTTP_OK; 00815 } 00816 00817 00818 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure 00819 { 00820 DBG("Trying to read between %d and %d bytes", minLen, maxLen); 00821 size_t readLen = 0; 00822 00823 if(!m_sock.is_connected()) 00824 { 00825 WARN("Connection was closed by server"); 00826 return HTTP_CLOSED; //Connection was closed by server 00827 } 00828 00829 int ret; 00830 while(readLen < maxLen) 00831 { 00832 if(readLen < minLen) 00833 { 00834 DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen); 00835 m_sock.set_blocking(false, m_timeout); 00836 ret = m_sock.receive_all(buf + readLen, minLen - readLen); 00837 } 00838 else 00839 { 00840 DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen); 00841 m_sock.set_blocking(false, 0); 00842 ret = m_sock.receive(buf + readLen, maxLen - readLen); 00843 } 00844 00845 if( ret > 0) 00846 { 00847 readLen += ret; 00848 } 00849 else if( ret == 0 ) 00850 { 00851 break; 00852 } 00853 else 00854 { 00855 if(!m_sock.is_connected()) 00856 { 00857 ERR("Connection error (recv returned %d)", ret); 00858 *pReadLen = readLen; 00859 return HTTP_CONN; 00860 } 00861 else 00862 { 00863 break; 00864 } 00865 } 00866 00867 if(!m_sock.is_connected()) 00868 { 00869 break; 00870 } 00871 } 00872 DBG("Read %d bytes", readLen); 00873 *pReadLen = readLen; 00874 return HTTP_OK; 00875 } 00876 00877 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure 00878 { 00879 if(len == 0) 00880 { 00881 len = strlen(buf); 00882 } 00883 DBG("Trying to write %d bytes", len); 00884 size_t writtenLen = 0; 00885 00886 if(!m_sock.is_connected()) 00887 { 00888 WARN("Connection was closed by server"); 00889 return HTTP_CLOSED; //Connection was closed by server 00890 } 00891 00892 m_sock.set_blocking(false, m_timeout); 00893 int ret = m_sock.send_all(buf, len); 00894 if(ret > 0) 00895 { 00896 writtenLen += ret; 00897 } 00898 else if( ret == 0 ) 00899 { 00900 WARN("Connection was closed by server"); 00901 return HTTP_CLOSED; //Connection was closed by server 00902 } 00903 else 00904 { 00905 ERR("Connection error (send returned %d)", ret); 00906 return HTTP_CONN; 00907 } 00908 00909 DBG("Written %d bytes", writtenLen); 00910 return HTTP_OK; 00911 } 00912 00913 HTTPResult 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 00914 { 00915 char* schemePtr = (char*) url; 00916 char* hostPtr = (char*) strstr(url, "://"); 00917 if(hostPtr == NULL) 00918 { 00919 WARN("Could not find host"); 00920 return HTTP_PARSE; //URL is invalid 00921 } 00922 00923 if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char 00924 { 00925 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1); 00926 return HTTP_PARSE; 00927 } 00928 memcpy(scheme, schemePtr, hostPtr - schemePtr); 00929 scheme[hostPtr - schemePtr] = '\0'; 00930 00931 hostPtr+=3; 00932 00933 size_t hostLen = 0; 00934 00935 char* portPtr = strchr(hostPtr, ':'); 00936 if( portPtr != NULL ) 00937 { 00938 hostLen = portPtr - hostPtr; 00939 portPtr++; 00940 if( sscanf(portPtr, "%hu", port) != 1) 00941 { 00942 WARN("Could not find port"); 00943 return HTTP_PARSE; 00944 } 00945 } 00946 else 00947 { 00948 *port=0; 00949 } 00950 char* pathPtr = strchr(hostPtr, '/'); 00951 if( hostLen == 0 ) 00952 { 00953 hostLen = pathPtr - hostPtr; 00954 } 00955 00956 if( maxHostLen < hostLen + 1 ) //including NULL-terminating char 00957 { 00958 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1); 00959 return HTTP_PARSE; 00960 } 00961 memcpy(host, hostPtr, hostLen); 00962 host[hostLen] = '\0'; 00963 00964 size_t pathLen; 00965 char* fragmentPtr = strchr(hostPtr, '#'); 00966 if(fragmentPtr != NULL) 00967 { 00968 pathLen = fragmentPtr - pathPtr; 00969 } 00970 else 00971 { 00972 pathLen = strlen(pathPtr); 00973 } 00974 00975 if( maxPathLen < pathLen + 1 ) //including NULL-terminating char 00976 { 00977 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1); 00978 return HTTP_PARSE; 00979 } 00980 memcpy(path, pathPtr, pathLen); 00981 path[pathLen] = '\0'; 00982 00983 return HTTP_OK; 00984 }
Generated on Fri Jul 15 2022 16:08:04 by 1.7.2