PullRequest
Dependents: CyaSSL-Twitter-OAuth4Tw TweetTest NetworkThermometer CyaSSL-Twitter-OAuth4Tw_arrange
Fork of HTTPClient by
Diff: HTTPClient.cpp
- Revision:
- 18:d89df40b4cf3
- Parent:
- 17:c73d8e61d391
- Child:
- 19:1e2f05809eb1
--- a/HTTPClient.cpp Mon Apr 07 23:30:35 2014 +0000 +++ b/HTTPClient.cpp Mon Apr 07 23:41:06 2014 +0000 @@ -21,15 +21,15 @@ #if 0 //Enable debug #include <cstdio> -#define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); -#define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); -#define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); +#define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); #else //Disable debug -#define DBG(x, ...) +#define DBG(x, ...) #define WARN(x, ...) -#define ERR(x, ...) +#define ERR(x, ...) #endif @@ -51,7 +51,7 @@ #include "HTTPClient.h" #include "TCPSocketConnection.h" -class TCPSocketConnection_fd: public TCPSocketConnection +class TCPSocketConnection_fd: public TCPSocketConnection { public: int get_fd() { @@ -70,7 +70,7 @@ { int n ; int i ; - #define RECV_RETRY 3 +#define RECV_RETRY 3 for(i=0; i<RECV_RETRY; i++) { n = m_sock.receive(buf, sz) ; if(n >= 0)return n ; @@ -91,11 +91,11 @@ } HTTPClient::HTTPClient() : -m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0) + m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0) { - //CyaSSL_Debugging_ON() ; - ctx = 0 ; - ssl = 0 ; + //CyaSSL_Debugging_ON() ; + ctx = 0 ; + ssl = 0 ; } HTTPClient::~HTTPClient() @@ -106,41 +106,41 @@ #if 0 void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification { - m_basicAuthUser = user; - m_basicAuthPassword = password; + m_basicAuthUser = user; + m_basicAuthPassword = password; } #endif HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking { - return connect(url, HTTP_GET, NULL, pDataIn, timeout); + return connect(url, HTTP_GET, NULL, pDataIn, timeout); } HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking { - HTTPText str(result, maxResultLen); - return get(url, &str, timeout); + HTTPText str(result, maxResultLen); + return get(url, &str, timeout); } HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking { - return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout); + return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout); } HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking { - return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout); + return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout); } HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking { - return connect(url, HTTP_DELETE, NULL, pDataIn, timeout); + return connect(url, HTTP_DELETE, NULL, pDataIn, timeout); } int HTTPClient::getHTTPResponseCode() { - return m_httpResponseCode; + return m_httpResponseCode; } void HTTPClient::setHeader(char * h) @@ -177,654 +177,558 @@ HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request -{ - m_httpResponseCode = 0; //Invalidate code - m_timeout = timeout; - - pDataIn->writeReset(); - if( pDataOut ) - { - pDataOut->readReset(); - } +{ + m_httpResponseCode = 0; //Invalidate code + m_timeout = timeout; - char scheme[8]; - char host[32]; - char path[64]; - - int ret ; + pDataIn->writeReset(); + if( pDataOut ) { + pDataOut->readReset(); + } - //First we need to parse the url (http[s]://host[:port][/[path]]) - HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); - if(res != HTTP_OK) - { - ERR("parseURL returned %d", res); - return res; - } + char scheme[8]; + char host[32]; + char path[64]; + + int ret ; - if(port == 0) //TODO do handle HTTPS->443 - { - if(strcmp(scheme, "http") == 0) - port = HTTP_PORT ; - else if(strcmp(scheme, "https") == 0) - port = HTTPS_PORT ; - } + //First we need to parse the url (http[s]://host[:port][/[path]]) + HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); + if(res != HTTP_OK) { + ERR("parseURL returned %d", res); + return res; + } - DBG("Scheme: %s", scheme); - DBG("Host: %s", host); - DBG("Port: %d", port); - DBG("Path: %s", path); + if(port == 0) { //TODO do handle HTTPS->443 + if(strcmp(scheme, "http") == 0) + port = HTTP_PORT ; + else if(strcmp(scheme, "https") == 0) + port = HTTPS_PORT ; + } - //Connect - DBG("Connecting socket to server"); - sockfd = m_sock.get_fd() ; - - #define MAX_RETRY 5 - int retry ; + DBG("Scheme: %s", scheme); + DBG("Host: %s", host); + DBG("Port: %d", port); + DBG("Path: %s", path); - for(retry=0; retry<MAX_RETRY; retry++) { - int ret = m_sock.connect(host, port); - if(ret == 0)break ; - } - if(retry == MAX_RETRY) - { - m_sock.close(); - ERR("Could not connect"); - return HTTP_CONN; - } + //Connect + DBG("Connecting socket to server"); + sockfd = m_sock.get_fd() ; + +#define MAX_RETRY 5 + int retry ; - if(port == HTTPS_PORT) { - /* Start SSL connect */ - ctx = CyaSSL_CTX_new( - CyaTLSv1_2_client_method - //CyaSSLv3_client_method - ()); - if (ctx == NULL) { - ERR("unable to get ctx"); - return HTTP_CONN; + for(retry=0; retry<MAX_RETRY; retry++) { + int ret = m_sock.connect(host, port); + if(ret == 0)break ; } - CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); - - ssl = CyaSSL_new(ctx); - if (ssl == NULL) { - ERR("unable to get SSL object"); - cyassl_free() ; - return HTTP_CONN; + if(retry == MAX_RETRY) { + m_sock.close(); + ERR("Could not connect"); + return HTTP_CONN; } - CyaSSL_SetVersion(ssl, CYASSL_TLSV1_2) ; - CyaSSL_set_fd(ssl, sockfd); - CyaSSL_SetIORecv(ctx, SocketReceive) ; - CyaSSL_SetIOSend(ctx, SocketSend) ; - DBG("ctx=%x, ssl=%x, ssl->ctx->CBIORecv, CBIOSend=%x, %x\n", - ctx, ssl, SocketReceive, SocketSend ) ; - if (CyaSSL_connect(ssl) != SSL_SUCCESS) { - ERR("SSL_connect failed"); - cyassl_free() ; - return HTTP_CONN; - } - } /* SSL connect complete */ - - //Send request - DBG("Sending request"); - char buf[CHUNK_SIZE]; - send_buf_p = send_buf ; // Reset send buffer ; - - const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":""; - snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request - ret = send(buf); - if(ret) - { - m_sock.close(); - ERR("Could not write request"); - return HTTP_CONN; - } + if(port == HTTPS_PORT) { + /* Start SSL connect */ + ctx = CyaSSL_CTX_new( + CyaTLSv1_2_client_method + //CyaSSLv3_client_method + ()); + if (ctx == NULL) { + ERR("unable to get ctx"); + return HTTP_CONN; + } + CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + + ssl = CyaSSL_new(ctx); + if (ssl == NULL) { + ERR("unable to get SSL object"); + cyassl_free() ; + return HTTP_CONN; + } - //Send all headers + CyaSSL_SetVersion(ssl, CYASSL_TLSV1_2) ; + CyaSSL_set_fd(ssl, sockfd); + CyaSSL_SetIORecv(ctx, SocketReceive) ; + CyaSSL_SetIOSend(ctx, SocketSend) ; + DBG("ctx=%x, ssl=%x, ssl->ctx->CBIORecv, CBIOSend=%x, %x\n", + ctx, ssl, SocketReceive, SocketSend ) ; + if (CyaSSL_connect(ssl) != SSL_SUCCESS) { + ERR("SSL_connect failed"); + cyassl_free() ; + return HTTP_CONN; + } + } /* SSL connect complete */ - //Send default headers - DBG("Sending headers"); - if( pDataOut != NULL ) - { - if( pDataOut->getIsChunked() ) - { - ret = send("Transfer-Encoding: chunked\r\n"); - CHECK_CONN_ERR(ret); - } - else - { - snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen()); - ret = send(buf); - CHECK_CONN_ERR(ret); - } - char type[48]; - if( pDataOut->getDataType(type, 48) == HTTP_OK ) - { - snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type); - ret = send(buf); - CHECK_CONN_ERR(ret); + //Send request + DBG("Sending request"); + char buf[CHUNK_SIZE]; + send_buf_p = send_buf ; // Reset send buffer ; + + const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":""; + snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request + ret = send(buf); + if(ret) { + m_sock.close(); + ERR("Could not write request"); + return HTTP_CONN; } - } - - //Add user headers - if(header) { - ret = send(header); - CHECK_CONN_ERR(ret); - } - //Close headers - DBG("Headers sent"); - ret = send("\r\n"); - CHECK_CONN_ERR(ret); + //Send all headers - size_t trfLen; - - //Send data (if available) - if( pDataOut != NULL ) - { - DBG("Sending data"); - while(true) - { - size_t writtenLen = 0; - pDataOut->read(buf, CHUNK_SIZE, &trfLen); - buf[trfLen] = 0x0 ; - DBG("buf:%s", buf) ; - if( pDataOut->getIsChunked() ) - { - //Write chunk header - char chunkHeader[16]; - snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding - ret = send(chunkHeader); + //Send default headers + DBG("Sending headers"); + if( pDataOut != NULL ) { + if( pDataOut->getIsChunked() ) { + ret = send("Transfer-Encoding: chunked\r\n"); + CHECK_CONN_ERR(ret); + } else { + snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen()); + ret = send(buf); + CHECK_CONN_ERR(ret); + } + char type[48]; + if( pDataOut->getDataType(type, 48) == HTTP_OK ) { + snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type); + ret = send(buf); + CHECK_CONN_ERR(ret); + } + } + + //Add user headers + if(header) { + ret = send(header); CHECK_CONN_ERR(ret); - } - else if( trfLen == 0 ) - { - break; - } - if( trfLen != 0 ) - { - ret = send(buf, trfLen); - CHECK_CONN_ERR(ret); - } - - if( pDataOut->getIsChunked() ) - { - ret = send("\r\n"); //Chunk-terminating CRLF - CHECK_CONN_ERR(ret); - } - else - { - writtenLen += trfLen; - if( writtenLen >= pDataOut->getDataLen() ) - { - break; - } - } - - if( trfLen == 0 ) - { - break; - } } - } - ret = flush() ; // flush the send buffer ; - CHECK_CONN_ERR(ret); - - //Receive response - DBG("Receiving response"); + //Close headers + DBG("Headers sent"); + ret = send("\r\n"); + CHECK_CONN_ERR(ret); - ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes - CHECK_CONN_ERR(ret); - - buf[trfLen] = '\0'; + size_t trfLen; - char* crlfPtr = strstr(buf, "\r\n"); - if(crlfPtr == NULL) - { - PRTCL_ERR(); - } - - int crlfPos = crlfPtr - buf; - buf[crlfPos] = '\0'; - - //Parse HTTP response - if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) - { - //Cannot match string, error - ERR("Not a correct HTTP answer : %s\n", buf); - PRTCL_ERR(); - } + //Send data (if available) + if( pDataOut != NULL ) { + DBG("Sending data"); + while(true) { + size_t writtenLen = 0; + pDataOut->read(buf, CHUNK_SIZE, &trfLen); + buf[trfLen] = 0x0 ; + DBG("buf:%s", buf) ; + if( pDataOut->getIsChunked() ) { + //Write chunk header + char chunkHeader[16]; + snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding + ret = send(chunkHeader); + CHECK_CONN_ERR(ret); + } else if( trfLen == 0 ) { + break; + } + if( trfLen != 0 ) { + ret = send(buf, trfLen); + CHECK_CONN_ERR(ret); + } - if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) ) - { - //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers - WARN("Response code %d", m_httpResponseCode); - PRTCL_ERR(); - } + if( pDataOut->getIsChunked() ) { + ret = send("\r\n"); //Chunk-terminating CRLF + CHECK_CONN_ERR(ret); + } else { + writtenLen += trfLen; + if( writtenLen >= pDataOut->getDataLen() ) { + break; + } + } - DBG("Reading headers"); - - memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well - trfLen -= (crlfPos + 2); + if( trfLen == 0 ) { + break; + } + } - size_t recvContentLength = 0; - bool recvChunked = false; - //Now get headers - while( true ) - { - crlfPtr = strstr(buf, "\r\n"); - if(crlfPtr == NULL) - { - if( trfLen < CHUNK_SIZE - 1 ) - { - size_t newTrfLen; - ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); - trfLen += newTrfLen; - buf[trfLen] = '\0'; - DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); - CHECK_CONN_ERR(ret); - continue; - } - else - { + } + ret = flush() ; // flush the send buffer ; + CHECK_CONN_ERR(ret); + + //Receive response + DBG("Receiving response"); + + ret = recv(buf, CHUNK_SIZE - 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes + CHECK_CONN_ERR(ret); + + buf[trfLen] = '\0'; + + char* crlfPtr = strstr(buf, "\r\n"); + if(crlfPtr == NULL) { PRTCL_ERR(); - } } - crlfPos = crlfPtr - buf; - - if(crlfPos == 0) //End of headers - { - DBG("Headers read"); - memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well - trfLen -= 2; - break; - } - + int crlfPos = crlfPtr - buf; buf[crlfPos] = '\0'; - char key[32]; - char value[32]; - - key[31] = '\0'; - value[31] = '\0'; + //Parse HTTP response + if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 ) { + //Cannot match string, error + ERR("Not a correct HTTP answer : %s\n", buf); + PRTCL_ERR(); + } - int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value); - if ( n == 2 ) - { - DBG("Read header : %s: %s\n", key, value); - if( !strcmp(key, "Content-Length") ) - { - sscanf(value, "%d", &recvContentLength); - pDataIn->setDataLen(recvContentLength); - } - else if( !strcmp(key, "Transfer-Encoding") ) - { - if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) - { - recvChunked = true; - pDataIn->setIsChunked(true); - } - } - else if( !strcmp(key, "Content-Type") ) - { - pDataIn->setDataType(value); - } - - memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well - trfLen -= (crlfPos + 2); - - } - else - { - ERR("Could not parse header"); - PRTCL_ERR(); + if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) ) { + //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers + WARN("Response code %d", m_httpResponseCode); + PRTCL_ERR(); } - } + DBG("Reading headers"); - //Receive data - DBG("Receiving data"); - - while(true) - { - size_t readLen = 0; + memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well + trfLen -= (crlfPos + 2); - if( recvChunked ) - { - //Read chunk header - bool foundCrlf; - do - { - foundCrlf = false; - crlfPos=0; - buf[trfLen]=0; - if(trfLen >= 2) - { - for(; crlfPos < trfLen - 2; crlfPos++) - { - if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) - { - foundCrlf = true; - break; + size_t recvContentLength = 0; + bool recvChunked = false; + //Now get headers + while( true ) { + crlfPtr = strstr(buf, "\r\n"); + if(crlfPtr == NULL) { + if( trfLen < CHUNK_SIZE - 1 ) { + size_t newTrfLen; + ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen); + trfLen += newTrfLen; + buf[trfLen] = '\0'; + DBG("Read %d chars; In buf: [%s]", newTrfLen, buf); + CHECK_CONN_ERR(ret); + continue; + } else { + PRTCL_ERR(); } - } + } + + crlfPos = crlfPtr - buf; + + if(crlfPos == 0) { //End of headers + DBG("Headers read"); + memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well + trfLen -= 2; + break; } - if(!foundCrlf) //Try to read more - { - if( trfLen < CHUNK_SIZE ) - { - size_t newTrfLen; - ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen); - trfLen += newTrfLen; - CHECK_CONN_ERR(ret); - continue; - } - else - { + + buf[crlfPos] = '\0'; + + char key[32]; + char value[32]; + + key[31] = '\0'; + value[31] = '\0'; + + int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value); + if ( n == 2 ) { + DBG("Read header : %s: %s\n", key, value); + if( !strcmp(key, "Content-Length") ) { + sscanf(value, "%d", &recvContentLength); + pDataIn->setDataLen(recvContentLength); + } else if( !strcmp(key, "Transfer-Encoding") ) { + if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") ) { + recvChunked = true; + pDataIn->setIsChunked(true); + } + } else if( !strcmp(key, "Content-Type") ) { + pDataIn->setDataType(value); + } + + memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well + trfLen -= (crlfPos + 2); + + } else { + ERR("Could not parse header"); PRTCL_ERR(); - } } - } while(!foundCrlf); - buf[crlfPos] = '\0'; - int n = sscanf(buf, "%x", &readLen); - if(n!=1) - { - ERR("Could not read chunk length"); - PRTCL_ERR(); - } - memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more - trfLen -= (crlfPos + 2); - - if( readLen == 0 ) - { - //Last chunk - break; - } - } - else - { - readLen = recvContentLength; } - DBG("Retrieving %d bytes", readLen); + //Receive data + DBG("Receiving data"); + + while(true) { + size_t readLen = 0; - do - { - pDataIn->write(buf, MIN(trfLen, readLen)); - if( trfLen > readLen ) - { - memmove(buf, &buf[readLen], trfLen - readLen); - trfLen -= readLen; - readLen = 0; - } - else - { - readLen -= trfLen; - } + if( recvChunked ) { + //Read chunk header + bool foundCrlf; + do { + foundCrlf = false; + crlfPos=0; + buf[trfLen]=0; + if(trfLen >= 2) { + for(; crlfPos < trfLen - 2; crlfPos++) { + if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' ) { + foundCrlf = true; + break; + } + } + } + if(!foundCrlf) { //Try to read more + if( trfLen < CHUNK_SIZE ) { + size_t newTrfLen; + ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen); + trfLen += newTrfLen; + CHECK_CONN_ERR(ret); + continue; + } else { + PRTCL_ERR(); + } + } + } while(!foundCrlf); + buf[crlfPos] = '\0'; + int n = sscanf(buf, "%x", &readLen); + if(n!=1) { + ERR("Could not read chunk length"); + PRTCL_ERR(); + } + + memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more + trfLen -= (crlfPos + 2); - if(readLen) - { - ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen); - CHECK_CONN_ERR(ret); - } - } while(readLen); + if( readLen == 0 ) { + //Last chunk + break; + } + } else { + readLen = recvContentLength; + } + + DBG("Retrieving %d bytes", readLen); + + do { + pDataIn->write(buf, MIN(trfLen, readLen)); + if( trfLen > readLen ) { + memmove(buf, &buf[readLen], trfLen - readLen); + trfLen -= readLen; + readLen = 0; + } else { + readLen -= trfLen; + } - if( recvChunked ) - { - if(trfLen < 2) - { - size_t newTrfLen; - //Read missing chars to find end of chunk - ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen); - CHECK_CONN_ERR(ret); - trfLen += newTrfLen; - } - if( (buf[0] != '\r') || (buf[1] != '\n') ) - { - ERR("Format error"); - PRTCL_ERR(); - } - memmove(buf, &buf[2], trfLen - 2); - trfLen -= 2; - } - else - { - break; + if(readLen) { + ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen); + CHECK_CONN_ERR(ret); + } + } while(readLen); + + if( recvChunked ) { + if(trfLen < 2) { + size_t newTrfLen; + //Read missing chars to find end of chunk + ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen); + CHECK_CONN_ERR(ret); + trfLen += newTrfLen; + } + if( (buf[0] != '\r') || (buf[1] != '\n') ) { + ERR("Format error"); + PRTCL_ERR(); + } + memmove(buf, &buf[2], trfLen - 2); + trfLen -= 2; + } else { + break; + } + } - } - - cyassl_free() ; - m_sock.close(); - DBG("Completed HTTP transaction"); + cyassl_free() ; + m_sock.close(); + DBG("Completed HTTP transaction"); - return HTTP_OK; + return HTTP_OK; } HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure { - DBG("Trying to read between %d and %d bytes", minLen, maxLen); - size_t readLen = 0; - - if(!m_sock.is_connected()) - { - WARN("Connection was closed by server"); - return HTTP_CLOSED; //Connection was closed by server - } - - int ret; - - if(port == HTTPS_PORT) { - DBG("Enter CyaSSL_read") ; - - m_sock.set_blocking(false, m_timeout); - readLen = CyaSSL_read(ssl, buf, maxLen); - if (readLen > 0) { - buf[readLen] = 0; - DBG("CyaSSL_read:%s\n", buf); - } else { - ERR("CyaSSL_read, ret = %d", readLen) ; - return HTTP_ERROR ; + DBG("Trying to read between %d and %d bytes", minLen, maxLen); + size_t readLen = 0; + + if(!m_sock.is_connected()) { + WARN("Connection was closed by server"); + return HTTP_CLOSED; //Connection was closed by server + } + + int ret; + + if(port == HTTPS_PORT) { + DBG("Enter CyaSSL_read") ; + + m_sock.set_blocking(false, m_timeout); + readLen = CyaSSL_read(ssl, buf, maxLen); + if (readLen > 0) { + buf[readLen] = 0; + DBG("CyaSSL_read:%s\n", buf); + } else { + ERR("CyaSSL_read, ret = %d", readLen) ; + return HTTP_ERROR ; + } + DBG("Read %d bytes", readLen); + *pReadLen = readLen; + return HTTP_OK; + } + + while(readLen < maxLen) { + if(readLen < minLen) { + DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen); + m_sock.set_blocking(false, m_timeout); + ret = m_sock.receive_all(buf + readLen, minLen - readLen); + } else { + DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen); + m_sock.set_blocking(false, 0); + ret = m_sock.receive(buf + readLen, maxLen - readLen); + } + + if( ret > 0) { + readLen += ret; + } else if( ret == 0 ) { + break; + } else { + if(!m_sock.is_connected()) { + ERR("Connection error (recv returned %d)", ret); + *pReadLen = readLen; + return HTTP_CONN; + } else { + break; + } + } + + if(!m_sock.is_connected()) { + break; + } } DBG("Read %d bytes", readLen); *pReadLen = readLen; return HTTP_OK; - } - - while(readLen < maxLen) - { - if(readLen < minLen) - { - DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen); - m_sock.set_blocking(false, m_timeout); - ret = m_sock.receive_all(buf + readLen, minLen - readLen); - } - else - { - DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen); - m_sock.set_blocking(false, 0); - ret = m_sock.receive(buf + readLen, maxLen - readLen); - } - - if( ret > 0) - { - readLen += ret; - } - else if( ret == 0 ) - { - break; - } - else - { - if(!m_sock.is_connected()) - { - ERR("Connection error (recv returned %d)", ret); - *pReadLen = readLen; - return HTTP_CONN; - } - else - { - break; - } - } - - if(!m_sock.is_connected()) - { - break; - } - } - DBG("Read %d bytes", readLen); - *pReadLen = readLen; - return HTTP_OK; } HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure { - HTTPResult ret ; - int cp_len ; - - if(len == 0) - { - len = strlen(buf); - } - - do { - if((SEND_BUF_SIZE - (send_buf_p - send_buf)) >= len){ - cp_len = len ; - } else { - cp_len = send_buf_p - send_buf ; + HTTPResult ret ; + int cp_len ; + + if(len == 0) { + len = strlen(buf); } - memcpy(send_buf_p, buf, cp_len) ; - send_buf_p += cp_len ; - len -= cp_len ; - if(send_buf_p == send_buf + SEND_BUF_SIZE){ - ret = flush() ; - if(ret)return(ret) ; - } - } while(len) ; - return HTTP_OK ; + do { + if((SEND_BUF_SIZE - (send_buf_p - send_buf)) >= len) { + cp_len = len ; + } else { + cp_len = send_buf_p - send_buf ; + } + memcpy(send_buf_p, buf, cp_len) ; + send_buf_p += cp_len ; + len -= cp_len ; + + if(send_buf_p == send_buf + SEND_BUF_SIZE) { + ret = flush() ; + if(ret)return(ret) ; + } + } while(len) ; + return HTTP_OK ; } HTTPResult HTTPClient::flush() //0 on success, err code on failure { - int len ; - char * buf ; - - buf = send_buf ; - len = send_buf_p - send_buf ; - send_buf_p = send_buf ; // reset send buffer - - DBG("Trying to write %d bytes:%s\n", len, buf); - size_t writtenLen = 0; - - if(!m_sock.is_connected()) - { - WARN("Connection was closed by server"); - return HTTP_CLOSED; //Connection was closed by server - } - - if(port == HTTPS_PORT) { - DBG("Enter CyaSSL_write") ; - if (CyaSSL_write(ssl, buf, len) != len) { - ERR("SSL_write failed"); - return HTTP_ERROR ; + int len ; + char * buf ; + + buf = send_buf ; + len = send_buf_p - send_buf ; + send_buf_p = send_buf ; // reset send buffer + + DBG("Trying to write %d bytes:%s\n", len, buf); + size_t writtenLen = 0; + + if(!m_sock.is_connected()) { + WARN("Connection was closed by server"); + return HTTP_CLOSED; //Connection was closed by server } + + if(port == HTTPS_PORT) { + DBG("Enter CyaSSL_write") ; + if (CyaSSL_write(ssl, buf, len) != len) { + ERR("SSL_write failed"); + return HTTP_ERROR ; + } + DBG("Written %d bytes", writtenLen); + return HTTP_OK; + } + m_sock.set_blocking(false, m_timeout); + int ret = m_sock.send_all(buf, len); + if(ret > 0) { + writtenLen += ret; + } else if( ret == 0 ) { + WARN("Connection was closed by server"); + return HTTP_CLOSED; //Connection was closed by server + } else { + ERR("Connection error (send returned %d)", ret); + return HTTP_CONN; + } + DBG("Written %d bytes", writtenLen); return HTTP_OK; - } - m_sock.set_blocking(false, m_timeout); - int ret = m_sock.send_all(buf, len); - if(ret > 0) - { - writtenLen += ret; - } - else if( ret == 0 ) - { - WARN("Connection was closed by server"); - return HTTP_CLOSED; //Connection was closed by server - } - else - { - ERR("Connection error (send returned %d)", ret); - return HTTP_CONN; - } - - DBG("Written %d bytes", writtenLen); - return HTTP_OK; } 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 { - char* schemePtr = (char*) url; - char* hostPtr = (char*) strstr(url, "://"); - if(hostPtr == NULL) - { - WARN("Could not find host"); - return HTTP_PARSE; //URL is invalid - } + char* schemePtr = (char*) url; + char* hostPtr = (char*) strstr(url, "://"); + if(hostPtr == NULL) { + WARN("Could not find host"); + return HTTP_PARSE; //URL is invalid + } + + if( maxSchemeLen < hostPtr - schemePtr + 1 ) { //including NULL-terminating char + WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1); + return HTTP_PARSE; + } + memcpy(scheme, schemePtr, hostPtr - schemePtr); + scheme[hostPtr - schemePtr] = '\0'; - if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char - { - WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1); - return HTTP_PARSE; - } - memcpy(scheme, schemePtr, hostPtr - schemePtr); - scheme[hostPtr - schemePtr] = '\0'; + hostPtr+=3; - hostPtr+=3; + size_t hostLen = 0; - size_t hostLen = 0; - - char* portPtr = strchr(hostPtr, ':'); - if( portPtr != NULL ) - { - hostLen = portPtr - hostPtr; - portPtr++; - if( sscanf(portPtr, "%hu", port) != 1) - { - WARN("Could not find port"); - return HTTP_PARSE; + char* portPtr = strchr(hostPtr, ':'); + if( portPtr != NULL ) { + hostLen = portPtr - hostPtr; + portPtr++; + if( sscanf(portPtr, "%hu", port) != 1) { + WARN("Could not find port"); + return HTTP_PARSE; + } + } else { + *port=0; } - } - else - { - *port=0; - } - char* pathPtr = strchr(hostPtr, '/'); - if( hostLen == 0 ) - { - hostLen = pathPtr - hostPtr; - } + char* pathPtr = strchr(hostPtr, '/'); + if( hostLen == 0 ) { + hostLen = pathPtr - hostPtr; + } - if( maxHostLen < hostLen + 1 ) //including NULL-terminating char - { - WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1); - return HTTP_PARSE; - } - memcpy(host, hostPtr, hostLen); - host[hostLen] = '\0'; + if( maxHostLen < hostLen + 1 ) { //including NULL-terminating char + WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1); + return HTTP_PARSE; + } + memcpy(host, hostPtr, hostLen); + host[hostLen] = '\0'; - size_t pathLen; - char* fragmentPtr = strchr(hostPtr, '#'); - if(fragmentPtr != NULL) - { - pathLen = fragmentPtr - pathPtr; - } - else - { - pathLen = strlen(pathPtr); - } + size_t pathLen; + char* fragmentPtr = strchr(hostPtr, '#'); + if(fragmentPtr != NULL) { + pathLen = fragmentPtr - pathPtr; + } else { + pathLen = strlen(pathPtr); + } - if( maxPathLen < pathLen + 1 ) //including NULL-terminating char - { - WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1); - return HTTP_PARSE; - } - memcpy(path, pathPtr, pathLen); - path[pathLen] = '\0'; + if( maxPathLen < pathLen + 1 ) { //including NULL-terminating char + WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1); + return HTTP_PARSE; + } + memcpy(path, pathPtr, pathLen); + path[pathLen] = '\0'; - return HTTP_OK; + return HTTP_OK; }