(file) Return to httpclient.c CVS log (file) (dir) Up to [OMI] / omi / http

Diff for /omi/http/httpclient.c between version 1.2 and 1.3

version 1.2, 2015/04/20 18:10:13 version 1.3, 2015/04/20 18:19:52
Line 24 
Line 24 
  
 #include <assert.h> #include <assert.h>
 #include <ctype.h> #include <ctype.h>
 //#include "http.h"  #include "httpcommon.h"
 #include "httpclient.h" #include "httpclient.h"
 #include <sock/addr.h> #include <sock/addr.h>
 #include <sock/sock.h> #include <sock/sock.h>
 #include <sock/selector.h> #include <sock/selector.h>
 #include <base/time.h>  #include <pal/sleep.h>
 #include <base/buf.h> #include <base/buf.h>
 #include <base/log.h> #include <base/log.h>
 #include <base/result.h> #include <base/result.h>
 #include <base/strings.h>  #include <pal/strings.h>
 #include <base/io.h>  #include <pal/format.h>
   #include <pal/sleep.h>
 #include <base/paths.h> #include <base/paths.h>
  
   // #define ENABLE_TRACING 1
   #ifdef ENABLE_TRACING
   # define TRACING_LEVEL 4
   # include <deprecated/logging/logging.h>
   #else
   # define LOGE2(a)
   # define LOGW2(a)
   # define LOGD2(a)
   # define LOGX2(a)
   #endif
   
 #ifdef CONFIG_POSIX #ifdef CONFIG_POSIX
 #include <openssl/ssl.h> #include <openssl/ssl.h>
 #include <openssl/err.h> #include <openssl/err.h>
Line 75 
Line 87 
  
 #endif #endif
  
 #define T MI_T  
   
 /* #define ENABLE_TRACING  // */  
 #ifdef  ENABLE_TRACING  
 #define PRINTF(a)  TIMESTAMP(); printf a  
 #define TIMESTAMP() \  
 {\  
         MI_Uint64 currentTimeUsec = 0;\  
 \  
         Time_Now(&currentTimeUsec);\  
         currentTimeUsec /= 1000;    /* ms */ \  
         printf("%ds%03dms ", (int)(currentTimeUsec / 1000 % 1000), (int)(currentTimeUsec % 1000));\  
 }  
   
 #define PRINTF_2(a)  
 #else  
 #define PRINTF(a)  
 #define PRINTF_2(a)  
 #endif  
   
   
   
 /* /*
 **============================================================================== **==============================================================================
 ** **
Line 119 
Line 109 
 } }
 Http_RecvState; Http_RecvState;
  
 typedef struct _Http_SR_SocketData  typedef struct _HttpClient_SR_SocketData
 { {
     /* based member*/     /* based member*/
     Handler     base;     Handler     base;
Line 133 
Line 123 
     MI_Boolean  connectDone;     MI_Boolean  connectDone;
  
     /* receiving data */     /* receiving data */
     char*       recvBuffer;      __field_ecount(recvBufferSize) char* recvBuffer;
     size_t      recvBufferSize;     size_t      recvBufferSize;
     size_t      recvievedSize;      size_t      receivedSize;
     Http_RecvState      recvingState;     Http_RecvState      recvingState;
     HttpClientHeaderField recvHeaderFields[64];     HttpClientHeaderField recvHeaderFields[64];
     HttpClientResponseHeader   recvHeaders;     HttpClientResponseHeader   recvHeaders;
     MI_Sint64   contentLength;     MI_Sint64   contentLength;
       MI_Sint64   contentBegin;
       MI_Sint64   contentEnd;
       MI_Sint64   contentTotalLength;
     Page*   recvPage;     Page*   recvPage;
  
       /* flag for a response from a HEAD request */
       MI_Boolean  headVerb;
   
     /* sending part */     /* sending part */
     Page*   sendPage;     Page*   sendPage;
     Page*   sendHeader;     Page*   sendHeader;
Line 152 
Line 148 
     MI_Result status;     MI_Result status;
  
 } }
 Http_SR_SocketData;  HttpClient_SR_SocketData;
  
 struct _HttpClient struct _HttpClient
 { {
Line 164 
Line 160 
     void*                               callbackData;     void*                               callbackData;
     SSL_CTX*    sslContext;     SSL_CTX*    sslContext;
  
     Http_SR_SocketData* connector;      HttpClient_SR_SocketData* connector;
  
     MI_Boolean  internalSelectorUsed;     MI_Boolean  internalSelectorUsed;
 }; };
Line 173 
Line 169 
 /* helper functions result */ /* helper functions result */
 typedef enum _Http_CallbackResult typedef enum _Http_CallbackResult
 { {
     PRT_CONTINUE,      PRT_RETURN_FALSE,
     PRT_RETURN_TRUE,     PRT_RETURN_TRUE,
     PRT_RETURN_FALSE      PRT_CONTINUE
 } }
 Http_CallbackResult; Http_CallbackResult;
  
