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