Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 0 00022 //Enable debug 00023 #include <cstdio> 00024 #define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 00025 #define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 00026 #define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 00027 00028 #else 00029 //Disable debug 00030 #define DBG(x, ...) 00031 #define WARN(x, ...) 00032 #define ERR(x, ...) 00033 00034 #endif 00035 00036 #define HTTP_PORT 80 00037 00038 #define OK 0 00039 00040 #define MIN(x,y) (((x)<(y))?(x):(y)) 00041 #define MAX(x,y) (((x)>(y))?(x):(y)) 00042 00043 #define CHUNK_SIZE 256 00044 00045 #include <cstring> 00046 00047 #include "HTTPClient.h" 00048 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::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00086 { 00087 return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout); 00088 } 00089 00090 HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking 00091 { 00092 return connect(url, HTTP_DELETE, NULL, pDataIn, timeout); 00093 } 00094 00095 00096 int HTTPClient::getHTTPResponseCode() 00097 { 00098 return m_httpResponseCode; 00099 } 00100 00101 #define CHECK_CONN_ERR(ret) \ 00102 do{ \ 00103 if(ret) { \ 00104 m_sock.close(); \ 00105 ERR("Connection error (%d)", ret); \ 00106 return HTTP_CONN; \ 00107 } \ 00108 } while(0) 00109 00110 #define PRTCL_ERR() \ 00111 do{ \ 00112 m_sock.close(); \ 00113 ERR("Protocol error"); \ 00114 return HTTP_PRTCL; \ 00115 } while(0) 00116 00117 HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request 00118 { 00119 m_httpResponseCode = 0; //Invalidate code 00120 m_timeout = timeout; 00121 00122 pDataIn->writeReset(); 00123 if( pDataOut ) 00124 { 00125 pDataOut->readReset(); 00126 } 00127 00128 char scheme[8]; 00129 uint16_t port; 00130 char host[32]; 00131 char path[64]; 00132 //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?) 00133 HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); 00134 if(res != HTTP_OK) 00135 { 00136 ERR("parseURL returned %d", res); 00137 return res; 00138 } 00139 00140 if(port == 0) //TODO do handle HTTPS->443 00141 { 00142 port = 80; 00143 } 00144 00145 DBG("Scheme: %s", scheme); 00146 DBG("Host: %s", host); 00147 DBG("Port: %d", port); 00148 DBG("Path: %s", path); 00149 00150 //Connect 00151 DBG("Connecting socket to server"); 00152 int ret = m_sock.connect(host, port); 00153 if (ret < 0) 00154 { 00155 m_sock.close(); 00156 ERR("Could not connect"); 00157 return HTTP_CONN; 00158 } 00159 //Send request 00160 DBG("Sending request"); 00161 char buf[CHUNK_SIZE]; 00162 const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":""; 00163 snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request 00164 ret = send(buf); 00165 if(ret) 00166 { 00167 m_sock.close(); 00168 ERR("Could not write request"); 00169 return HTTP_CONN; 00170 } 00171 00172 //Send all headers 00173 00174 //Send default headers 00175 DBG("Sending headers"); 00176 if( pDataOut != NULL ) 00177 { 00178 if( pDataOut->getIsChunked() ) 00179 { 00180 ret = send("Transfer-Encoding: chunked\r\n"); 00181 CHECK_CONN_ERR(ret); 00182 } 00183 else 00184 { 00185 snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen()); 00186 ret = send(buf); 00187 CHECK_CONN_ERR(ret); 00188 } 00189 char type[48]; 00190 if( pDataOut->getDataType(type, 48) == HTTP_OK ) 00191 { 00192 snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type); 00193 ret = send(buf); 00194 CHECK_CONN_ERR(ret); 00195 } 00196 00197 //Send specific headers 00198 while( pDataOut->getHeader(buf, sizeof(buf) - 3) ) //must have space left for CRLF + 0 terminating char 00199 { 00200 size_t headerlen = strlen(buf); 00201 snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n"); 00202 ret = send(buf); 00203 CHECK_CONN_ERR(ret); 00204 } 00205 } 00206 00207 //Send specific headers 00208 while( pDataIn->getHeader(buf, sizeof(buf) - 3) ) 00209 { 00210 size_t headerlen = strlen(buf); 00211 snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n"); 00212 ret = send(buf); 00213 CHECK_CONN_ERR(ret); 00214 } 00215 00216 //Close headers 00217 DBG("Headers sent"); 00218 ret = send("\r\n"); 00219 CHECK_CONN_ERR(ret); 00220 00221 size_t trfLen; 00222 00223 //Send data (if available) 00224 if( pDataOut != NULL ) 00225 { 00226 DBG("Sending data"); 00227 while(true) 00228 { 00229 size_t writtenLen = 0; 00230 pDataOut->read(buf, CHUNK_SIZE, &trfLen); 00231 if( pDataOut->getIsChunked() ) 00232 { 00233 //Write chunk header 00234 char chunkHeader[16]; 00235 snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding 00236 ret = send(chunkHeader); 00237 CHECK_CONN_ERR(ret); 00238 } 00239 else if( trfLen == 0 ) 00240 { 00241 break; 00242 } 00243 if( trfLen != 0 ) 00244 { 00245 ret = send(buf, trfLen); 00246 CHECK_CONN_ERR(ret); 00247 } 00248 00249 if( pDataOut->getIsChunked() ) 00250 { 00251 ret = send("\r\n"); //Chunk-terminating CRLF 00252 CHECK_CONN_ERR(ret); 00253 } 00254 else 00255 { 00256 writtenLen += trfLen; 00257 if( writtenLen >= pDataOut->getDataLen() ) 00258 { 00259 break; 00260 } 00261 } 00262 00263 if( trfLen == 0 ) 00264 { 00265 break; 00266 } 00267 } 00268 } 00269 00270 //Receive response 00271 DBG("Receiving response"); 00272 ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes 00273 CHECK_CONN_ERR(ret); 00274 00275 buf[trfLen] = '\0'; 00276 00277 //Make sure we got the first response line 00278 char* crlfPtr = NULL; 00279 while( true ) 00280 { 00281 crlfPtr = strstr(buf, "\r\n"); 00282 if(crlfPtr == NULL) 00283 { 00284 if( trfLen < CHUNK_SIZE - 1 ) 00285 { 00286 size_t newTrfLen; 00287 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00288 trfLen += newTrfLen; 00289 buf[trfLen] = '\0'; 00290 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); 00291 CHECK_CONN_ERR(ret); 00292 continue; 00293 } 00294 else 00295 { 00296 PRTCL_ERR(); 00297 } 00298 } 00299 break; 00300 } 00301 00302 int crlfPos = crlfPtr - buf; 00303 buf[crlfPos] = '\0'; 00304 00305 //Parse HTTP response 00306 //if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) 00307 if(crlfPos > 13) 00308 { 00309 buf[13] = '\0'; 00310 } 00311 if( sscanf(buf, "HTTP/%*d.%*d %d", &m_httpResponseCode) != 1 ) //Kludge for newlib nano 00312 { 00313 //Cannot match string, error 00314 ERR("Not a correct HTTP answer : %s\n", buf); 00315 PRTCL_ERR(); 00316 } 00317 00318 if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) ) 00319 { 00320 //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers 00321 WARN("Response code %d", m_httpResponseCode); 00322 PRTCL_ERR(); 00323 } 00324 00325 DBG("Reading headers"); 00326 00327 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00328 trfLen -= (crlfPos + 2); 00329 00330 size_t recvContentLength = 0; 00331 bool recvChunked = false; 00332 bool recvLengthUnknown = true; 00333 //Now get headers 00334 while( true ) 00335 { 00336 crlfPtr = strstr(buf, "\r\n"); 00337 if(crlfPtr == NULL) 00338 { 00339 if( trfLen < CHUNK_SIZE - 1 ) 00340 { 00341 size_t newTrfLen; 00342 ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00343 trfLen += newTrfLen; 00344 buf[trfLen] = '\0'; 00345 DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); 00346 CHECK_CONN_ERR(ret); 00347 continue; 00348 } 00349 else 00350 { 00351 PRTCL_ERR(); 00352 } 00353 } 00354 00355 crlfPos = crlfPtr - buf; 00356 00357 if(crlfPos == 0) //End of headers 00358 { 00359 DBG("Headers read"); 00360 memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well 00361 trfLen -= 2; 00362 break; 00363 } 00364 00365 buf[crlfPos] = '\0'; 00366 00367 char key[32]; 00368 char value[32]; 00369 00370 //key[31] = '\0'; 00371 //value[31] = '\0'; 00372 00373 memset(key, 0, 32); 00374 memset(value, 0, 32); 00375 00376 //int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value); 00377 00378 int n = 0; 00379 00380 char* keyEnd = strchr(buf, ':'); 00381 if(keyEnd != NULL) 00382 { 00383 *keyEnd = '\0'; 00384 if(strlen(buf) < 32) 00385 { 00386 strcpy(key, buf); 00387 n++; 00388 char* valueStart = keyEnd + 2; 00389 if( (valueStart - buf) < crlfPos ) 00390 { 00391 if(strlen(valueStart) < 32) 00392 { 00393 strcpy(value, valueStart); 00394 n++; 00395 } 00396 } 00397 } 00398 } 00399 if ( n == 2 ) 00400 { 00401 DBG("Read header : %s: %s\n", key, value); 00402 if( !strcmp(key, "Content-Length") ) 00403 { 00404 sscanf(value, "%d", &recvContentLength); 00405 recvLengthUnknown = false; 00406 pDataIn->setDataLen(recvContentLength); 00407 } 00408 else if( !strcmp(key, "Transfer-Encoding") ) 00409 { 00410 if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) 00411 { 00412 recvChunked = true; 00413 recvLengthUnknown = false; 00414 pDataIn->setIsChunked(true); 00415 } 00416 } 00417 else if( !strcmp(key, "Content-Type") ) 00418 { 00419 pDataIn->setDataType(value); 00420 } 00421 00422 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well 00423 trfLen -= (crlfPos + 2); 00424 00425 } 00426 else 00427 { 00428 ERR("Could not parse header"); 00429 PRTCL_ERR(); 00430 } 00431 00432 } 00433 00434 //Receive data 00435 DBG("Receiving data"); 00436 while(true) 00437 { 00438 size_t readLen = 0; 00439 00440 if( recvChunked ) 00441 { 00442 //Read chunk header 00443 bool foundCrlf; 00444 do 00445 { 00446 foundCrlf = false; 00447 crlfPos=0; 00448 buf[trfLen]=0; 00449 if(trfLen >= 2) 00450 { 00451 for(; crlfPos < trfLen - 2; crlfPos++) 00452 { 00453 if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) 00454 { 00455 foundCrlf = true; 00456 break; 00457 } 00458 } 00459 } 00460 if(!foundCrlf) //Try to read more 00461 { 00462 if( trfLen < CHUNK_SIZE ) 00463 { 00464 size_t newTrfLen; 00465 ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00466 trfLen += newTrfLen; 00467 CHECK_CONN_ERR(ret); 00468 continue; 00469 } 00470 else 00471 { 00472 PRTCL_ERR(); 00473 } 00474 } 00475 } while(!foundCrlf); 00476 buf[crlfPos] = '\0'; 00477 int n = sscanf(buf, "%x", &readLen); 00478 if(n!=1) 00479 { 00480 ERR("Could not read chunk length"); 00481 PRTCL_ERR(); 00482 } 00483 00484 memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more 00485 trfLen -= (crlfPos + 2); 00486 00487 if( readLen == 0 ) 00488 { 00489 //Last chunk 00490 break; 00491 } 00492 } 00493 else 00494 { 00495 readLen = recvContentLength; 00496 } 00497 00498 DBG("Retrieving %d bytes (%d bytes in buffer)", readLen, trfLen); 00499 00500 do 00501 { 00502 if(recvLengthUnknown ) 00503 { 00504 readLen = trfLen; 00505 } 00506 pDataIn->write(buf, MIN(trfLen, readLen)); 00507 if(!recvLengthUnknown) 00508 { 00509 if( trfLen > readLen ) 00510 { 00511 memmove(buf, &buf[readLen], trfLen - readLen); 00512 trfLen -= readLen; 00513 readLen = 0; 00514 } 00515 else 00516 { 00517 readLen -= trfLen; 00518 } 00519 } 00520 else 00521 { 00522 trfLen = 0; 00523 } 00524 00525 if(readLen || recvLengthUnknown) 00526 { 00527 ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen); 00528 if(recvLengthUnknown && (ret == HTTP_CLOSED)) 00529 { 00530 //Write and exit 00531 pDataIn->write(buf, trfLen); 00532 break; 00533 } 00534 CHECK_CONN_ERR(ret); 00535 if(recvLengthUnknown && (trfLen == 0)) 00536 { 00537 break; 00538 } 00539 } 00540 } while(readLen || recvLengthUnknown); 00541 00542 if( recvChunked ) 00543 { 00544 if(trfLen < 2) 00545 { 00546 size_t newTrfLen; 00547 //Read missing chars to find end of chunk 00548 ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen); 00549 CHECK_CONN_ERR(ret); 00550 trfLen += newTrfLen; 00551 } 00552 if( (buf[0] != '\r') || (buf[1] != '\n') ) 00553 { 00554 ERR("Format error"); 00555 PRTCL_ERR(); 00556 } 00557 memmove(buf, &buf[2], trfLen - 2); 00558 trfLen -= 2; 00559 } 00560 else 00561 { 00562 break; 00563 } 00564 00565 } 00566 00567 m_sock.close(); 00568 DBG("Completed HTTP transaction"); 00569 00570 return HTTP_OK; 00571 } 00572 00573 HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure 00574 { 00575 DBG("Trying to read between %d and %d bytes", minLen, maxLen); 00576 size_t readLen = 0; 00577 00578 if(!m_sock.is_connected()) 00579 { 00580 WARN("Connection was closed by server"); 00581 return HTTP_CLOSED; //Connection was closed by server 00582 } 00583 00584 int ret; 00585 while(readLen < maxLen) 00586 { 00587 if(readLen < minLen) 00588 { 00589 DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen); 00590 m_sock.set_blocking(false, m_timeout); 00591 ret = m_sock.receive_all(buf + readLen, minLen - readLen); 00592 } 00593 else 00594 { 00595 DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen); 00596 m_sock.set_blocking(false, 0); 00597 ret = m_sock.receive(buf + readLen, maxLen - readLen); 00598 } 00599 00600 if( ret > 0) 00601 { 00602 readLen += ret; 00603 } 00604 else if( ret == 0 ) 00605 { 00606 break; 00607 } 00608 else 00609 { 00610 if(!m_sock.is_connected()) 00611 { 00612 ERR("Connection error (recv returned %d)", ret); 00613 *pReadLen = readLen; 00614 return HTTP_CONN; 00615 } 00616 else 00617 { 00618 break; 00619 } 00620 } 00621 00622 if(!m_sock.is_connected()) 00623 { 00624 break; 00625 } 00626 } 00627 DBG("Read %d bytes", readLen); 00628 *pReadLen = readLen; 00629 return HTTP_OK; 00630 } 00631 00632 HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure 00633 { 00634 if(len == 0) 00635 { 00636 len = strlen(buf); 00637 } 00638 DBG("Trying to write %d bytes", len); 00639 size_t writtenLen = 0; 00640 00641 if(!m_sock.is_connected()) 00642 { 00643 WARN("Connection was closed by server"); 00644 return HTTP_CLOSED; //Connection was closed by server 00645 } 00646 00647 m_sock.set_blocking(false, m_timeout); 00648 int ret = m_sock.send_all(buf, len); 00649 if(ret > 0) 00650 { 00651 writtenLen += ret; 00652 } 00653 else if( ret == 0 ) 00654 { 00655 WARN("Connection was closed by server"); 00656 return HTTP_CLOSED; //Connection was closed by server 00657 } 00658 else 00659 { 00660 ERR("Connection error (send returned %d)", ret); 00661 return HTTP_CONN; 00662 } 00663 00664 DBG("Written %d bytes", writtenLen); 00665 return HTTP_OK; 00666 } 00667 00668 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 00669 { 00670 char* schemePtr = (char*) url; 00671 char* hostPtr = (char*) strstr(url, "://"); 00672 if(hostPtr == NULL) 00673 { 00674 WARN("Could not find host"); 00675 return HTTP_PARSE; //URL is invalid 00676 } 00677 00678 if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char 00679 { 00680 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1); 00681 return HTTP_PARSE; 00682 } 00683 memcpy(scheme, schemePtr, hostPtr - schemePtr); 00684 scheme[hostPtr - schemePtr] = '\0'; 00685 00686 hostPtr+=3; 00687 00688 size_t hostLen = 0; 00689 00690 char* portPtr = strchr(hostPtr, ':'); 00691 if( portPtr != NULL ) 00692 { 00693 hostLen = portPtr - hostPtr; 00694 portPtr++; 00695 if( sscanf(portPtr, "%hu", port) != 1) 00696 { 00697 WARN("Could not find port"); 00698 return HTTP_PARSE; 00699 } 00700 } 00701 else 00702 { 00703 *port=0; 00704 } 00705 char* pathPtr = strchr(hostPtr, '/'); 00706 if( hostLen == 0 ) 00707 { 00708 hostLen = pathPtr - hostPtr; 00709 } 00710 00711 if( maxHostLen < hostLen + 1 ) //including NULL-terminating char 00712 { 00713 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1); 00714 return HTTP_PARSE; 00715 } 00716 memcpy(host, hostPtr, hostLen); 00717 host[hostLen] = '\0'; 00718 00719 size_t pathLen; 00720 char* fragmentPtr = strchr(hostPtr, '#'); 00721 if(fragmentPtr != NULL) 00722 { 00723 pathLen = fragmentPtr - pathPtr; 00724 } 00725 else 00726 { 00727 pathLen = strlen(pathPtr); 00728 } 00729 00730 if( maxPathLen < pathLen + 1 ) //including NULL-terminating char 00731 { 00732 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1); 00733 return HTTP_PARSE; 00734 } 00735 memcpy(path, pathPtr, pathLen); 00736 path[pathLen] = '\0'; 00737 00738 return HTTP_OK; 00739 }
Generated on Wed Jul 13 2022 22:53:16 by
1.7.2
Multi IoT Board