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