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