Simple IoT Board用のライブラリです。 ESP8266ライブラリの軽量化 送信のみのソフトシリアルライブラリを含んでいます。
Dependents: SITB_HttpGetSample SITB_IFTTTSample SITB_INA226PRC AmbientExampleSITB ... more
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 Tue Jul 12 2022 18:13:35 by 1.7.2