Line 187 
Line 183 
  
 #define _HashCode(first,last,len) ( (((MI_Uint8)first) << 16) | (((MI_Uint8)last) << 8)  | (((MI_Uint16)len)) ) #define _HashCode(first,last,len) ( (((MI_Uint8)first) << 16) | (((MI_Uint8)last) << 8)  | (((MI_Uint16)len)) )
  
   _Return_type_success_(return == MI_TRUE)
 static MI_Boolean _getNameValuePair( static MI_Boolean _getNameValuePair(
     char ** line,      _Inout_ CharPtr* line,
     char ** value,      _Out_ CharPtr* value,
     int*  nameHashCode )      _Out_ int*  nameHashCode)
 { {
     int len = 0;     int len = 0;
     char* p;     char* p;
     /* find name end /hash-code */     /* find name end /hash-code */
  
       if ((*line)[0] == '\0')
       {
           return MI_FALSE;
       }
   
     *nameHashCode =  _ToLower((MI_Uint8)(*line)[0])<<16;     *nameHashCode =  _ToLower((MI_Uint8)(*line)[0])<<16;
  
     for (len = 1; (*line)[len] != ':' && (*line)[len] != '\r'; len++ )      for (len = 1; (*line)[len] != '\0' && (*line)[len] != ':' && (*line)[len] != '\r'; len++)
         ;         ;
  
     if ((*line)[len] != ':')     if ((*line)[len] != ':')
Line 215 
Line 217 
     *value = p;     *value = p;
  
     /* skip to end of line */     /* skip to end of line */
     for ( ; ; )      for ( ; p[0]; )
     {     {
         if (p[0] == '\r' && p[1] == '\n' &&          if (p[0] != '\0' && p[1] != '\0' && p[2] != '\0' &&
             (p[2] != ' ' && p[2] != '\t') )              p[0] == '\r' && p[1] == '\n' &&
               p[2] != ' '  && p[2] != '\t')
         {         {
             p[0] = 0;              p[0] = '\0';
             (*line) = p + 2;             (*line) = p + 2;
             break;             break;
         }         }
Line 229 
Line 232 
  
     /* remove trailing spaces */     /* remove trailing spaces */
     p--;     p--;
   #ifdef _PREFAST_
   #pragma prefast (push)
   #pragma prefast (disable: 26001)
   #endif
       /* disabling IPv6 OACR warnings - D3M bug 56 */
     while (p[0] == ' ' || p[0] == '\t')     while (p[0] == ' ' || p[0] == '\t')
         p--;         p--;
   #ifdef _PREFAST_
   #pragma prefast (pop)
   #endif
  
     p[1] = 0;      p[1] = '\0';
  
     return MI_TRUE;     return MI_TRUE;
 } }
  
   
 static MI_Boolean _getHeaderField( static MI_Boolean _getHeaderField(
     Http_SR_SocketData* handler,      HttpClient_SR_SocketData* handler,
     char ** line)      _Inout_ CharPtr* line)
 { {
     /* expecting  Request-Line = Method SP Request-URI SP HTTP-Version CRLF     /* expecting  Request-Line = Method SP Request-URI SP HTTP-Version CRLF
         Read more: http://www.faqs.org/rfcs/rfc2616.html#ixzz0jKdjJdZv         Read more: http://www.faqs.org/rfcs/rfc2616.html#ixzz0jKdjJdZv
Line 252 
Line 262 
     if (!_getNameValuePair(line, &value, &nameHashCode))     if (!_getNameValuePair(line, &value, &nameHashCode))
         return MI_FALSE;         return MI_FALSE;
  
   
     if (nameHashCode == _HashCode('c','h',14) && /*Content-Length*/     if (nameHashCode == _HashCode('c','h',14) && /*Content-Length*/
         Strcasecmp(name,"Content-Length") == 0)         Strcasecmp(name,"Content-Length") == 0)
     {     {
             handler->contentLength = Strtoull(value, NULL, 10);             handler->contentLength = Strtoull(value, NULL, 10);
             /*if ( handler->contentLength > HTTP_MAX_CONTENT )             /*if ( handler->contentLength > HTTP_MAX_CONTENT )
           handler->contentBegin = -1;
           handler->contentEnd = -1;
           handler->contentTotalLength = -1;
                 return MI_FALSE;*/                 return MI_FALSE;*/
     }     }
     else if (nameHashCode == _HashCode('t','g',17) && /*Transfer-Encoding*/     else if (nameHashCode == _HashCode('t','g',17) && /*Transfer-Encoding*/
         Strcasecmp(name,"Transfer-Encoding") == 0)         Strcasecmp(name,"Transfer-Encoding") == 0)
     {     {
             handler->contentLength = -1;             handler->contentLength = -1;
           handler->contentBegin = -1;
           handler->contentEnd = -1;
           handler->contentTotalLength = -1;
       }
       else if (nameHashCode == _HashCode('c','e',13) && /*Content-Range*/
           Strcasecmp(name, "Content-Range") == 0)
       {
           char* delimptr;
           char* endptr;
           handler->contentEnd = -1;
           handler->contentBegin = (MI_Sint64)Strtoull(value, NULL, 10);
           delimptr = strchr(value, '-');
           endptr = strchr(value, '\n');
           if (delimptr != NULL && (endptr == NULL || endptr > delimptr))
               handler->contentEnd = Strtoull(++delimptr, NULL, 10);
           delimptr = strchr(value, '/');
           if (delimptr != NULL && (endptr == NULL || endptr > delimptr))
               handler->contentTotalLength = Strtoull(++delimptr, NULL, 10);
     }     }
   
     else  
     {  
         if (handler->recvHeaders.sizeHeaders < MI_COUNT(handler->recvHeaderFields))         if (handler->recvHeaders.sizeHeaders < MI_COUNT(handler->recvHeaderFields))
         {         {
             handler->recvHeaderFields[handler->recvHeaders.sizeHeaders].name = name;             handler->recvHeaderFields[handler->recvHeaders.sizeHeaders].name = name;
Line 276 
Line 303 
         }         }
         else         else
         {         {
             LOGW_CHAR(("too many http headers; skipping %s: %s\n", name, value));          trace_TooManyHttpHeaders(scs(name), scs(value));
         }  
     }     }
  
     return MI_TRUE;     return MI_TRUE;
Line 310 
Line 336 
  
  
 static MI_Boolean _getRequestLine( static MI_Boolean _getRequestLine(
     Http_SR_SocketData* handler,      HttpClient_SR_SocketData* handler,
     char ** line)      _Inout_ CharPtr* line)
 { {
     size_t index;     size_t index;
     /* expecting  Request-Line = Method SP Request-URI SP HTTP-Version CRLF     /* expecting  Request-Line = Method SP Request-URI SP HTTP-Version CRLF
Line 330 
Line 356 
  
                 Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF                 Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
         */         */
         const char* s = *line + 9; /*+ HTTP/1.1<sp>*/          const char* s = *line; /*+ HTTP/1.1<sp>*/
           size_t skips = 9;
           for (; skips > 0; s++)
           {
               skips--;
               if (!*s)
               {
                   return MI_FALSE;
               }
           }
  
         handler->recvHeaders.httpError = Strtoul(s, NULL, 10);         handler->recvHeaders.httpError = Strtoul(s, NULL, 10);
     }     }
  
     /* skip to end of line */     /* skip to end of line */
     for ( index = 1; index < handler->recvievedSize; index++ )      for (index = 1; (*line)[index] && index < handler->receivedSize; index++)
     {     {
         if ((*line)[index-1] == '\r' && (*line)[index] == '\n' )         if ((*line)[index-1] == '\r' && (*line)[index] == '\n' )
         {         {
Line 349 
Line 384 
 } }
  
 static MI_Result _Sock_Read( static MI_Result _Sock_Read(
     Http_SR_SocketData* handler,      HttpClient_SR_SocketData* handler,
     void* buf,     void* buf,
     size_t buf_size,     size_t buf_size,
     size_t* sizeRead)     size_t* sizeRead)
 { {
     int res;     int res;
       int sslError;
  
     if (!handler->ssl)      if (handler->ssl == NULL)
         return Sock_Read(handler->base.sock, buf, buf_size, sizeRead);      {
           MI_Result res = Sock_Read(handler->base.sock, buf, buf_size, sizeRead);
   
           LOGD2((ZT("_Sock_Read - After regular read. socket: %d, result: %d (%s), bytes read: %u / %u"), handler->base.sock, (int)res, mistrerror(res), (unsigned int)*sizeRead, (unsigned int)buf_size));
           return res;
       }
  
     handler->base.mask &= ~SELECTOR_WRITE;     handler->base.mask &= ~SELECTOR_WRITE;
     handler->base.mask |= SELECTOR_READ;     handler->base.mask |= SELECTOR_READ;
Line 366 
Line 407 
     *sizeRead = 0;     *sizeRead = 0;
  
     res = SSL_read(handler->ssl, buf, buf_size);     res = SSL_read(handler->ssl, buf, buf_size);
     PRINTF(("ssl read %d\n", res));      LOGD2((ZT("_Sock_Read - SSL_Read returned: %d (< 0 for error) / %u bytes read, errno: %d (%s)"), res, (unsigned int)buf_size, errno, strerror(errno)));
   
     if ( res == 0 )     if ( res == 0 )
       {
           LOGW2((ZT("_Sock_Read - SSL socket connection closed. socket: %d"), handler->base.sock));
         return MI_RESULT_OK;    /* connection closed */         return MI_RESULT_OK;    /* connection closed */
       }
  
     if ( res > 0 )     if ( res > 0 )
     {     {
           LOGD2((ZT("_Sock_read - Bytes read: %d"), res));
         *sizeRead = res;         *sizeRead = res;
         return MI_RESULT_OK;    /* ok */         return MI_RESULT_OK;    /* ok */
     }     }
  
     switch (SSL_get_error(handler->ssl, res))      sslError = SSL_get_error(handler->ssl, res);
       switch (sslError)
     {     {
     case SSL_ERROR_WANT_WRITE:     case SSL_ERROR_WANT_WRITE:
         handler->reverseOperations = MI_TRUE;   /* wait until write is allowed */         handler->reverseOperations = MI_TRUE;   /* wait until write is allowed */
         handler->base.mask &= ~SELECTOR_READ;         handler->base.mask &= ~SELECTOR_READ;
         handler->base.mask |= SELECTOR_WRITE;         handler->base.mask |= SELECTOR_WRITE;
         PRINTF(("ssl read/accept WANT_WRITE\n"));          LOGD2((ZT("_Sock_Read - SSL_read/accept returned WANT_WRITE")));
         return MI_RESULT_WOULD_BLOCK;         return MI_RESULT_WOULD_BLOCK;
  
     case SSL_ERROR_WANT_READ:     case SSL_ERROR_WANT_READ:
         PRINTF(("ssl read/accept WANT_READ\n"));          LOGD2((ZT("Sock_Read - SSL_read/accept returned WANT_READ")));
         return MI_RESULT_WOULD_BLOCK;         return MI_RESULT_WOULD_BLOCK;
  
     case SSL_ERROR_SYSCALL:     case SSL_ERROR_SYSCALL:
Line 396 
Line 441 
             EINPROGRESS == errno)             EINPROGRESS == errno)
             return MI_RESULT_WOULD_BLOCK;             return MI_RESULT_WOULD_BLOCK;
  
         LOGW_CHAR(("ssl-read: unexpected sys error %d\n", errno));          LOGE2((ZT("Sock_Read - SSL_read returned OS error %d (%s)"), errno, strerror(errno)));
           trace_SSLRead_UnexpectedSysError(errno);
         break;         break;
  
     default:     default:
           /* print Open SSL error stack */
         {         {
             /* print error */              unsigned long err;
             unsigned long err = ERR_get_error();              while ((err = ERR_get_error()) != 0)
             while (err)  
             {             {
                 char err_txt[200];                 char err_txt[200];
                 ERR_error_string_n(err, err_txt, sizeof(err_txt));  
   
                 LOGW_CHAR(("ssl-read error: %d [%s]\n", (int)err, err_txt));  
  
                 err = ERR_get_error();                  ERR_error_string_n(err, err_txt, sizeof (err_txt));
                   LOGE2((ZT("_Sock_Read - SSL_read returned OpenSSL error: %lu (%s)"), err, err_txt));
             }             }
         }         }
         break;         break;
Line 419 
Line 463 
 } }
  
 static MI_Result _Sock_Write( static MI_Result _Sock_Write(
     Http_SR_SocketData* handler,      HttpClient_SR_SocketData* handler,
     void* buf,     void* buf,
     size_t buf_size,     size_t buf_size,
     size_t* sizeWritten)     size_t* sizeWritten)
 { {
     int res;     int res;
       int sslError;
  
     if (!handler->ssl)     if (!handler->ssl)
         return Sock_Write(handler->base.sock, buf, buf_size, sizeWritten);      {
           MI_Result res = Sock_Write(handler->base.sock, buf, buf_size, sizeWritten);
           LOGD2((ZT("_Sock_Write - Non-SSS write. Sock_Write returned %d (%s). %u / %u bytes sent"), res, mistrerror(res), (unsigned int)*sizeWritten, (unsigned int)buf_size));
           return res;
       }
  
     /* Do not clear READ flag, since 'close' notification     /* Do not clear READ flag, since 'close' notification
     delivered as READ event */     delivered as READ event */
Line 440 
Line 489 
     if (handler->connectDone)     if (handler->connectDone)
     {     {
         res = SSL_write(handler->ssl, buf, buf_size);         res = SSL_write(handler->ssl, buf, buf_size);
         PRINTF(("ssl write %d\n", res));          LOGD2((ZT("_Sock_Write - SSL_write using socket %d returned %d (< 0 for error) / %u bytes written, errno: %d (%s)"), handler->base.sock, res, (unsigned int)buf_size, errno, strerror(errno)));
     }     }
     else     else
     {     {
         res = SSL_connect(handler->ssl);         res = SSL_connect(handler->ssl);
         PRINTF(("ssl connect %d\n", res));          LOGD2((ZT("_Sock_Write - SSL connect using socket %d returned result: %d, errno: %d (%s)"), handler->base.sock, res, errno, strerror(errno)));
         if ( res > 0 )         if ( res > 0 )
         {         {
             /* we are done with accpet */              /* we are done with accept */
             handler->connectDone = MI_TRUE;             handler->connectDone = MI_TRUE;
             return _Sock_Write(handler,buf,buf_size,sizeWritten);             return _Sock_Write(handler,buf,buf_size,sizeWritten);
         }         }
Line 457 
Line 506 
  
  
     if ( res == 0 )     if ( res == 0 )
       {
           LOGW2((ZT("_Sock_Write - SSL socket connection closed")));
         return MI_RESULT_OK;    /* connection closed */         return MI_RESULT_OK;    /* connection closed */
       }
  
     if ( res > 0 )     if ( res > 0 )
     {     {
         *sizeWritten = res;         *sizeWritten = res;
           LOGD2((ZT("_Sock_Write - SSL socket successful write of %d / %u bytes"), res, (unsigned int)buf_size));
         return MI_RESULT_OK;    /* ok */         return MI_RESULT_OK;    /* ok */
     }     }
  
     switch (SSL_get_error(handler->ssl, res))      sslError = SSL_get_error(handler->ssl, res);
       switch (sslError)
     {     {
     case SSL_ERROR_WANT_WRITE:     case SSL_ERROR_WANT_WRITE:
         PRINTF(("ssl write/connetc WANT_WRITE\n"));          LOGD2((ZT("_Sock_Write - SSL_write/connect returned WANT_WRITE")));
         return MI_RESULT_WOULD_BLOCK;         return MI_RESULT_WOULD_BLOCK;
  
     case SSL_ERROR_WANT_READ:     case SSL_ERROR_WANT_READ:
         PRINTF(("ssl write/connetc WANT_READ\n"));          LOGD2((ZT("_Sock_Write - SSL_write/connect returned WANT_READ")));
         handler->reverseOperations = MI_TRUE;   /* wait until write is allowed */         handler->reverseOperations = MI_TRUE;   /* wait until write is allowed */
         handler->base.mask |= SELECTOR_READ;         handler->base.mask |= SELECTOR_READ;
         handler->base.mask &= ~SELECTOR_WRITE;         handler->base.mask &= ~SELECTOR_WRITE;
Line 482 
Line 536 
         if (EAGAIN == errno ||         if (EAGAIN == errno ||
             EWOULDBLOCK == errno ||             EWOULDBLOCK == errno ||
             EINPROGRESS == errno)             EINPROGRESS == errno)
           {
               LOGD2((ZT("_Sock_Write - Returning WOULD_BLOCK. errno: %d (%s)"), errno, strerror(errno)));
             return MI_RESULT_WOULD_BLOCK;             return MI_RESULT_WOULD_BLOCK;
           }
   
           LOGE2((ZT("_Sock_Write - SSL_write/connect returned unexpected OS error %d (%s)"), errno, strerror(errno)));
           trace_SSLWrite_UnexpectedSysError(errno);
           break;
  
         LOGW_CHAR(("ssl-write: unexpected sys error %d\n", errno));      case SSL_ERROR_SSL:
           LOGE2((ZT("_Sock_Write - SSL_write/connect returned OpenSSL error %d (%s)"), sslError, ERR_error_string(sslError, NULL)));
         break;         break;
  
     default:     default:
           LOGD2((ZT("_Sock_Write - SSL_write/connect returned uncategorized OpenSSL error: %d"), res));
         break;         break;
     }     }
   
     return MI_RESULT_FAILED;     return MI_RESULT_FAILED;
 } }
  
 static Http_CallbackResult _ReadHeader( static Http_CallbackResult _ReadHeader(
     Http_SR_SocketData* handler)      HttpClient_SR_SocketData* handler)
 { {
     char* buf;     char* buf;
     char* currentLine;     char* currentLine;
     char* data;     char* data;
       size_t contentSize;
     size_t buf_size, received, index;     size_t buf_size, received, index;
     MI_Result r;     MI_Result r;
     MI_Boolean fullHeaderReceived = MI_FALSE;     MI_Boolean fullHeaderReceived = MI_FALSE;
Line 507 
Line 572 
     if (handler->recvingState != RECV_STATE_HEADER)     if (handler->recvingState != RECV_STATE_HEADER)
         return PRT_CONTINUE;         return PRT_CONTINUE;
  
     buf = handler->recvBuffer + handler->recvievedSize;      buf = handler->recvBuffer + handler->receivedSize;
     buf_size = handler->recvBufferSize - handler->recvievedSize;      buf_size = handler->recvBufferSize - handler->receivedSize;
     received = 0;     received = 0;
  
     r = _Sock_Read(handler, buf, buf_size, &received);     r = _Sock_Read(handler, buf, buf_size, &received);
     PRINTF(("%d: read r = %d, recv = %d; reverse %d\n", (int)handler->base.sock, (int)r, (int)received, (int)handler->reverseOperations ));      LOGD2((ZT("_ReadHeader - Begin. _Sock_read result: %d (%s), socket: %d, %u / %u bytes read, reverse: %d"), (int)r, mistrerror(r), (int)handler->base.sock, (unsigned int)received, (unsigned int)buf_size, (int)handler->reverseOperations));
  
     if ( r == MI_RESULT_OK && 0 == received )     if ( r == MI_RESULT_OK && 0 == received )
         return PRT_RETURN_FALSE; /* conection closed */      {
           LOGW2((ZT("_ReadHeader - 0 bytes received without error. Socket closed?")));
           return PRT_RETURN_FALSE; /* connection closed */
       }
  
     if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )     if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
       {
           LOGE2((ZT("_ReadHeader - Error %d (%s)"), r, mistrerror(r)));
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
       }
  
     if (!received)      if (received == 0)
       {
           LOGD2((ZT("_ReadHeader - 0 bytes received. Waiting...")));
         return PRT_RETURN_TRUE;         return PRT_RETURN_TRUE;
       }
  
     handler->recvievedSize += received;      handler->receivedSize += received;
  
     /* check header */     /* check header */
     PRINTF_2(("%s\n",buf));      LOGD2((ZT("_ReadHeader - Received buffer: %s"), buf));
  
     /* did we get full header? */     /* did we get full header? */
     buf = handler->recvBuffer;     buf = handler->recvBuffer;
     for ( index = 3; index < handler->recvievedSize; index++ )      LOGD2((ZT("_ReadHeader - Checking for full header...")));
       for ( index = 3; index < handler->receivedSize; index++ )
     {     {
           _Analysis_assume_(handler->recvBufferSize > 3);
         if (buf[index-3] == '\r' && buf[index-1] == '\r' &&         if (buf[index-3] == '\r' && buf[index-1] == '\r' &&
             buf[index-2] == '\n' && buf[index] == '\n' )             buf[index-2] == '\n' && buf[index] == '\n' )
         {         {
             fullHeaderReceived = MI_TRUE;             fullHeaderReceived = MI_TRUE;
               LOGD2((ZT("_ReadHeader - Full header has been received")));
             break;             break;
         }         }
     }     }
  
     if (!fullHeaderReceived )     if (!fullHeaderReceived )
     {     {
         if ( handler->recvievedSize <  handler->recvBufferSize )          if (handler->receivedSize <  handler->recvBufferSize)
           {
               LOGD2((ZT("_ReadHeader - Full header not received. Waiting...")));
             return PRT_RETURN_TRUE; /* continue reading */             return PRT_RETURN_TRUE; /* continue reading */
           }
  
         if ( handler->recvBufferSize < MAX_HEADER_SIZE )         if ( handler->recvBufferSize < MAX_HEADER_SIZE )
         {         {
             buf = realloc(handler->recvBuffer, handler->recvBufferSize * 2);              LOGD2((ZT("_ReadHeader - Reallocating buffer...")));
               buf = PAL_Realloc(handler->recvBuffer, handler->recvBufferSize * 2);
  
             if (!buf)             if (!buf)
               {
                   LOGE2((ZT("_ReadHeader - Cannot allocate memory for larger header")));
                 return PRT_RETURN_FALSE;                 return PRT_RETURN_FALSE;
               }
  
             handler->recvBufferSize *= 2;             handler->recvBufferSize *= 2;
             handler->recvBuffer = buf;             handler->recvBuffer = buf;
               LOGD2((ZT("_ReadHeader - Going recursive...")));
             return _ReadHeader(handler);             return _ReadHeader(handler);
         }         }
         else         else
         {         {
             /* http header is too big - drop connection */              /* Http header is too big - drop connection */
             LOGW((T("http header is too big; dropping connection\n")));              trace_HttpHeaderIsTooBig();
               LOGE2((ZT("_ReadHeader - HTTP header is too big. Dropping connection")));
             return PRT_RETURN_FALSE;             return PRT_RETURN_FALSE;
         }         }
     }     }
Line 569 
Line 655 
     data = buf + index + 1; /* pointer to data in case we got some */     data = buf + index + 1; /* pointer to data in case we got some */
  
     if (!_getRequestLine(handler, &currentLine))     if (!_getRequestLine(handler, &currentLine))
       {
           LOGE2((ZT("_ReadHeader - Cannot find request line in HTTP header")));
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
       }
  
     while ((data-currentLine) > 3)     while ((data-currentLine) > 3)
     {     {
         if (!_getHeaderField(handler, &currentLine))         if (!_getHeaderField(handler, &currentLine))
           {
               LOGE2((ZT("_ReadHeader - Cannot find HTTP header field")));
             return PRT_RETURN_FALSE;             return PRT_RETURN_FALSE;
           }
     }     }
  
     /* Check if we have to deal with chunked-encoded data */     /* Check if we have to deal with chunked-encoded data */
     if (handler->contentLength < 0)     if (handler->contentLength < 0)
     {     {
         handler->recvievedSize -= index + 1;          handler->receivedSize -= index + 1;
  
         /* Invoke user's callback with header information */         /* Invoke user's callback with header information */
         {         {
Line 590 
Line 680 
  
             if (!(*self->callbackOnResponse)( self, self->callbackData, &handler->recvHeaders,             if (!(*self->callbackOnResponse)( self, self->callbackData, &handler->recvHeaders,
                 handler->contentLength, handler->contentLength == 0, 0))                 handler->contentLength, handler->contentLength == 0, 0))
               {
                   LOGD2((ZT("_ReadHeader - On response callback for chunked data header failed")));
                 return PRT_RETURN_FALSE;                 return PRT_RETURN_FALSE;
         }         }
           }
  
         /* remove consumed header part */         /* remove consumed header part */
         memmove(handler->recvBuffer, data, handler->recvievedSize);          memmove(handler->recvBuffer, data, handler->receivedSize);
  
         handler->recvingState = RECV_STATE_CHUNKHEADER;         handler->recvingState = RECV_STATE_CHUNKHEADER;
         return PRT_CONTINUE;         return PRT_CONTINUE;
     }     }
  
       contentSize = (size_t)handler->contentLength;
       if (handler->headVerb)
       {
           LOGD2((ZT("_ReadHeader - HEAD response received. Download will contain %u bytes"), (unsigned int)contentSize));
           contentSize = 0;
       }
   
     /* Allocate zero-terminated buffer */     /* Allocate zero-terminated buffer */
     handler->recvPage = (Page*)malloc(sizeof(Page) + (size_t)handler->contentLength + 1);      handler->recvPage = (Page*)PAL_Malloc(sizeof (Page) + (size_t)contentSize + 1);
  
     if (!handler->recvPage)      if (handler->recvPage == NULL)
       {
           LOGD2((ZT("_ReadHeader - Cannot allocate memory for received page")));
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
       }
       ((char*)(handler->recvPage + 1))[contentSize] = '\0';
  
     ((char*)(handler->recvPage + 1))[handler->contentLength] = 0;      handler->recvPage->u.s.size = (unsigned int)contentSize;
   
     handler->recvPage->u.s.size = (unsigned int)handler->contentLength;  
     handler->recvPage->u.s.next = 0;     handler->recvPage->u.s.next = 0;
       handler->receivedSize -= index + 1;
     handler->recvievedSize -= index + 1;  
  
     /* Verify that we have not more than 'content-length' bytes in buffer left     /* Verify that we have not more than 'content-length' bytes in buffer left
         If we have more, assuming http client is invalid and drop connection */         If we have more, assuming http client is invalid and drop connection */
     if (handler->recvievedSize > (size_t)handler->contentLength)      if (handler->receivedSize > contentSize)
     {     {
         LOGW((T("http payload is bigger than content-length\n")));          trace_HttpPayloadIsBiggerThanContentLength();
           LOGE2((ZT("_ReadHeader - HTTP payload is bigger than content-length (%u > %u bytes)"), (unsigned int)handler->receivedSize, (unsigned int)contentSize));
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
     }     }
  
     memcpy( handler->recvPage + 1, data, handler->recvievedSize );      if (handler->receivedSize != 0)
           memcpy(handler->recvPage + 1, data, handler->receivedSize);
     handler->recvingState = RECV_STATE_CONTENT;     handler->recvingState = RECV_STATE_CONTENT;
  
     PRINTF_2(("full header read; page size %d, position %d\n", handler->recvPage->u.s.size, handler->recvievedSize));  
   
     /* Invoke user's callback with header information */     /* Invoke user's callback with header information */
     {     {
         HttpClient* self = (HttpClient*)handler->base.data;         HttpClient* self = (HttpClient*)handler->base.data;
  
         if (!(*self->callbackOnResponse)( self, self->callbackData, &handler->recvHeaders,         if (!(*self->callbackOnResponse)( self, self->callbackData, &handler->recvHeaders,
             handler->contentLength, handler->contentLength == 0, 0))             handler->contentLength, handler->contentLength == 0, 0))
           {
               LOGE2((ZT("_ReadHeader - On response callback for header failed")));
             return PRT_RETURN_FALSE;             return PRT_RETURN_FALSE;
     }     }
       }
  
       LOGD2((ZT("_ReadHeader - OK exit")));
     return PRT_CONTINUE;     return PRT_CONTINUE;
 } }
  
 static Http_CallbackResult _ReadData( static Http_CallbackResult _ReadData(
     Http_SR_SocketData* handler)      HttpClient_SR_SocketData* handler)
 { {
     //HttpClient* self = (HttpClient*)handler->base.data;      /* HttpClient* self = (HttpClient*)handler->base.data; */
     char* buf;     char* buf;
     size_t buf_size, received;     size_t buf_size, received;
     MI_Result r;     MI_Result r;
Line 650 
Line 755 
     if (handler->recvingState != RECV_STATE_CONTENT)     if (handler->recvingState != RECV_STATE_CONTENT)
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
  
     buf = ((char*)(handler->recvPage + 1)) + handler->recvievedSize;      LOGD2((ZT("_ReadData - Begin. Head? %d"), handler->headVerb));
     buf_size = (size_t)(handler->contentLength - handler->recvievedSize);      if (!handler->headVerb)
       {
           buf = (char*)(handler->recvPage + 1) + handler->receivedSize;
           buf_size = (size_t)(handler->contentLength - handler->receivedSize);
     received = 0;     received = 0;
  
     if (buf_size)          if (buf_size != 0)
     {     {
         r = _Sock_Read(handler, buf, buf_size, &received);         r = _Sock_Read(handler, buf, buf_size, &received);
               LOGD2((ZT("_ReadData - _Sock_Read result: %d (%s), socket: %d, recv: %u"), (int)r, mistrerror(r), (int)handler->base.sock, (unsigned int)received));
         PRINTF(("%d: read r = %d, recv = %d\n", (int)handler->base.sock, (int)r, (int)received ));  
  
         if ( r == MI_RESULT_OK && 0 == received )         if ( r == MI_RESULT_OK && 0 == received )
             return PRT_RETURN_FALSE; /* conection closed */                  return PRT_RETURN_FALSE; /* connection closed */
  
         if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )         if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
             return PRT_RETURN_FALSE;             return PRT_RETURN_FALSE;
  
         handler->recvievedSize += received;              handler->receivedSize += received;
   
               LOGD2((ZT("_RequestCallback - Called _ReadData. %d / %d bytes read"), (int)handler->receivedSize, (int)handler->contentLength));
   
               if (handler->contentLength > 0 && handler->receivedSize < (size_t)handler->contentLength)
               {                           /* assume 500 bytes per millisecond transmission */
                                           /* wait to avoid spinning on _Sock_Read */
                   unsigned int bytesLeft = (unsigned int)handler->contentLength - (unsigned int)handler->receivedSize;
                   unsigned long msec = (unsigned long)(bytesLeft / 500 + 1);
   
                   Sleep_Milliseconds(msec);
               }
     }     }
  
     /* did we get all data? */     /* did we get all data? */
     PRINTF_2(("dt status - %d / %d\n", (int)handler->recvievedSize, (int)handler->contentLength));          LOGD2((ZT("_ReadData - Received size: %d / %d"), (int)handler->receivedSize, (int)handler->contentLength));
           if (handler->receivedSize != (size_t)handler->contentLength)
     if ( handler->recvievedSize != (size_t)handler->contentLength )  
         return PRT_RETURN_TRUE;         return PRT_RETURN_TRUE;
       }
  
     /* Invoke user's callback with header information */     /* Invoke user's callback with header information */
     {     {
         HttpClient* self = (HttpClient*)handler->base.data;         HttpClient* self = (HttpClient*)handler->base.data;
           MI_Boolean lastChunk = MI_TRUE;
   
           if (handler->contentEnd >= 0 &&
               handler->contentEnd + 1 < handler->contentTotalLength)
           {
               lastChunk = MI_FALSE;
           }
  
         if (!(*self->callbackOnResponse)( self, self->callbackData, 0,         if (!(*self->callbackOnResponse)( self, self->callbackData, 0,
             handler->contentLength, MI_TRUE, &handler->recvPage))              handler->contentLength, lastChunk, &handler->recvPage))
             return PRT_RETURN_FALSE;             return PRT_RETURN_FALSE;
  
         /* status callback */         /* status callback */
Line 691 
Line 816 
             MI_RESULT_OK );             MI_RESULT_OK );
     }     }
  
       if (handler->recvPage != NULL)
       {
           LOGD2((ZT("_ReadData - Freeing recvPage. socket: %d"), (int)handler->base.sock));
           PAL_Free(handler->recvPage);
       }
  
     if (handler->recvPage)      handler->recvPage = NULL;
         free(handler->recvPage);      handler->receivedSize = 0;
   
     handler->recvPage = 0;  
     handler->recvievedSize = 0;  
     memset(&handler->recvHeaders, 0, sizeof(handler->recvHeaders));     memset(&handler->recvHeaders, 0, sizeof(handler->recvHeaders));
     handler->recvingState = RECV_STATE_HEADER;     handler->recvingState = RECV_STATE_HEADER;
       LOGD2((ZT("_ReadData - OK exit")));
     return PRT_CONTINUE;     return PRT_CONTINUE;
 } }
  
   
 static Http_CallbackResult _ReadChunkHeader( static Http_CallbackResult _ReadChunkHeader(
     Http_SR_SocketData* handler)      HttpClient_SR_SocketData* handler)
 { {
     char* buf;     char* buf;
     char* currentLine;     char* currentLine;
Line 719 
Line 846 
     if (handler->recvingState != RECV_STATE_CHUNKHEADER)     if (handler->recvingState != RECV_STATE_CHUNKHEADER)
         return PRT_CONTINUE;         return PRT_CONTINUE;
  
     buf = handler->recvBuffer + handler->recvievedSize;      buf = handler->recvBuffer + handler->receivedSize;
     buf_size = handler->recvBufferSize - handler->recvievedSize;      buf_size = handler->recvBufferSize - handler->receivedSize;
     received = 0;     received = 0;
  
     r = _Sock_Read(handler, buf, buf_size, &received);     r = _Sock_Read(handler, buf, buf_size, &received);
     PRINTF(("%d: read r = %d, recv = %d; reverse %d\n", (int)handler->base.sock, (int)r, (int)received, (int)handler->reverseOperations ));  
  
     if ( r == MI_RESULT_OK && 0 == received )     if ( r == MI_RESULT_OK && 0 == received )
     {     {
         if (!handler->recvBufferSize)         if (!handler->recvBufferSize)
             return PRT_RETURN_FALSE; /* conection closed */              return PRT_RETURN_FALSE; /* connection closed */
  
         connectionClosed = MI_TRUE;         connectionClosed = MI_TRUE;
     }     }
Line 740 
Line 866 
     if (!received && !handler->recvBufferSize)     if (!received && !handler->recvBufferSize)
         return PRT_RETURN_TRUE;         return PRT_RETURN_TRUE;
  
     handler->recvievedSize += received;      handler->receivedSize += received;
   
     /* check header */  
     PRINTF_2(("%s\n",buf));  
  
     /* did we get full header? */     /* did we get full header? */
     buf = handler->recvBuffer;     buf = handler->recvBuffer;
     for ( index = 1; index < handler->recvievedSize; index++ )  
       _Analysis_assume_(handler->recvBufferSize > 2);
       for (index = 1; index < handler->receivedSize && buf[index]; index++)
     {     {
         if (buf[index-1] == '\r' && buf[index] == '\n' )         if (buf[index-1] == '\r' && buf[index] == '\n' )
         {         {
Line 759 
Line 884 
     if (!fullHeaderReceived )     if (!fullHeaderReceived )
     {     {
         if (connectionClosed)         if (connectionClosed)
             return PRT_RETURN_FALSE; /* conection closed */              return PRT_RETURN_FALSE; /* connection closed */
  
         if ( handler->recvievedSize <  handler->recvBufferSize )          if (handler->receivedSize <  handler->recvBufferSize)
             return PRT_RETURN_TRUE; /* continue reading */             return PRT_RETURN_TRUE; /* continue reading */
  
         if ( handler->recvBufferSize < MAX_HEADER_SIZE )         if ( handler->recvBufferSize < MAX_HEADER_SIZE )
         {         {
             buf = realloc(handler->recvBuffer, handler->recvBufferSize * 2);              buf = PAL_Realloc(handler->recvBuffer, handler->recvBufferSize * 2);
  
             if (!buf)             if (!buf)
                 return PRT_RETURN_FALSE;                 return PRT_RETURN_FALSE;
Line 778 
Line 903 
         else         else
         {         {
             /* http chunk header is too big - drop connection */             /* http chunk header is too big - drop connection */
             LOGW((T("http chunk header is too big; dropping connection\n")));              trace_HttpChunkHeaderIsTooBig();
             return PRT_RETURN_FALSE;             return PRT_RETURN_FALSE;
         }         }
     }     }
Line 812 
Line 937 
  
         /* clean up state */         /* clean up state */
         handler->recvPage = 0;         handler->recvPage = 0;
         handler->recvievedSize = 0;          handler->receivedSize = 0;
         memset(&handler->recvHeaders, 0, sizeof(handler->recvHeaders));         memset(&handler->recvHeaders, 0, sizeof(handler->recvHeaders));
         handler->recvingState = RECV_STATE_HEADER;         handler->recvingState = RECV_STATE_HEADER;
  
         if (connectionClosed)         if (connectionClosed)
             return PRT_RETURN_FALSE; /* conection closed */              return PRT_RETURN_FALSE; /* connection closed */
  
         return PRT_CONTINUE;         return PRT_CONTINUE;
     }     }
  
     /* Allocate zero-terminated buffer */     /* Allocate zero-terminated buffer */
     handler->recvPage = (Page*)malloc(sizeof(Page) + (size_t)chunkSize + 2 /*CR-LF*/ + 1 /* \0 */);      handler->recvPage = (Page*)PAL_Malloc(sizeof(Page) + (size_t)chunkSize + 2 /*CR-LF*/ + 1 /* \0 */);
  
     if (!handler->recvPage)     if (!handler->recvPage)
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
Line 834 
Line 959 
     handler->recvPage->u.s.next = 0;     handler->recvPage->u.s.next = 0;
  
     /* subtract header size */     /* subtract header size */
     handler->recvievedSize -= index + 1;      handler->receivedSize -= index + 1;
  
     /* in case of small chunks we may receive more than one chunk already */     /* in case of small chunks we may receive more than one chunk already */
     if (handler->recvievedSize > (size_t)(chunkSize+2))      if (handler->receivedSize > (size_t)(chunkSize+2))
     {     {
         /* copy page size to page */         /* copy page size to page */
         memcpy( handler->recvPage + 1, data, chunkSize+2 );         memcpy( handler->recvPage + 1, data, chunkSize+2 );
Line 851 
Line 976 
                 return PRT_RETURN_FALSE;                 return PRT_RETURN_FALSE;
  
             if (handler->recvPage)             if (handler->recvPage)
                 free(handler->recvPage);                  PAL_Free(handler->recvPage);
  
             handler->recvPage = 0;             handler->recvPage = 0;
         }         }
  
         /* remove consumed part */         /* remove consumed part */
         memmove(handler->recvBuffer, data + chunkSize+2, handler->recvievedSize - (chunkSize+2));          memmove(handler->recvBuffer, data + chunkSize+2, handler->receivedSize - (chunkSize+2));
         handler->recvievedSize -= (chunkSize+2);          handler->receivedSize -= (chunkSize+2);
  
         /* consume next chunk */         /* consume next chunk */
         return _ReadChunkHeader(handler);         return _ReadChunkHeader(handler);
     }     }
  
     memcpy( handler->recvPage + 1, data, handler->recvievedSize );      memcpy(handler->recvPage + 1, data, handler->receivedSize);
     handler->recvingState = RECV_STATE_CHUNKDATA;     handler->recvingState = RECV_STATE_CHUNKDATA;
  
     if (connectionClosed)     if (connectionClosed)
         return PRT_RETURN_FALSE; /* conection closed */          return PRT_RETURN_FALSE; /* connection closed */
  
     return PRT_CONTINUE;     return PRT_CONTINUE;
 } }
 static Http_CallbackResult _ReadChunkData( static Http_CallbackResult _ReadChunkData(
     Http_SR_SocketData* handler)      HttpClient_SR_SocketData* handler)
 { {
     //HttpClient* self = (HttpClient*)handler->base.data;     //HttpClient* self = (HttpClient*)handler->base.data;
     char* buf;     char* buf;
Line 884 
Line 1009 
     if (handler->recvingState != RECV_STATE_CHUNKDATA)     if (handler->recvingState != RECV_STATE_CHUNKDATA)
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
  
     buf = ((char*)(handler->recvPage + 1)) + handler->recvievedSize;      buf = ((char*)(handler->recvPage + 1)) + handler->receivedSize;
     buf_size = (size_t)(handler->recvPage->u.s.size + 2 /* CR-LF */ - handler->recvievedSize);      buf_size = (size_t)(handler->recvPage->u.s.size + 2 /* CR-LF */ - handler->receivedSize);
     received = 0;     received = 0;
  
     if (buf_size)     if (buf_size)
     {     {
         r = _Sock_Read(handler, buf, buf_size, &received);         r = _Sock_Read(handler, buf, buf_size, &received);
  
         PRINTF(("%d: read r = %d, recv = %d\n", (int)handler->base.sock, (int)r, (int)received ));  
   
         if ( r == MI_RESULT_OK && 0 == received )         if ( r == MI_RESULT_OK && 0 == received )
             return PRT_RETURN_FALSE; /* conection closed */              return PRT_RETURN_FALSE; /* connection closed */
  
         if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )         if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
             return PRT_RETURN_FALSE;             return PRT_RETURN_FALSE;
  
         handler->recvievedSize += received;          handler->receivedSize += received;
     }     }
  
     /* did we get all data? */      if (handler->receivedSize != (size_t)(handler->recvPage->u.s.size + 2 /* CR-LF */))
     PRINTF_2(("dt status - %d / %d\n", (int)handler->recvievedSize, (int)handler->contentLength));  
   
     if ( handler->recvievedSize != (size_t)(handler->recvPage->u.s.size + 2 /* CR-LF */) )  
         return PRT_RETURN_TRUE;         return PRT_RETURN_TRUE;
  
     /* Invoke user's callback with header information */     /* Invoke user's callback with header information */
Line 919 
Line 1039 
  
     }     }
  
   
     if (handler->recvPage)     if (handler->recvPage)
         free(handler->recvPage);          PAL_Free(handler->recvPage);
  
     handler->recvPage = 0;     handler->recvPage = 0;
     handler->recvievedSize = 0;      handler->receivedSize = 0;
     memset(&handler->recvHeaders, 0, sizeof(handler->recvHeaders));     memset(&handler->recvHeaders, 0, sizeof(handler->recvHeaders));
     handler->recvingState = RECV_STATE_CHUNKHEADER;     handler->recvingState = RECV_STATE_CHUNKHEADER;
     return PRT_CONTINUE;     return PRT_CONTINUE;
 } }
  
   
 static Http_CallbackResult _WriteHeader( static Http_CallbackResult _WriteHeader(
     Http_SR_SocketData* handler)      HttpClient_SR_SocketData* handler)
 { {
     char* buf;     char* buf;
     size_t buf_size, sent;     size_t buf_size, sent;
Line 946 
Line 1064 
     if (handler->sendingState == RECV_STATE_CONTENT)     if (handler->sendingState == RECV_STATE_CONTENT)
         return PRT_CONTINUE;         return PRT_CONTINUE;
  
       LOGD2((ZT("_WriteHeader - Begin")));
   
     buf = ((char*)(handler->sendHeader + 1)) + handler->sentSize;     buf = ((char*)(handler->sendHeader + 1)) + handler->sentSize;
     buf_size = handler->sendHeader->u.s.size - handler->sentSize;     buf_size = handler->sendHeader->u.s.size - handler->sentSize;
     sent = 0;     sent = 0;
  
     r = _Sock_Write(handler, buf, buf_size, &sent);     r = _Sock_Write(handler, buf, buf_size, &sent);
       LOGD2((ZT("_WriteHeader - _Sock_Write result: %d (%s), socket: %d, sent: %d"), (int)r, mistrerror(r), (int)handler->base.sock, (int)sent));
     PRINTF(("%d: write r = %d, sent = %d\n", (int)handler->base.sock, (int)r, (int)sent ));  
  
     if ( r == MI_RESULT_OK && 0 == sent )     if ( r == MI_RESULT_OK && 0 == sent )
         return PRT_RETURN_FALSE; /* conection closed */      {
           LOGE2((ZT("_WriteHeader - Connection closed")));
           return PRT_RETURN_FALSE; /* connection closed */
       }
  
     if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )     if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
       {
           LOGE2((ZT("_WriteHeader - _Sock_Write returned error: %d (%s)"), (int)r, mistrerror(r)));
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
       }
  
     handler->sentSize += sent;     handler->sentSize += sent;
       handler->headVerb = buf_size > 4 && Strncasecmp(buf, "HEAD", 4) == 0;
  
     /* did we get all data? */      /* did we send all data? */
   
     if ( handler->sentSize != handler->sendHeader->u.s.size )     if ( handler->sentSize != handler->sendHeader->u.s.size )
       {
           LOGD2((ZT("_WriteHeader - Partial write. %u sent this time, %u / %d written, result: %d (%s)"), (unsigned int)sent, (unsigned int)handler->sentSize, (unsigned int)handler->sendHeader->u.s.size, r, mistrerror(r)));
         return PRT_RETURN_TRUE;         return PRT_RETURN_TRUE;
       }
  
     free(handler->sendHeader);      PAL_Free(handler->sendHeader);
     handler->sendHeader = 0;     handler->sendHeader = 0;
     handler->sentSize = 0;     handler->sentSize = 0;
     handler->sendingState = RECV_STATE_CONTENT;     handler->sendingState = RECV_STATE_CONTENT;
  
       LOGD2((ZT("_WriteHeader - OK exit")));
     return PRT_CONTINUE;     return PRT_CONTINUE;
 } }
  
 static Http_CallbackResult _WriteData( static Http_CallbackResult _WriteData(
     Http_SR_SocketData* handler)      HttpClient_SR_SocketData* handler)
 { {
     char* buf;     char* buf;
     size_t buf_size, sent;     size_t buf_size, sent;
     MI_Result r;     MI_Result r;
  
       LOGD2((ZT("_WriteData - Begin")));
     /* are we in the right state? */     /* are we in the right state? */
     if (handler->sendingState != RECV_STATE_CONTENT)     if (handler->sendingState != RECV_STATE_CONTENT)
       {
           LOGE2((ZT("_WriteData - Wrong state. state: %d"), handler->sendingState));
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
       }
  
     if (!handler->sendPage)     if (!handler->sendPage)
     {   /* no content*/     {   /* no content*/
Line 993 
Line 1126 
         handler->base.mask &= ~SELECTOR_WRITE;         handler->base.mask &= ~SELECTOR_WRITE;
         handler->base.mask |= SELECTOR_READ;         handler->base.mask |= SELECTOR_READ;
  
           LOGW2((ZT("_WriteData - Content is empty. Continuing")));
         return PRT_CONTINUE;         return PRT_CONTINUE;
     }     }
  
Line 1001 
Line 1135 
     sent = 0;     sent = 0;
  
     r = _Sock_Write(handler, buf, buf_size, &sent);     r = _Sock_Write(handler, buf, buf_size, &sent);
       LOGD2((ZT("_WriteData - HTTPClient sent %u / %u bytes with result %d (%s)"), (unsigned int)sent, (unsigned int)buf_size, (int)r, mistrerror(r)));
     PRINTF(("%d: write r = %d, sent = %d\n", (int)handler->base.sock, (int)r, (int)sent ));  
  
     if ( r == MI_RESULT_OK && 0 == sent )     if ( r == MI_RESULT_OK && 0 == sent )
         return PRT_RETURN_FALSE; /* conection closed */      {
           LOGE2((ZT("_WriteData exit. Connection closed")));
           return PRT_RETURN_FALSE; /* connection closed */
       }
  
     if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )     if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
       {
           LOGE2((ZT("_WriteData exit - Error: %d (%s)"), r, mistrerror(r)));
         return PRT_RETURN_FALSE;         return PRT_RETURN_FALSE;
       }
  
     handler->sentSize += sent;     handler->sentSize += sent;
  
     /* did we get all data? */      /* did we send all data? */
  
     if ( handler->sentSize != handler->sendPage->u.s.size )     if ( handler->sentSize != handler->sendPage->u.s.size )
       {
           LOGD2((ZT("_WriteData - Exit. Partial write. %u / %u bytes written"), (unsigned int)handler->sentSize, (unsigned int)handler->sendPage->u.s.size));
         return PRT_RETURN_TRUE;         return PRT_RETURN_TRUE;
       }
  
     free(handler->sendPage);      LOGD2((ZT("_WriteData - %u / %u bytes sent"), (unsigned int)handler->sentSize, (unsigned int)handler->sendPage->u.s.size));
     handler->sendPage = 0;      PAL_Free(handler->sendPage);
       handler->sendPage = NULL;
     handler->sentSize = 0;     handler->sentSize = 0;
     handler->sendingState = RECV_STATE_HEADER;     handler->sendingState = RECV_STATE_HEADER;
     handler->base.mask &= ~SELECTOR_WRITE;     handler->base.mask &= ~SELECTOR_WRITE;
     handler->base.mask |= SELECTOR_READ;     handler->base.mask |= SELECTOR_READ;
  
       LOGD2((ZT("_WriteData - OK exit. returning: %d"), PRT_CONTINUE));
   
     return PRT_CONTINUE;     return PRT_CONTINUE;
 } }
  
   
 static MI_Boolean _RequestCallbackRead( static MI_Boolean _RequestCallbackRead(
     Http_SR_SocketData* handler)      HttpClient_SR_SocketData* handler)
 { {
     switch (_ReadHeader(handler))     switch (_ReadHeader(handler))
     {     {
Line 1071 
Line 1215 
 } }
  
 static MI_Boolean _RequestCallbackWrite( static MI_Boolean _RequestCallbackWrite(
     Http_SR_SocketData* handler)      HttpClient_SR_SocketData* handler)
 { {
     switch (_WriteHeader(handler))     switch (_WriteHeader(handler))
     {     {
Line 1096 
Line 1240 
     MI_Uint32 mask,     MI_Uint32 mask,
     MI_Uint64 currentTimeUsec)     MI_Uint64 currentTimeUsec)
 { {
     Http_SR_SocketData* handler = (Http_SR_SocketData*)handlerIn;      HttpClient_SR_SocketData* handler = (HttpClient_SR_SocketData*)handlerIn;
     sel=sel;      MI_UNUSED(sel);
  
     if ( ((mask & SELECTOR_READ) != 0 && !handler->reverseOperations) ||     if ( ((mask & SELECTOR_READ) != 0 && !handler->reverseOperations) ||
         ((mask & SELECTOR_WRITE) != 0 && handler->reverseOperations) )         ((mask & SELECTOR_WRITE) != 0 && handler->reverseOperations) )
     {     {
         if (!_RequestCallbackRead(handler))         if (!_RequestCallbackRead(handler))
           {
               LOGE2((ZT("_RequestCallback - RequestCallbackRead failed")));
             return MI_FALSE;             return MI_FALSE;
     }     }
           LOGD2((ZT("_RequestCallback - Called _RequestCallbackRead. %u / %u bytes read"), (unsigned int)handler->receivedSize, handler->recvPage == NULL ? 0 : (unsigned int)handler->recvPage->u.s.size));
       }
  
     if ( ((mask & SELECTOR_WRITE) != 0 && !handler->reverseOperations) ||     if ( ((mask & SELECTOR_WRITE) != 0 && !handler->reverseOperations) ||
         ((mask & SELECTOR_READ) != 0 && handler->reverseOperations) )         ((mask & SELECTOR_READ) != 0 && handler->reverseOperations) )
     {     {
         if (!_RequestCallbackWrite(handler))         if (!_RequestCallbackWrite(handler))
           {
               LOGE2((ZT("_RequestCallback - _RequestCallbackWrite failed")));
               return MI_FALSE;
           }
           LOGD2((ZT("_RequestCallback - Called _RequestCallbackWrite. %u / %u bytes sent"), (unsigned int)handler->sentSize, handler->sendPage == NULL ? 0 : (unsigned int)handler->sendPage->u.s.size));
           while (handler->sendPage != NULL && handler->sentSize < handler->sendPage->u.s.size)
           {                               /* assume 500 bytes per millisecond transmission */
                                           /* wait after to avoid spinning too much on _WriteData */
               unsigned int bytesLeft = (unsigned int)handler->sendPage->u.s.size - (unsigned int)handler->sentSize;
               unsigned long msec = (unsigned long)(bytesLeft / 500 + 1);
   
               LOGD2((ZT("_RequestCallback - Called _WriteData. %u / %u bytes sent"), (unsigned int)handler->sentSize, handler->sendPage == NULL ? 0 : (unsigned int)handler->sendPage->u.s.size));
               if (_WriteData(handler) == MI_FALSE)
               {
                   LOGE2((ZT("_RequestCallback - _WriteData failed")));
             return MI_FALSE;             return MI_FALSE;
     }     }
               LOGD2((ZT("_RequestCallback - Called _WriteData. %u bytes written, %u bytes left"), (unsigned int)handler->sentSize, handler->sendPage == NULL ? 0 : (unsigned int)handler->sendPage->u.s.size));
               Sleep_Milliseconds(msec);
           }
           LOGD2((ZT("_RequestCallback - Called _RequestCallbackWrite. %u / %u bytes sent"), (unsigned int)handler->sentSize, handler->sendPage == NULL ? 0 : (unsigned int)handler->sendPage->u.s.size));
       }
  
     /* re-set timeout - if we performed R/W operation, set timeout depending where we are in communication */     /* re-set timeout - if we performed R/W operation, set timeout depending where we are in communication */
     if (mask & (SELECTOR_READ | SELECTOR_WRITE))     if (mask & (SELECTOR_READ | SELECTOR_WRITE))
Line 1119 
Line 1287 
         handler->base.fireTimeoutAt = currentTimeUsec + handler->timeoutUsec;         handler->base.fireTimeoutAt = currentTimeUsec + handler->timeoutUsec;
     }     }
  
     /* Close conenction by timeout */      /* Close connection by timeout */
     if (mask & SELECTOR_TIMEOUT)      if ((mask & SELECTOR_TIMEOUT) != 0)
       {
           if (handler->status != MI_RESULT_OK)
     {     {
         if (MI_RESULT_OK != handler->status)              handler->recvHeaders.httpError = 408;
             handler->status = MI_RESULT_TIME_OUT;             handler->status = MI_RESULT_TIME_OUT;
           }
           LOGE2((ZT("_RequestCallback - Timed out. socket: %d, result: %d (%s)"), handler->base.sock, handler->status, mistrerror(handler->status)));
         return MI_FALSE;         return MI_FALSE;
     }     }
  
     if ((mask & SELECTOR_REMOVE) != 0 ||      if ((mask & SELECTOR_REMOVE) != 0 || (mask & SELECTOR_DESTROY) != 0)
         (mask & SELECTOR_DESTROY) != 0)  
     {     {
         HttpClient* self = (HttpClient*)handler->base.data;         HttpClient* self = (HttpClient*)handler->base.data;
  
         /* notify next stack layer */         /* notify next stack layer */
         if (MI_RESULT_OK != handler->status)          if (handler->status != MI_RESULT_OK)
             (*self->callbackOnStatus)(              (*self->callbackOnStatus)(self, self->callbackData, handler->status);
                 self,  
                 self->callbackData,          /* Yeah, this is hokey, but we need to sleep here to let the */
                 handler->status);                  /* subsystems have the opportunity to send the data before we close */
                   /* the socket, or we'll get a broken pipe/connection reset */
   #if defined(CONFIG_OS_WINDOWS)
           Sleep_Milliseconds(1);
   #else
           usleep(50);
   #endif
   
           if (handler == NULL)
           {
               LOGE2((ZT("_RequestCallback - The handler object was free'd under us!")));
               return MI_TRUE;
           }
  
         self->connector = 0;          self->connector = NULL;
  
         if (handler->ssl)         if (handler->ssl)
             SSL_free(handler->ssl);             SSL_free(handler->ssl);
  
         PRINTF(("%d: close\n", (int)handler->base.sock));  
   
         Sock_Close(handler->base.sock);         Sock_Close(handler->base.sock);
  
         if (handler->recvPage)         if (handler->recvPage)
             free(handler->recvPage);              PAL_Free(handler->recvPage);
  
         if (handler->sendPage)         if (handler->sendPage)
             free(handler->sendPage);              PAL_Free(handler->sendPage);
  
         if (handler->sendHeader)         if (handler->sendHeader)
             free(handler->sendHeader);              PAL_Free(handler->sendHeader);
  
         free(handler->recvBuffer);          PAL_Free(handler->recvBuffer);
         free(handler);          PAL_Free(handler);
     }     }
  
     return MI_TRUE;     return MI_TRUE;
 } }
  
 #ifdef CONFIG_POSIX #ifdef CONFIG_POSIX
 static MI_Result _CreateSSLContext(HttpClient* self)  
   /*
    Verify callback when the server authentication certificate's chain of trust is checked. This
    is the same as the Open SSL verify callback function (return preverify_ok), except that it
    logs a diagnostic message when preverify_ok has a failed status.
   */
   static int _ctxVerify(
       int preverify_ok,
       X509_STORE_CTX* ctx)
   {
       if (preverify_ok <= 0)
 { {
     SSL_CTX * sslContext = 0;          X509* certWithError = X509_STORE_CTX_get_current_cert(ctx);
           int error = X509_STORE_CTX_get_error(ctx);
           char nameBuf[256];
  
     sslContext = SSL_CTX_new(SSLv23_method());          X509_NAME_oneline(X509_get_subject_name(certWithError), nameBuf, 256);
           trace_SSL_VerifyFailed(error, nameBuf);
       }
       return preverify_ok;
   }
  
     if (!sslContext)  /*
    Create an Open SSL context that will be used for secure communication. Set up server and client
    certificate authentication if specified.
   */
   static MI_Result _CreateSSLContext(
       HttpClient* self,
       const char* trustedCertsDir,
       const char* certFile,
       const char* privateKeyFile)
   {
       SSL_CTX* sslContext = SSL_CTX_new(SSLv23_method());
       if (sslContext == NULL)
     {     {
         LOGE_CHAR((          LOGE2((ZT("_CreateSSLContext - Cannot create SSL context")));
             "---> SSL: cannot create ssl context"));          trace_SSL_CannotCreateContext();
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
     SSL_CTX_set_quiet_shutdown(sslContext, 1);     SSL_CTX_set_quiet_shutdown(sslContext, 1);
     SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY);      (void)SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY | SSL_MODE_ENABLE_PARTIAL_WRITE);
     SSL_CTX_set_mode(sslContext, SSL_MODE_ENABLE_PARTIAL_WRITE);  
     SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);     SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
 #if 0      SSL_CTX_sess_set_remove_cb(sslContext, NULL);
     /* Check if there is a certificate file (file containing server  
     ** certificate) specified. If specified, validate and load the      if (trustedCertsDir != NULL)
     ** certificate.      {
           /* Cause Open SSL to check the server certificate Subject against its FQDN and
           ** to check the server certificate chain against the contents of *trustedCertsDir.
           */
           if (SSL_CTX_load_verify_locations(sslContext, NULL, trustedCertsDir) < 0)
           {
               LOGE2((ZT("_CreateSSLContext - Cannot set directory containing trusted certificate(s) to %s"), trustedCertsDir));
               trace_SSL_BadTrustDir(trustedCertsDir);
           }
           SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER, _ctxVerify);
       }
   
       /* Check if there is a client certificate file (file containing client authentication
       ** certificate) specified. If specified, validate and load the certificate.
     */     */
       if (certFile != NULL && *certFile != '\0')
     {     {
         /* load the specified server certificates */          int err;
         LOGI_CHAR(("---> SSL: Loading server certificate from: %s",  
             GetPath(ID_PEMFILE)));  
  
         if (SSL_CTX_use_certificate_file(sslContext,          /* load the specified client certificates */
             GetPath(ID_PEMFILE), SSL_FILETYPE_PEM) <=0)          LOGD2((ZT("_CreateSSLContext - Loading server certificate from: %s"), certFile));
   
           err = SSL_CTX_use_certificate_file(sslContext,
                                              certFile,
                                              strcmp(certFile + strlen(certFile) - 4, ".pem") == 0 ? SSL_FILETYPE_PEM :  SSL_FILETYPE_ASN1);
           if (err <= 0)
         {         {
             LOGE_CHAR(("---> SSL: No server certificate found in %s",  #if defined(ENABLE_TRACING)
                 GetPath(ID_PEMFILE)));              unsigned long error = ERR_peek_last_error();
   #endif
   
               LOGE2((ZT("_CreateSSLContext - No client certificate found in %s"), certFile));
               LOGE2((ZT("_CreateSSLContext - OpenSSL Error 0x%lX (%s) in SSL_CTX_use_certificate_file"), error, sslstrerror(error)));
             SSL_CTX_free(sslContext);             SSL_CTX_free(sslContext);
               sslContext = NULL;
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
         }         }
     }  
  
     /*          if (privateKeyFile != NULL && *privateKeyFile != '\0')
     ** Check if there is a key file (file containing server          {
     ** private key) specified and the key was not already loaded.              /* load the specified private key */
     ** If specified, validate and load the key.              LOGD2((ZT("_CreateSSLContext - SSL Loading client private key from: %s"), privateKeyFile));
     */  
               err = SSL_CTX_use_RSAPrivateKey_file(sslContext,
                                                    privateKeyFile,
                                                    strcmp(privateKeyFile + strlen(privateKeyFile) - 4, ".pem") == 0 ? SSL_FILETYPE_PEM :  SSL_FILETYPE_ASN1);
               if (err <= 0)
     {     {
         /* load the specified server certificates */  #if defined(ENABLE_TRACING)
         LOGI_CHAR(("---> SSL: Loading certificate's private key from: %s",                  unsigned long error = ERR_peek_last_error();
             GetPath(ID_KEYFILE)));  #endif
                   LOGE2((ZT("_CreateSSLContext - Invalid private key found in %s"), privateKeyFile));
         //                  LOGE2((ZT("_CreateSSLContext - OpenSSL error 0x%lX (%s) in SSL_CTX_use_PrivateKey_file"), error, sslstrerror(error)));
         // load given private key and check for validity  
         //  
         if (!_verifyPrivateKey(sslContext, GetPath(ID_KEYFILE)))  
         {  
             LOGE_CHAR((  
                 "---> SSL: No server certificate found in %s",  
                 GetPath(ID_KEYFILE)));  
             SSL_CTX_free(sslContext);             SSL_CTX_free(sslContext);
                   sslContext = NULL;
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
         }         }
     }     }
 #endif      }
   
     self->sslContext = sslContext;     self->sslContext = sslContext;
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
   
 #endif #endif
  
   static MI_Result _CreateSocketAndConnect(
       Sock* s,
       Addr* addr)
   {
       MI_Result r;
   
       LOGD2((ZT("_CreateSocketAndConnect - Begin")));
   
       /* Create client socket. */
       r = Sock_Create(s, addr->is_ipv6);
       if (r != MI_RESULT_OK)
       {
           LOGE2((ZT("_CreateSocketAndConnect - Sock_Create failed. result: %d (%s)"), r, mistrerror(r)));
           return r;
       }
   
       /* set the socket to be non-blocking */
       r = Sock_SetBlocking(*s, MI_FALSE);
       if (r != MI_RESULT_OK)
       {
           LOGE2((ZT("_CreateSocketAndConnect - Sock_SetBlocking failed. result: %d (%s)"), r, mistrerror(r)));
           return r;
       }
   
       /* connect the socket to the IP address */
       r = Sock_Connect(*s, addr);
       if (r != MI_RESULT_OK)
       {
           LOGE2((ZT("_CreateSocketAndConnect - Sock_Connect failed. result: %d (%s)"), r, mistrerror(r)));
           return r;
       }
   
       LOGD2((ZT("_CreateSocketAndConnect - OK exit")));
   
       return MI_RESULT_WOULD_BLOCK;
   }
   
 static MI_Result _CreateConnectorSocket( static MI_Result _CreateConnectorSocket(
     HttpClient* self,     HttpClient* self,
     const char* host,     const char* host,
Line 1239 
Line 1503 
     Addr addr;     Addr addr;
     MI_Result r;     MI_Result r;
     Sock s;     Sock s;
     Http_SR_SocketData* h;      HttpClient_SR_SocketData* h;
     MI_Uint64 currentTimeUsec;     MI_Uint64 currentTimeUsec;
  
       LOGD2((ZT("_CreateConnectorSocket - Begin. host: %s, port: %d, secure? %d"), host, port, secure));
   
     /* timeout calculation */     /* timeout calculation */
     if (MI_RESULT_OK != Time_Now(&currentTimeUsec))      if (PAL_Time(&currentTimeUsec) != PAL_TRUE)
       {
           LOGE2((ZT("_CreateConnectorSocket - PAL_Time failed")));
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
       }
  
     // Initialize address.      /* This code tries to connect using the preferred addressing family (IPv4 */
     r = Addr_Init(&addr, host, port);          /* or IPv6). If that fails and Addr_Init has a secondary addressing */
     if (r != MI_RESULT_OK)          /* family, a connection with the secondary family, it tries using the */
         return MI_RESULT_FAILED;          /* secondary family next. */
  
     // Create client socket.      /* Initialize preferred address */
     r = Sock_Create(&s);      r = Addr_Init(&addr, host, port, MI_FALSE);
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
     {     {
         Sock_Close(s);          LOGE2((ZT("_CreateConnectorSocket - Addr_Init failed. result: %d (%s)"), r, mistrerror(r)));
         return MI_RESULT_FAILED;          return r;
     }     }
  
     r = Sock_SetBlocking(s, MI_FALSE);      /* Connect to the server */
     if (r != MI_RESULT_OK)      r = _CreateSocketAndConnect(&s, &addr);
       if (r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK)
     {     {
           MI_Result r2;
   
         Sock_Close(s);         Sock_Close(s);
         return MI_RESULT_FAILED;  
     }  
  
     // Connect to the server.          LOGW2((ZT("_CreateConnectorSocket - _CreateSocketAndConnect of primary address failed. result: %d (%s)"), r, mistrerror(r)));
     r = Sock_Connect(s, &addr);  
     if (r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK)          /* Initialize secondary address */
           r2 = Addr_Init(&addr, host, port, MI_TRUE);
           if (r2 != MI_RESULT_OK)
               return r;                   /* on error, return original failure */
           r2 = _CreateSocketAndConnect(&s, &addr);
           if (r2 != MI_RESULT_OK && r2 != MI_RESULT_WOULD_BLOCK)
     {     {
         Sock_Close(s);         Sock_Close(s);
         return MI_RESULT_FAILED;  
               LOGE2((ZT("_CreateConnectorSocket - Addr_Init failed. result: %d (%s)"), r, mistrerror(r)));
   
               return r;                   /* on error, return original failure */
           }
           r = r2;
     }     }
  
     /* Create handler */     /* Create handler */
     h = (Http_SR_SocketData*)calloc(1, sizeof(Http_SR_SocketData));      h = (HttpClient_SR_SocketData*)PAL_Calloc(1, sizeof(HttpClient_SR_SocketData));
  
     if (!h)      if (h == NULL)
     {     {
         Sock_Close(s);         Sock_Close(s);
           LOGE2((ZT("_CreateConnectorSocket - calloc failed")));
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
  
     h->recvBufferSize = INITIAL_BUFFER_SIZE;     h->recvBufferSize = INITIAL_BUFFER_SIZE;
     h->recvBuffer = (char*)calloc(1, h->recvBufferSize);      h->recvBuffer = (char*)PAL_Calloc(1, h->recvBufferSize);
     if (!h->recvBuffer)     if (!h->recvBuffer)
     {     {
         free(h);          PAL_Free(h);
         Sock_Close(s);         Sock_Close(s);
           LOGE2((ZT("_CreateConnectorSocket - calloc failed")));
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
  
Line 1299 
Line 1581 
     h->timeoutUsec = DEFAULT_HTTP_TIMEOUT_USEC;     h->timeoutUsec = DEFAULT_HTTP_TIMEOUT_USEC;
     h->base.fireTimeoutAt = currentTimeUsec + h->timeoutUsec;     h->base.fireTimeoutAt = currentTimeUsec + h->timeoutUsec;
  
     /* ssl support */      /* SSL support */
     if (secure)     if (secure)
     {     {
         h->ssl = SSL_new(self->sslContext);         h->ssl = SSL_new(self->sslContext);
  
         if (!h->ssl)         if (!h->ssl)
         {         {
             LOGW((T("ssl_new() failed\n")));              LOGW2((ZT("_CreateConnectorSocket - SSL_new failed")));
             free(h);              trace_SSLNew_Failed();
               PAL_Free(h);
             Sock_Close(s);             Sock_Close(s);
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
         }         }
  
           Sock_SetBlocking(s, MI_TRUE);
         if (!(SSL_set_fd(h->ssl, s) ))         if (!(SSL_set_fd(h->ssl, s) ))
         {         {
             LOGW((T("ssl_set_fd() failed\n")));              LOGW2((ZT("_CreateConnectorSocket - SSL_set_fd failed")));
               trace_SSL_setfd_Failed();
             SSL_free(h->ssl);             SSL_free(h->ssl);
             free(h);              PAL_Free(h);
             Sock_Close(s);             Sock_Close(s);
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
         }         }
Line 1329 
Line 1614 
  
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
     {     {
         LOGW((T("Selector_AddHandler() failed\n")));          LOGE2((ZT("_CreateConnectorSocket - Selector_AddHandler failed with error: %d (%s)"), (int)r, mistrerror(r)));
           trace_SelectorAddHandler_Failed();
         if (secure)         if (secure)
             SSL_free(h->ssl);             SSL_free(h->ssl);
         free(h);          PAL_Free(h);
         Sock_Close(s);         Sock_Close(s);
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
  
     self->connector = h;     self->connector = h;
  
       LOGD2((ZT("_CreateConnectorSocket - OK exit. socket: %d, secure: %d, timeout: %s"), h->base.sock, secure, FmtInterval(h->base.fireTimeoutAt - currentTimeUsec)));
   
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
   
 static MI_Result _New_Http( static MI_Result _New_Http(
     HttpClient** selfOut,     HttpClient** selfOut,
     Selector* selector, /*optional, maybe NULL*/     Selector* selector, /*optional, maybe NULL*/
Line 1361 
Line 1648 
  
     /* Allocate structure */     /* Allocate structure */
     {     {
         self = (HttpClient*)calloc(1, sizeof(HttpClient));          self = (HttpClient*)PAL_Calloc(1, sizeof(HttpClient));
  
         if (!self)         if (!self)
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
Line 1380 
Line 1667 
         /* Initialize the selector */         /* Initialize the selector */
         if (Selector_Init(&self->internalSelector) != MI_RESULT_OK)         if (Selector_Init(&self->internalSelector) != MI_RESULT_OK)
         {         {
             free(self);              PAL_Free(self);
               LOGE2((ZT("_NewHttp - Selector_Init failed")));
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
         }         }
         self->selector = &self->internalSelector;         self->selector = &self->internalSelector;
Line 1448 
Line 1736 
     if (headers)     if (headers)
         pageSize += _GetHeadersSize(headers);         pageSize += _GetHeadersSize(headers);
  
     page = (Page*)malloc(pageSize + sizeof(Page));      page = (Page*)PAL_Malloc(pageSize + sizeof(Page));
  
     if (!page)     if (!page)
         return 0;         return 0;
Line 1465 
Line 1753 
  
     if (r < 0)     if (r < 0)
     {     {
         free(page);          PAL_Free(page);
         return 0;         return 0;
     }     }
  
Line 1524 
Line 1812 
     MI_Boolean secure,     MI_Boolean secure,
     HttpClientCallbackOnStatus statusCallback,     HttpClientCallbackOnStatus statusCallback,
     HttpClientCallbackOnResponse  responseCallback,     HttpClientCallbackOnResponse  responseCallback,
     void* callbackData)      void* callbackData,
       const char* trustedCertsDir,
       const char* certFile,
       const char* privateKeyFile)
 { {
     HttpClient* self;     HttpClient* self;
     MI_Result r;     MI_Result r;
Line 1534 
Line 1825 
         responseCallback, callbackData);         responseCallback, callbackData);
  
     if (MI_RESULT_OK != r)     if (MI_RESULT_OK != r)
       {
           LOGE2((ZT("HttpClient_New_Connector - _New_Http failed. result: %d (%s)"), r, mistrerror(r)));
         return r;         return r;
       }
     self = *selfOut;     self = *selfOut;
  
 #ifdef CONFIG_POSIX #ifdef CONFIG_POSIX
     /* Allocate ssl context */      /* Allocate SSL context */
     if (secure)     if (secure)
     {     {
         /* init ssl */         /* init ssl */
         SSL_library_init();         SSL_library_init();
  
         /* create context */         /* create context */
         r = _CreateSSLContext(self);          r = _CreateSSLContext(self, trustedCertsDir, certFile, privateKeyFile);
  
         if (r != MI_RESULT_OK)         if (r != MI_RESULT_OK)
         {         {
             HttpClient_Delete(self);             HttpClient_Delete(self);
               *selfOut = NULL;
               LOGE2((ZT("HttpClient_New_Connector - _CreateSSLContext failed. result: %d (%s)"), r, mistrerror(r)));
             return r;             return r;
         }         }
     }     }
Line 1565 
Line 1860 
         if (r != MI_RESULT_OK)         if (r != MI_RESULT_OK)
         {         {
             HttpClient_Delete(self);             HttpClient_Delete(self);
               LOGE2((ZT("HttpClient_New_Connector - _CreateConnectorSocket failed failed. result: %d (%s)"), r, mistrerror(r)));
             return r;             return r;
         }         }
     }     }
  
   
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
Line 1592 
Line 1887 
  
     /* Check magic number */     /* Check magic number */
     if (self->magic != _MAGIC)     if (self->magic != _MAGIC)
       {
           LOGE2((ZT("HttpClient_Delete - Bad magic number")));
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
       }
  
     if (self->internalSelectorUsed)     if (self->internalSelectorUsed)
     {     {
         /* Release selector;         /* Release selector;
         Note: selector-destory closes all sockects in a list including connector and listener */          Note: Selector_Destroy closes all sockets in a list including connector and listener */
         Selector_Destroy(self->selector);         Selector_Destroy(self->selector);
  
         /* Shutdown the network */         /* Shutdown the network */
Line 1617 
Line 1915 
     self->magic = 0xDDDDDDDD;     self->magic = 0xDDDDDDDD;
  
     /* Free self pointer */     /* Free self pointer */
     free(self);      PAL_Free(self);
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
Line 1643 
Line 1941 
     const HttpClientRequestHeaders* headers,     const HttpClientRequestHeaders* headers,
     Page** data)     Page** data)
 { {
       LOGD2((ZT("HttpClient_StartRequest - Begin. verb: %s, URI: %s"), verb, uri));
  
     /* check params */     /* check params */
     if (!self || !uri)     if (!self || !uri)
Line 1650 
Line 1949 
  
     if (self->magic != _MAGIC)     if (self->magic != _MAGIC)
     {     {
         LOGW((T("start-request: invalid magic!") ));          LOGE2((ZT("HttpClient_Delete - Bad magic number")));
           trace_StartRequest_InvalidMagic();
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
     }     }
  
     if (!self->connector)      if (self->connector == NULL)
     {     {
         LOGW((T("start-request: connection was closed") ));          LOGE2((ZT("HttpClient_Delete - Connection is not open")));
           trace_StartRequest_ConnectionClosed();
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
  
Line 1664 
Line 1965 
     self->connector->sendHeader =     self->connector->sendHeader =
         _CreateHttpHeader(verb, uri, headers, (data && *data) ? (*data)->u.s.size : 0);         _CreateHttpHeader(verb, uri, headers, (data && *data) ? (*data)->u.s.size : 0);
  
     if (data)      if (data != NULL)
     {     {
         self->connector->sendPage = *data;         self->connector->sendPage = *data;
         *data = 0;         *data = 0;
     }     }
     else     else
     {          self->connector->sendPage = NULL;
         self->connector->sendPage = 0;  
     }  
  
     /* set status to failed, until we know more details */     /* set status to failed, until we know more details */
     self->connector->status = MI_RESULT_FAILED;     self->connector->status = MI_RESULT_FAILED;
Line 1685 
Line 1984 
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
   
 MI_Result HttpClient_Run( MI_Result HttpClient_Run(
     HttpClient* self,     HttpClient* self,
     MI_Uint64 timeoutUsec)     MI_Uint64 timeoutUsec)
 { {
     /* Run the selector */     /* Run the selector */
     return Selector_Run(self->selector, timeoutUsec);      return Selector_Run(self->selector, timeoutUsec, MI_FALSE);
 } }
  
 MI_Result HttpClient_SetTimeout( MI_Result HttpClient_SetTimeout(
Line 1700 
Line 1998 
 { {
     MI_Uint64 currentTimeUsec = 0;     MI_Uint64 currentTimeUsec = 0;
  
     Time_Now(&currentTimeUsec);      PAL_Time(&currentTimeUsec);
  
     /* check params */     /* check params */
     if (!self)     if (!self)
Line 1708 
Line 2006 
  
     if (self->magic != _MAGIC)     if (self->magic != _MAGIC)
     {     {
         LOGW((T("setTimeout: invalid magic!") ));          trace_Timeout_InvalidMagic();
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
     }     }
  
Line 1721 
Line 2019 
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
   
   


Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

ViewCVS 0.9.2