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

   1 mike  1.1 /*
   2           **==============================================================================
   3           **
   4           ** Open Management Infrastructure (OMI)
   5           **
   6           ** Copyright (c) Microsoft Corporation
   7           ** 
   8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
   9           ** use this file except in compliance with the License. You may obtain a copy 
  10           ** of the License at 
  11           **
  12           **     http://www.apache.org/licenses/LICENSE-2.0 
  13           **
  14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
  16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
  17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
  18           **
  19           ** See the Apache 2 License for the specific language governing permissions 
  20           ** and limitations under the License.
  21           **
  22 mike  1.1 **==============================================================================
  23           */
  24           
  25           #include <assert.h>
  26           #include <ctype.h>
  27           #include "http.h"
  28           #include <sock/addr.h>
  29           #include <sock/sock.h>
  30           #include <sock/selector.h>
  31           #include <base/time.h>
  32           #include <base/buf.h>
  33           #include <base/log.h>
  34           #include <base/result.h>
  35           #include <base/strings.h>
  36           #include <base/io.h>
  37           #include <base/paths.h>
  38           #include <base/base64.h>
  39           
  40           #ifdef CONFIG_POSIX
  41           #include <openssl/ssl.h>
  42           #include <openssl/err.h>
  43 mike  1.1 #include <pthread.h>
  44           #else
  45           /* ssl not supported in this configuration; just make compiler happy */
  46           typedef void SSL;
  47           typedef void SSL_CTX;
  48           #define SSL_CTX_free(c)
  49           #define SSL_new(c) 0
  50           #define SSL_free(c)
  51           #define SSL_set_fd(c,a) (a==a)
  52           #define SSL_read(c,a,b) 0
  53           #define SSL_write(c,a,b) 0
  54           #define SSL_get_error(c,e) e
  55           #define SSL_ERROR_WANT_WRITE 0
  56           #define SSL_ERROR_WANT_READ 1
  57           #define SSL_ERROR_SYSCALL 2
  58           
  59           #ifdef EWOULDBLOCK
  60           # undef EWOULDBLOCK
  61           #endif
  62           #define EWOULDBLOCK 0
  63           
  64 mike  1.1 #ifdef EINPROGRESS
  65           # undef EINPROGRESS
  66           #endif
  67           #define EINPROGRESS 0
  68           
  69           #define ERR_get_error() 0
  70           #define ERR_error_string_n(c,a,b) a[0]=0
  71           #define SSL_accept(c) 0
  72           
  73           #endif
  74           
  75           #define T MI_T
  76           
  77           /* #define ENABLE_TRACING  // */
  78           #ifdef  ENABLE_TRACING
  79           #define PRINTF(a)  TIMESTAMP(); printf a
  80           #define TIMESTAMP() \
  81           {\
  82                   MI_Uint64 currentTimeUsec = 0;\
  83           \
  84                   Time_Now(&currentTimeUsec);\
  85 mike  1.1         currentTimeUsec /= 1000;    /* ms */ \
  86                   printf("%ds%03dms ", (int)(currentTimeUsec / 1000 % 1000), (int)(currentTimeUsec % 1000));\
  87           }
  88           
  89           #define PRINTF_2(a)
  90           #else
  91           #define PRINTF(a)
  92           #define PRINTF_2(a)
  93           #endif
  94           
  95           
  96           
  97           /*
  98           **==============================================================================
  99           **
 100           ** Local definitions:
 101           **
 102           **==============================================================================
 103           */
 104           
 105           static const MI_Uint32 _MAGIC = 0xE0BB5FD3;
 106 mike  1.1 static const MI_Uint32 MAX_HEADER_SIZE = 2 * 1024;
 107           static const MI_Uint32 INITIAL_BUFFER_SIZE = 2 * 1024;
 108           static const size_t HTTP_MAX_CONTENT = 1024 * 1024;
 109           
 110           struct _Http
 111           {
 112               MI_Uint32           magic;
 113               Selector        internalSelector;
 114               Selector*       selector;
 115               HttpCallbackOnNewConnection     callbackOnNewConnection;
 116               HttpCallbackOnCloseConnection   callbackOnCloseConnection;
 117               HttpCallbackOnRequest           callbackOnRequest;
 118               void*                               callbackData;
 119               SSL_CTX*    sslContext;
 120               /* options: timeouts etc */
 121               HttpOptions     options;
 122               MI_Boolean  internalSelectorUsed;
 123           };
 124           
 125           typedef struct _Http_Listener_SocketData
 126           {
 127 mike  1.1     /* based member*/
 128               Handler     base;
 129           
 130               MI_Boolean secure;
 131           }
 132           Http_Listener_SocketData;
 133           
 134           typedef enum _Http_RecvState
 135           {
 136               RECV_STATE_HEADER,
 137               RECV_STATE_CONTENT
 138           }
 139           Http_RecvState;
 140           
 141           typedef struct _Http_SR_SocketData
 142           {
 143               /* based member*/
 144               Handler base;
 145           
 146               /* ssl part */
 147               SSL* ssl;
 148 mike  1.1     MI_Boolean reverseOperations;  /*reverse read/write Events/Handlers*/
 149               MI_Boolean acceptDone;
 150           
 151               /* is server/provider is processing request 
 152                   (to disbale timeout) */
 153               MI_Boolean requestIsBeingProcessed;
 154           
 155               /* link to next stack layer */
 156               void* connectionData;
 157           
 158               /* receiving data */
 159               char* recvBuffer;
 160               size_t recvBufferSize;
 161               size_t recvievedSize;
 162               Http_RecvState recvingState;
 163               HttpHeaders recvHeaders;
 164               Page* recvPage;
 165           
 166               /* sending part */
 167               Page* sendPage;
 168               size_t sentSize;
 169 mike  1.1     Http_RecvState sendingState;
 170               int httpErrorCode;
 171           
 172               /* Enable tracing */
 173               MI_Boolean enableTracing;
 174           }
 175           Http_SR_SocketData;
 176           
 177           /* helper functions result */
 178           typedef enum _Http_CallbackResult
 179           {
 180               PRT_CONTINUE,
 181               PRT_RETURN_TRUE,
 182               PRT_RETURN_FALSE
 183           }
 184           Http_CallbackResult;
 185           
 186           MI_INLINE MI_Uint8 _ToLower(MI_Uint8 x)
 187           {
 188               return (MI_Uint8)tolower(x);
 189           }
 190 mike  1.1 
 191           #define _HashCode(first,last,len) ( (((MI_Uint8)first) << 16) | (((MI_Uint8)last) << 8)  | (((MI_Uint16)len)) )
 192           
 193           
 194           static int _Base64DecCallback(
 195               const void* data, 
 196               size_t size, 
 197               void* callbackData)
 198           {
 199               char** str = (char**)callbackData;
 200               size_t i;
 201           
 202               for (i = 0; i < size; i++)
 203               {
 204                   **str = ((unsigned char*)data)[i];
 205                   (*str)++;
 206               }
 207           
 208               return 0;
 209           }
 210           
 211 mike  1.1 static MI_Boolean _DecodeBasicAuth(
 212               HttpHeaders* recvHeaders,
 213               const char * src,
 214               char* tgt)
 215           {
 216               char* startBuffer = tgt;
 217           
 218               /* skip spaces in value */
 219           
 220               while (src[0] == ' ' || src[0] == '\t')
 221                   src++;
 222           
 223               /* Decode the password */
 224           
 225               if (Base64Dec(src, strlen(src), _Base64DecCallback, &tgt) != 0)
 226               {
 227                   return MI_FALSE;
 228               }
 229           
 230               *tgt = 0;
 231           
 232 mike  1.1     /* decoded string has format: <uersname>[:<password>] */
 233               recvHeaders->username = startBuffer;
 234               startBuffer = strchr(startBuffer, ':');
 235           
 236               if ( startBuffer )
 237               {
 238                   *startBuffer = 0;
 239                   recvHeaders->password = startBuffer + 1;
 240               }
 241           
 242               return MI_TRUE; 
 243           }
 244           
 245           static MI_Boolean _getNameValuePair(
 246               char ** line,
 247               char ** value,
 248               int*  nameHashCode )
 249           {
 250               int len = 0;
 251               char* p;
 252               /* find name end /hash-code */
 253 mike  1.1 
 254               *nameHashCode =  _ToLower((MI_Uint8)(*line)[0])<<16;
 255           
 256               for (len = 1; (*line)[len] != ':' && (*line)[len] != '\r'; len++ )
 257                   ;
 258           
 259               if ((*line)[len] != ':')
 260                   return MI_FALSE;
 261           
 262               *nameHashCode |=  (len) | _ToLower((MI_Uint8)(*line)[len-1])<<8;
 263               (*line)[len] = 0;
 264               p = *line + len + 1;
 265           
 266               /* skip spaces in value */
 267               while (p[0] == ' ' || p[0] == '\t')
 268                   p++;
 269           
 270               *value = p;
 271           
 272               /* skip to end of line */
 273               for ( ; ; )
 274 mike  1.1     {
 275                   if (p[0] == '\r' && p[1] == '\n' && 
 276                       (p[2] != ' ' && p[2] != '\t') )
 277                   {
 278                       p[0] = 0;
 279                       (*line) = p + 2;
 280                       break;
 281                   }
 282                   p ++;
 283               }
 284           
 285               /* remove trailing spaces */
 286               p--;
 287               while (p[0] == ' ' || p[0] == '\t')
 288                   p--;
 289           
 290               p[1] = 0;
 291           
 292               return MI_TRUE;
 293           }
 294           
 295 mike  1.1 static void _ParseContentType(
 296               HttpHeaders* recvHeaders,
 297               char* value)
 298           {
 299               recvHeaders->contentType = value;
 300           
 301               /* find attribute list */
 302               while (value[0] != 0 && value[0] != ';')
 303                   value++;
 304           
 305               /* Check if attribute list was provided */
 306               if (value[0] == 0)
 307                   return;
 308           
 309               /* terminate type/subtype; move to attributes list */
 310               value[0] = 0;
 311               value++;
 312           
 313               /* skip spaces in value */
 314               while (value[0] == ' ' || value[0] == '\t')
 315                   value++;
 316 mike  1.1 
 317               /* find charset attribute (if present) */
 318               if (Strncasecmp(value,"charset=",8) != 0)
 319                   return;
 320           
 321               value += 8;
 322               recvHeaders->charset = value;
 323           
 324               /* can be enclosed in quotes */
 325               if (value[0] == '"')
 326               {
 327                   /* skip '"' */
 328                   recvHeaders->charset++;
 329                   value++;
 330                   value = strchr(value, '"');
 331                   if (value)
 332                       *value = 0;
 333                   else
 334                       recvHeaders->charset = 0;
 335               }
 336               else
 337 mike  1.1     {
 338                   /*skip trialing spaces */
 339                   while (value[0] != 0 && value[0] != ' ' && value[0] != '\t')
 340                       value++;
 341           
 342                   *value = 0;
 343               }
 344           }
 345           
 346           static MI_Boolean _getHeaderField(
 347               Http_SR_SocketData* handler,
 348               char ** line)
 349           {
 350               char* name = *line;
 351               char* value = NULL;
 352               int nameHashCode;
 353           
 354               if (!_getNameValuePair(line, &value, &nameHashCode))
 355                   return MI_FALSE;
 356           
 357           
 358 mike  1.1     switch (nameHashCode)
 359               {
 360               case (_HashCode('c','e',12)): /*Content-Type*/
 361                   if (Strcasecmp(name,"Content-Type") == 0)
 362                       _ParseContentType(&handler->recvHeaders, value);
 363           
 364                   break;
 365           
 366               case (_HashCode('c','h',14)): /*Content-Length*/
 367                   if (Strcasecmp(name,"Content-Length") == 0)
 368                   {
 369                       handler->recvHeaders.contentLength = (size_t)Strtoull(value, NULL, 10);
 370                       if ( handler->recvHeaders.contentLength > HTTP_MAX_CONTENT )
 371                           return MI_FALSE;
 372                   }
 373                   break;
 374           
 375               case (_HashCode('a','n',13)): /*Authorization*/
 376                   if (Strcasecmp(name,"Authorization") == 0)
 377                   {
 378                       if (Strncasecmp(value,"Basic",5) == 0)
 379 mike  1.1             {
 380                           /* since decoded string is smaller, performing decoding inplace;
 381                               for source skip 'Basic ' part (6 chars) */
 382                           if (!_DecodeBasicAuth(&handler->recvHeaders, value + 6, value))
 383                           {
 384                               LOGW_CHAR(("base64 decoding error in Basic auth: [%s]\n", value));
 385                               return MI_FALSE;
 386                           }
 387                       }
 388                       else    /* unknown authorization type */
 389                           handler->recvHeaders.authorization = value;
 390                   }
 391                   break;
 392           
 393               default:
 394                   break;
 395           
 396               }
 397           
 398               return MI_TRUE;
 399           }
 400 mike  1.1 
 401           static MI_Boolean _getRequestLine(
 402               Http_SR_SocketData* handler,
 403               char ** line)
 404           {
 405               size_t index;
 406               /* expecting  Request-Line = Method SP Request-URI SP HTTP-Version CRLF
 407                   Read more: http://www.faqs.org/rfcs/rfc2616.html#ixzz0jKdjJdZv
 408               */
 409           
 410               /* skip to end of line */
 411               for ( index = 1; index < handler->recvievedSize; index++ )
 412               {
 413                   if ((*line)[index-1] == '\r' && (*line)[index] == '\n' )
 414                   {
 415                       (*line) = (*line) + index + 1;
 416                       return MI_TRUE;
 417                   }
 418               }
 419           
 420               return MI_FALSE;
 421 mike  1.1 }
 422           
 423           static MI_Result _Sock_ReadAux(
 424               Http_SR_SocketData* handler,
 425               void* buf,
 426               size_t buf_size,
 427               size_t* sizeRead)
 428           {
 429               int res;
 430           
 431               if (!handler->ssl)
 432                   return Sock_Read(handler->base.sock, buf, buf_size, sizeRead);
 433           
 434               handler->base.mask &= ~SELECTOR_WRITE;
 435               handler->base.mask |= SELECTOR_READ;
 436               handler->reverseOperations = MI_FALSE;
 437           
 438               *sizeRead = 0;
 439           
 440               if (handler->acceptDone)
 441               {
 442 mike  1.1         res = SSL_read(handler->ssl, buf, buf_size);
 443                   PRINTF(("ssl read %d\n", res));
 444               }
 445               else
 446               {
 447                   res = SSL_accept(handler->ssl);
 448                   PRINTF(("ssl accept %d\n", res));
 449                   if ( res > 0 )
 450                   {
 451                       /* we are done with accpet */
 452                       handler->acceptDone = MI_TRUE;
 453                       return _Sock_ReadAux(handler,buf,buf_size,sizeRead);
 454                   }
 455                   /* perform regular error checking */
 456               }
 457           
 458               if ( res == 0 )
 459                   return MI_RESULT_OK;    /* connection closed */
 460           
 461               if ( res > 0 )
 462               {
 463 mike  1.1         *sizeRead = res;
 464                   return MI_RESULT_OK;    /* ok */
 465               }
 466           
 467               switch (SSL_get_error(handler->ssl, res))
 468               {
 469               case SSL_ERROR_WANT_WRITE:
 470                   handler->reverseOperations = MI_TRUE;   /* wait until write is allowed */
 471                   handler->base.mask |= SELECTOR_WRITE;
 472                   handler->base.mask &= ~SELECTOR_READ;
 473                   PRINTF(("ssl read/accept WANT_WRITE\n"));
 474                   return MI_RESULT_WOULD_BLOCK;
 475           
 476               case SSL_ERROR_WANT_READ:
 477                   PRINTF(("ssl read/accept WANT_READ\n"));
 478                   return MI_RESULT_WOULD_BLOCK;
 479           
 480               case SSL_ERROR_SYSCALL:
 481                   if (EAGAIN == errno ||
 482                       EWOULDBLOCK == errno ||
 483                       EINPROGRESS == errno)
 484 mike  1.1             return MI_RESULT_WOULD_BLOCK;
 485           
 486                   LOGW_CHAR(("ssl-read: unexpected sys error %d\n", errno));
 487                   break;
 488           
 489               default:
 490                   {
 491                       /* print error */
 492                       unsigned long err = ERR_get_error();
 493                       while (err)
 494                       {
 495                           char err_txt[200];
 496                           ERR_error_string_n(err, err_txt, sizeof(err_txt));
 497           
 498                           LOGW_CHAR(("ssl-read error: %d [%s]\n", (int)err, err_txt));
 499           
 500                           err = ERR_get_error();
 501                       }
 502                   }
 503                   break;
 504               }
 505 mike  1.1     return MI_RESULT_FAILED;
 506           }
 507           
 508           static MI_Result _Sock_WriteAux(
 509               Http_SR_SocketData* handler,
 510               void* buf,
 511               size_t buf_size,
 512               size_t* sizeWritten)
 513           {
 514               int res;
 515           
 516               if (!handler->ssl)
 517                   return Sock_Write(handler->base.sock, buf, buf_size, sizeWritten);
 518           
 519               /* Do not clear READ flag, since 'close' notification
 520               delivered as READ event*/
 521               handler->base.mask &= ~SELECTOR_READ; 
 522               handler->base.mask |= SELECTOR_WRITE;
 523               handler->reverseOperations = MI_FALSE;
 524           
 525               *sizeWritten = 0;
 526 mike  1.1     res = SSL_write(handler->ssl, buf, buf_size);
 527               PRINTF(("ssl write %d\n", res));
 528           
 529               if ( res == 0 )
 530                   return MI_RESULT_OK;    /* connection closed */
 531           
 532               if ( res > 0 )
 533               {
 534                   *sizeWritten = res;
 535                   return MI_RESULT_OK;    /* ok */
 536               }
 537           
 538               switch (SSL_get_error(handler->ssl, res))
 539               {
 540               case SSL_ERROR_WANT_WRITE:
 541                   return MI_RESULT_WOULD_BLOCK;
 542           
 543               case SSL_ERROR_WANT_READ:
 544                   handler->reverseOperations = MI_TRUE;   /* wait until write is allowed */
 545                   handler->base.mask |= SELECTOR_READ;
 546                   handler->base.mask &= ~SELECTOR_WRITE;
 547 mike  1.1         return MI_RESULT_WOULD_BLOCK;
 548           
 549               case SSL_ERROR_SYSCALL:
 550                   if (EAGAIN == errno ||
 551                       EWOULDBLOCK == errno ||
 552                       EINPROGRESS == errno)
 553                       return MI_RESULT_WOULD_BLOCK;
 554           
 555                   LOGW_CHAR(("ssl-write: unexpected sys error %d\n", errno));
 556                   break;
 557           
 558               default:
 559                   break;
 560               }
 561               return MI_RESULT_FAILED;
 562           }
 563           
 564           static void _WriteTraceFile(PathID id, void* data, size_t size)
 565           {
 566               static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
 567               const char* path;
 568 mike  1.1     
 569               if (!(path = GetPath(id)))
 570                   return;
 571           
 572               pthread_mutex_lock(&s_mutex);
 573               {
 574                   FILE* out = fopen(path, "a");
 575           
 576                   if (out)
 577                       fwrite(data, 1, size, out);
 578           
 579                   fclose(out);
 580               }
 581               pthread_mutex_unlock(&s_mutex);
 582           }
 583           
 584           INLINE MI_Result _Sock_Read(
 585               Http_SR_SocketData* handler,
 586               void* buf,
 587               size_t buf_size,
 588               size_t* sizeRead)
 589 mike  1.1 {
 590               MI_Result r = _Sock_ReadAux(handler, buf, buf_size, sizeRead);
 591           
 592               if (r == MI_RESULT_OK && handler->enableTracing)
 593               {
 594                   _WriteTraceFile(ID_HTTPRECVTRACEFILE, buf, *sizeRead);
 595               }
 596           
 597               return r;
 598           }
 599           
 600           INLINE MI_Result _Sock_Write(
 601               Http_SR_SocketData* handler,
 602               void* buf,
 603               size_t buf_size,
 604               size_t* sizeWritten)
 605           {
 606               MI_Result r = _Sock_WriteAux(handler, buf, buf_size, sizeWritten);
 607           
 608               if (r == MI_RESULT_OK && handler->enableTracing)
 609               {
 610 mike  1.1         _WriteTraceFile(ID_HTTPSENDTRACEFILE, buf, *sizeWritten);
 611               }
 612           
 613               return r;
 614           }
 615           
 616           static Http_CallbackResult _ReadHeader(
 617               Http_SR_SocketData* handler)
 618           {
 619               char* buf;
 620               char* currentLine;
 621               char* data;
 622               size_t buf_size, received, index;
 623               MI_Result r;
 624               MI_Boolean fullHeaderReceived = MI_FALSE;
 625           
 626               /* are we done with header? */
 627               if (handler->recvingState == RECV_STATE_CONTENT)
 628                   return PRT_CONTINUE;
 629           
 630               buf = handler->recvBuffer + handler->recvievedSize;
 631 mike  1.1     buf_size = handler->recvBufferSize - handler->recvievedSize;
 632               received = 0;
 633           
 634               r = _Sock_Read(handler, buf, buf_size, &received);
 635               PRINTF(("%d: read r = %d, recv = %d; reverse %d\n", (int)handler->base.sock, (int)r, (int)received, (int)handler->reverseOperations ));
 636           
 637               if ( r == MI_RESULT_OK && 0 == received )
 638                   return PRT_RETURN_FALSE; /* conection closed */
 639           
 640               if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
 641                   return PRT_RETURN_FALSE;
 642           
 643               if (!received)
 644                   return PRT_RETURN_TRUE;
 645           
 646               handler->recvievedSize += received;
 647           
 648               /* check header */
 649               PRINTF_2(("%s\n",buf));
 650           
 651               /* did we get full header? */
 652 mike  1.1     buf = handler->recvBuffer;
 653               for ( index = 3; index < handler->recvievedSize; index++ )
 654               {
 655                   if (buf[index-3] == '\r' && buf[index-1] == '\r' &&
 656                       buf[index-2] == '\n' && buf[index] == '\n' )
 657                   {
 658                       fullHeaderReceived = MI_TRUE;
 659                       break;
 660                   }
 661               }
 662           
 663               if (!fullHeaderReceived )
 664               {
 665                   if ( handler->recvievedSize <  handler->recvBufferSize )
 666                       return PRT_RETURN_TRUE; /* continue reading */
 667           
 668                   if ( handler->recvBufferSize < MAX_HEADER_SIZE )
 669                   {
 670                       buf = realloc(handler->recvBuffer, handler->recvBufferSize * 2);
 671           
 672                       if (!buf)
 673 mike  1.1                 return PRT_RETURN_FALSE;
 674           
 675                       handler->recvBufferSize *= 2;
 676                       handler->recvBuffer = buf;
 677                       return _ReadHeader(handler);
 678                   }
 679                   else
 680                   {
 681                       /* http header is too big - drop connection */
 682                       LOGW((T("http header is too big; dropping connection\n")));
 683                       return PRT_RETURN_FALSE;
 684                   }
 685               }
 686           
 687               /* consume data */
 688               currentLine = buf;
 689               data = buf + index + 1; /* pointer to data in case we got some */
 690           
 691               if (!_getRequestLine(handler, &currentLine))
 692                   return PRT_RETURN_FALSE;
 693           
 694 mike  1.1 
 695               while ((data-currentLine) > 3)
 696               {
 697                   if (!_getHeaderField(handler, &currentLine))
 698                       return PRT_RETURN_FALSE;
 699           
 700               }
 701           
 702               /* Allocate zero-terminated buffer */
 703               handler->recvPage = (Page*)malloc(sizeof(Page) + handler->recvHeaders.contentLength + 1);
 704           
 705               if (!handler->recvPage)
 706                   return PRT_RETURN_FALSE;
 707           
 708               ((char*)(handler->recvPage + 1))[handler->recvHeaders.contentLength] = 0;
 709           
 710               handler->recvPage->u.s.size = (unsigned int)handler->recvHeaders.contentLength;
 711               handler->recvPage->u.s.next = 0;
 712           
 713               handler->recvievedSize -= index + 1;
 714           
 715 mike  1.1     /* Verify that we have not more than 'content-length' bytes in buffer left 
 716                   If we hvae more, assuming http client is invalid and drop connection */
 717               if (handler->recvievedSize > handler->recvHeaders.contentLength)
 718               {
 719                   LOGW((T("http payload is bigger than content-length\n")));
 720                   return PRT_RETURN_FALSE;
 721               }
 722           
 723               memcpy( handler->recvPage + 1, data, handler->recvievedSize );
 724               handler->recvingState = RECV_STATE_CONTENT;
 725           
 726               PRINTF_2(("full header read; page size %d, position %d\n", handler->recvPage->u.s.size, handler->recvievedSize));
 727           
 728               return PRT_CONTINUE;
 729           }
 730           
 731           static Http_CallbackResult _ReadData(
 732               Http_SR_SocketData* handler)
 733           {
 734               Http* self = (Http*)handler->base.data;
 735               char* buf;
 736 mike  1.1     size_t buf_size, received;
 737               MI_Result r;
 738           
 739               /* are we in the right state? */
 740               if (handler->recvingState != RECV_STATE_CONTENT)
 741                   return PRT_RETURN_FALSE;
 742           
 743               buf = ((char*)(handler->recvPage + 1)) + handler->recvievedSize;
 744               buf_size = handler->recvHeaders.contentLength - handler->recvievedSize;
 745               received = 0;
 746           
 747               if (buf_size)
 748               {
 749                   r = _Sock_Read(handler, buf, buf_size, &received);
 750           
 751                   PRINTF(("%d: read r = %d, recv = %d\n", (int)handler->base.sock, (int)r, (int)received ));
 752           
 753                   if ( r == MI_RESULT_OK && 0 == received )
 754                       return PRT_RETURN_FALSE; /* conection closed */
 755           
 756                   if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
 757 mike  1.1             return PRT_RETURN_FALSE;
 758           
 759                   handler->recvievedSize += received;
 760               }
 761           
 762               /* did we get all data? */
 763               PRINTF_2(("dt status - %d / %d\n", (int)handler->recvievedSize, (int)handler->recvHeaders.contentLength));
 764           
 765               if ( handler->recvievedSize != handler->recvHeaders.contentLength )
 766                   return PRT_RETURN_TRUE;
 767            
 768               handler->requestIsBeingProcessed = MI_TRUE;
 769               (*self->callbackOnRequest)( self, self->callbackData, handler->connectionData, handler, &handler->recvHeaders,
 770                   &handler->recvPage );
 771           
 772               if (handler->recvPage)
 773                   free(handler->recvPage);
 774           
 775               handler->recvPage = 0;
 776               handler->recvievedSize = 0;
 777               memset(&handler->recvHeaders, 0, sizeof(handler->recvHeaders));
 778 mike  1.1     handler->recvingState = RECV_STATE_HEADER;
 779               return PRT_CONTINUE;
 780           }
 781           
 782           static MI_Boolean _RequestCallbackRead(
 783               Http_SR_SocketData* handler)
 784           {
 785               switch (_ReadHeader(handler))
 786               {
 787               case PRT_CONTINUE: break;
 788               case PRT_RETURN_TRUE: return MI_TRUE;
 789               case PRT_RETURN_FALSE: return MI_FALSE;
 790               }
 791           
 792               switch (_ReadData(handler))
 793               {
 794               case PRT_CONTINUE: break;
 795               case PRT_RETURN_TRUE: return MI_TRUE;
 796               case PRT_RETURN_FALSE: return MI_FALSE;
 797               }
 798               return MI_TRUE;
 799 mike  1.1 }
 800           
 801           /* length of longest description - has to be updated if descriptions are updated */
 802           #define HTTP_LONGEST_ERROR_DESCRIPTION 50
 803           static const char* _GetHttpErrorCodeDescription(
 804               int httpErrorCode )
 805           {
 806               switch (httpErrorCode)
 807               {
 808               case 200:
 809                   return "OK";
 810           
 811               case 400:
 812                   return "Bad Request";
 813           
 814               case 401:
 815                   return "Unauthorized";
 816           
 817               case 500:
 818                   return "Internal Server Error";
 819               }
 820 mike  1.1     return "Error";
 821           }
 822           
 823           static Http_CallbackResult _WriteHeader(
 824               Http_SR_SocketData* handler)
 825           {
 826           #define RESPONSE_HEADER_FMT \
 827               "HTTP/1.1 %d %s\r\n"   \
 828               "Content-Length: %d\r\n"\
 829               "Connection: Keep-Alive\r\n"\
 830               "Content-Type: application/soap+xml;charset=UTF-8\r\n"\
 831               "\r\n"
 832           
 833           /*    "SOAPAction: http://schemas.xmlsoap.org/ws/2004/08/addressing/fault\r\n"\ */
 834           
 835               char currentLine[sizeof(RESPONSE_HEADER_FMT) + 
 836                   10 /* content length */ + 
 837                   10 /*error code*/ + 
 838                   HTTP_LONGEST_ERROR_DESCRIPTION /* code descirpiton */ ];
 839               char* buf;
 840               size_t buf_size, sent;
 841 mike  1.1     MI_Result r;
 842           
 843               /* Do we have any data to send? */
 844               if (!handler->sendPage && 0 == handler->httpErrorCode)
 845                   return PRT_RETURN_TRUE;
 846           
 847               /* are we done with header? */
 848               if (handler->sendingState == RECV_STATE_CONTENT)
 849                   return PRT_CONTINUE;
 850           
 851               if (handler->sendPage)
 852               {
 853                   buf_size = (size_t)Snprintf(
 854                       currentLine,
 855                       sizeof(currentLine),
 856                       RESPONSE_HEADER_FMT, 
 857                       (int)handler->httpErrorCode, 
 858                       _GetHttpErrorCodeDescription(handler->httpErrorCode),
 859                       (int)handler->sendPage->u.s.size );
 860               }
 861               else
 862 mike  1.1     {
 863                   buf_size = (size_t)Snprintf(
 864                       currentLine,
 865                       sizeof(currentLine),
 866                       "HTTP/1.1 %d %s\r\n\r\n", 
 867                       (int)handler->httpErrorCode,
 868                       _GetHttpErrorCodeDescription(handler->httpErrorCode));
 869               }
 870           
 871               buf = currentLine + handler->sentSize;
 872           
 873               sent = 0;
 874           
 875               r = _Sock_Write(handler, buf, buf_size - handler->sentSize, &sent);
 876           
 877               PRINTF(("%d: write r = %d, sent = %d; reverse %d\n", (int)handler->base.sock, (int)r, (int)sent, (int)handler->reverseOperations ));
 878           
 879               if ( r == MI_RESULT_OK && 0 == sent )
 880                   return PRT_RETURN_FALSE; /* conection closed */
 881           
 882               if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
 883 mike  1.1         return PRT_RETURN_FALSE;
 884           
 885               if (!sent)
 886                   return PRT_RETURN_TRUE;
 887           
 888               handler->sentSize += sent;
 889           
 890               if (handler->sentSize < buf_size)
 891                   return PRT_RETURN_TRUE;
 892           
 893               handler->sentSize = 0;
 894               handler->sendingState = RECV_STATE_CONTENT;
 895               return PRT_CONTINUE;
 896           }
 897           
 898           static Http_CallbackResult _WriteData(
 899               Http_SR_SocketData* handler)
 900           {
 901               char* buf;
 902               size_t buf_size, sent;
 903               MI_Result r;
 904 mike  1.1 
 905               /* are we in the right state? */
 906               if (handler->sendingState != RECV_STATE_CONTENT)
 907                   return PRT_RETURN_FALSE;
 908           
 909               if (!handler->sendPage)
 910               {   /* no content*/
 911                   handler->httpErrorCode = 0;
 912                   handler->sentSize = 0;
 913                   handler->sendingState = RECV_STATE_HEADER;
 914                   handler->base.mask &= ~SELECTOR_WRITE;
 915                   handler->base.mask |= SELECTOR_READ;
 916                   return PRT_CONTINUE;
 917               }
 918           
 919               buf = ((char*)(handler->sendPage + 1)) + handler->sentSize;
 920               buf_size = handler->sendPage->u.s.size - handler->sentSize;
 921               sent = 0;
 922           
 923               r = _Sock_Write(handler, buf, buf_size, &sent);
 924           
 925 mike  1.1     PRINTF(("%d: write r = %d, sent = %d\n", (int)handler->base.sock, (int)r, (int)sent ));
 926           
 927               if ( r == MI_RESULT_OK && 0 == sent )
 928                   return PRT_RETURN_FALSE; /* conection closed */
 929           
 930               if ( r != MI_RESULT_OK && r != MI_RESULT_WOULD_BLOCK )
 931                   return PRT_RETURN_FALSE;
 932           
 933               handler->sentSize += sent;
 934           
 935               /* did we get all data? */
 936           
 937               if ( handler->sentSize != handler->sendPage->u.s.size )
 938                   return PRT_RETURN_TRUE;
 939            
 940               free(handler->sendPage);
 941               handler->sendPage = 0;
 942               handler->httpErrorCode = 0;
 943               handler->sentSize = 0;
 944               handler->sendingState = RECV_STATE_HEADER;
 945               handler->base.mask &= ~SELECTOR_WRITE;
 946 mike  1.1     handler->base.mask |= SELECTOR_READ;
 947           
 948               return PRT_CONTINUE;
 949           }
 950           
 951           static MI_Boolean _RequestCallbackWrite(
 952               Http_SR_SocketData* handler)
 953           {
 954               switch (_WriteHeader(handler))
 955               {
 956               case PRT_CONTINUE: break;
 957               case PRT_RETURN_TRUE: return MI_TRUE;
 958               case PRT_RETURN_FALSE: return MI_FALSE;
 959               }
 960           
 961               switch (_WriteData(handler))
 962               {
 963               case PRT_CONTINUE: break;
 964               case PRT_RETURN_TRUE: return MI_TRUE;
 965               case PRT_RETURN_FALSE: return MI_FALSE;
 966               }
 967 mike  1.1     return MI_TRUE;
 968           }
 969           
 970           static MI_Boolean _RequestCallback(
 971               Selector* sel,
 972               Handler* handlerIn,
 973               MI_Uint32 mask, 
 974               MI_Uint64 currentTimeUsec)
 975           {
 976               Http_SR_SocketData* handler = (Http_SR_SocketData*)handlerIn;
 977               sel=sel;
 978           
 979               if ( ((mask & SELECTOR_READ) != 0 && !handler->reverseOperations) ||
 980                   ((mask & SELECTOR_WRITE) != 0 && handler->reverseOperations) )
 981               {
 982                   if (!_RequestCallbackRead(handler))
 983                       return MI_FALSE;
 984               }
 985           
 986               if ( ((mask & SELECTOR_WRITE) != 0 && !handler->reverseOperations) ||
 987                   ((mask & SELECTOR_READ) != 0 && handler->reverseOperations) )
 988 mike  1.1     {
 989                   if (!_RequestCallbackWrite(handler))
 990                       return MI_FALSE;
 991               }
 992               
 993               /* re-set timeout - if we performed R/W operation, set timeout depending where we are in communication */
 994               if (mask & (SELECTOR_READ | SELECTOR_WRITE))
 995               {
 996                   Http* self = (Http*)handler->base.data;
 997           
 998                   if (handler->requestIsBeingProcessed)
 999                   {
1000                       /* since request is processed by server, disable timeout for this period */
1001                       handler->base.fireTimeoutAt = TIME_NEVER;
1002                   }
1003                   else
1004                   {
1005                       /* Use configuration timeout */
1006                       handler->base.fireTimeoutAt = currentTimeUsec + self->options.timeoutUsec;
1007                   }
1008               }
1009 mike  1.1 
1010               /* Close conenction by timeout */
1011               if (mask & SELECTOR_TIMEOUT)
1012                   return MI_FALSE;
1013           
1014               if ((mask & SELECTOR_REMOVE) != 0 ||
1015                   (mask & SELECTOR_DESTROY) != 0)
1016               {
1017                   Http* self = (Http*)handler->base.data;
1018           
1019                   /* notify next stack layer */
1020                   (*self->callbackOnCloseConnection)(
1021                       self, 
1022                       self->callbackData, 
1023                       handler->connectionData );
1024           
1025                   if (handler->ssl)
1026                       SSL_free(handler->ssl);
1027           
1028                   PRINTF(("%d: close\n", (int)handler->base.sock));
1029           
1030 mike  1.1         Sock_Close(handler->base.sock);
1031           
1032                   if (handler->recvPage)
1033                       free(handler->recvPage);
1034           
1035                   if (handler->sendPage)
1036                       free(handler->sendPage);
1037           
1038                   free(handler->recvBuffer);
1039                   free(handler);
1040               }
1041           
1042               return MI_TRUE;
1043           }
1044           
1045           static MI_Boolean _ListenerCallback(
1046               Selector* sel,
1047               Handler* handler_,
1048               MI_Uint32 mask, 
1049               MI_Uint64 currentTimeUsec)
1050           {
1051 mike  1.1     Http_Listener_SocketData* handler = (Http_Listener_SocketData*)handler_;
1052               Http* self = (Http*)handler->base.data;
1053               MI_Result r;
1054               Sock s;
1055               Addr addr;
1056               Http_SR_SocketData* h;
1057           
1058               sel=sel;
1059               mask=mask;
1060               currentTimeUsec = currentTimeUsec;
1061           
1062               if (mask & SELECTOR_READ)
1063               {
1064                   int count;
1065           
1066                   for (count = 0; count < 5; count++)
1067                   {
1068                       /* Accept the incoming connection */
1069                       r = Sock_Accept(handler->base.sock, &s, &addr);
1070           
1071                       PRINTF(("%d: accept r = %d\n", (int)s, (int)r ));
1072 mike  1.1 
1073                       if (MI_RESULT_WOULD_BLOCK == r)
1074                           return MI_TRUE;
1075           
1076           
1077                       if (r != MI_RESULT_OK)
1078                       {
1079                           LOGW((T("Sock_Accept() failed; err %d\n"), Sock_GetLastError()));
1080                           return MI_TRUE;
1081                       }
1082           
1083                       r = Sock_SetBlocking(s, MI_FALSE);
1084                       if (r != MI_RESULT_OK)
1085                       {
1086                           LOGW((T("Sock_SetBlocking() failed\n")));
1087                           Sock_Close(s);
1088                           return MI_TRUE;
1089                       }
1090           
1091                       /* Create handler */
1092                       h = (Http_SR_SocketData*)calloc(1, sizeof(Http_SR_SocketData));
1093 mike  1.1 
1094                       if (!h)
1095                       {
1096                           Sock_Close(s);
1097                           return MI_TRUE;
1098                       }
1099           
1100                       h->recvBufferSize = INITIAL_BUFFER_SIZE;
1101                       h->recvBuffer = (char*)calloc(1, h->recvBufferSize);
1102                       if (!h->recvBuffer)
1103                       {
1104                           free(h);
1105                           Sock_Close(s);
1106                           return MI_TRUE;
1107                       }
1108           
1109                       h->base.sock = s;
1110                       h->base.mask = SELECTOR_READ | SELECTOR_EXCEPTION;
1111                       h->base.callback = _RequestCallback;
1112                       h->base.data = self;
1113                       h->base.fireTimeoutAt = currentTimeUsec + self->options.timeoutUsec;
1114 mike  1.1             h->enableTracing = self->options.enableTracing;
1115           
1116                       /* ssl support */
1117                       if (handler->secure)
1118                       {
1119                           h->ssl = SSL_new(self->sslContext);
1120           
1121                           if (!h->ssl)
1122                           {
1123                               LOGW((T("ssl_new() failed\n")));
1124                               free(h);
1125                               Sock_Close(s);
1126                               return MI_TRUE;
1127                           }
1128           
1129                           if (!(SSL_set_fd(h->ssl, s) ))
1130                           {
1131                               LOGW((T("ssl_set_fd() failed\n")));
1132                               SSL_free(h->ssl);
1133                               free(h);
1134                               Sock_Close(s);
1135 mike  1.1                     return MI_TRUE;
1136                           }
1137           
1138                       }
1139           
1140                       /* Watch for read events on the incoming connection */
1141                       r = Selector_AddHandler(self->selector, &h->base);
1142           
1143                       if (r != MI_RESULT_OK)
1144                       {
1145                           LOGW((T("Selector_AddHandler() failed\n")));
1146                           if (handler->secure)
1147                               SSL_free(h->ssl);
1148                           free(h);
1149                           Sock_Close(s);
1150                           return MI_TRUE;
1151                       }
1152           
1153                       /* notify next stack layer about new connection */
1154                       (*self->callbackOnNewConnection)(
1155                           self, 
1156 mike  1.1                 self->callbackData, 
1157                           h,
1158                           &h->connectionData );
1159                   }
1160               }
1161           
1162               if ((mask & SELECTOR_REMOVE) != 0 ||
1163                   (mask & SELECTOR_DESTROY) != 0)
1164               {
1165                   Sock_Close(handler->base.sock);
1166                   free(handler);
1167               }
1168           
1169               return MI_TRUE;
1170           }
1171           
1172           static MI_Result _New_Http(
1173               Http** selfOut,
1174               Selector* selector, /*optional, maybe NULL*/
1175               HttpCallbackOnNewConnection callbackOnNewConnection,
1176               HttpCallbackOnCloseConnection callbackOnCloseConnection,
1177 mike  1.1     HttpCallbackOnRequest callbackOnRequest,
1178               void* callbackData)
1179           {
1180               Http* self;
1181           
1182               /* Check parameters */
1183               if (!selfOut)
1184                   return MI_RESULT_INVALID_PARAMETER;
1185           
1186               /* Clear output parameter */
1187               *selfOut = NULL;
1188           
1189               /* Allocate structure */
1190               {
1191                   self = (Http*)calloc(1, sizeof(Http));
1192           
1193                   if (!self)
1194                       return MI_RESULT_FAILED;
1195               }
1196           
1197               if (selector)
1198 mike  1.1     {   /* attach the exisiting selector */
1199                   self->selector = selector;
1200                   self->internalSelectorUsed = MI_FALSE;
1201               }
1202               else
1203               {   /* creaet a new selector */
1204                   /* Initialize the network */
1205                   Sock_Start();
1206           
1207                   /* Initialize the selector */
1208                   if (Selector_Init(&self->internalSelector) != MI_RESULT_OK)
1209                   {
1210                       free(self);
1211                       return MI_RESULT_FAILED;
1212                   }
1213                   self->selector = &self->internalSelector;
1214                   self->internalSelectorUsed = MI_TRUE;
1215               }
1216           
1217               /* Save the callback and callbackData */
1218               self->callbackOnRequest = callbackOnRequest;
1219 mike  1.1     self->callbackOnCloseConnection = callbackOnCloseConnection;
1220               self->callbackOnNewConnection = callbackOnNewConnection;
1221               self->callbackData = callbackData;
1222           
1223               /* Set the magic number */
1224               self->magic = _MAGIC;
1225           
1226               /* options */
1227               {
1228                   HttpOptions options = DEFAULT_HTTP_OPTIONS;
1229                   self->options = options;
1230               }
1231           
1232               /* Set output parameter */
1233               *selfOut = self;
1234               return MI_RESULT_OK;
1235           }
1236           
1237           #ifdef CONFIG_POSIX
1238           static MI_Boolean _verifyPrivateKey(
1239               SSL_CTX *ctx, 
1240 mike  1.1     const char* keyPath)
1241           {
1242               // Open the private key file.
1243           
1244               FILE* is = fopen(keyPath, "r");
1245           
1246               if (!is)
1247               {
1248                   LOGE_CHAR((
1249                       "---> SSL: failed to open private key file: %s",
1250                       keyPath));
1251                   return MI_FALSE;
1252               }
1253           
1254               // Read the private key from the input stream.
1255           
1256               EVP_PKEY* pkey;
1257               pkey = PEM_read_PrivateKey(is, NULL, NULL, NULL);
1258           
1259               if (!pkey)
1260               {
1261 mike  1.1         LOGE_CHAR(("---> SSL: failed to create private key"));
1262                   return MI_FALSE;
1263               }
1264           
1265               /* Close the input stream. */
1266           
1267               fclose(is);
1268           
1269               /* Associate the new private key with the SSL context object. */
1270           
1271               if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0)
1272               {
1273                   EVP_PKEY_free(pkey);
1274                   LOGE_CHAR((
1275                       "---> SSL: no private key found in %s",
1276                       keyPath));
1277                   return MI_FALSE;
1278               }
1279           
1280               EVP_PKEY_free(pkey);
1281           
1282 mike  1.1     /* Check private key for validity. */
1283           
1284               if (!SSL_CTX_check_private_key(ctx))
1285               {
1286                   LOGE_CHAR((
1287                       "---> SSL: Private and public key do not match"));
1288                   return MI_FALSE;
1289               }
1290           
1291               return MI_TRUE;
1292           }
1293           
1294           static MI_Result _CreateSSLContext(Http* self)
1295           {
1296               SSL_CTX * sslContext = 0;
1297           
1298               sslContext = SSL_CTX_new(SSLv23_method());
1299           
1300               if (!sslContext)
1301               {
1302                   LOGE_CHAR((
1303 mike  1.1             "---> SSL: cannot create ssl context"));
1304                   return MI_RESULT_FAILED;
1305               }
1306               SSL_CTX_set_quiet_shutdown(sslContext, 1);
1307               SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY);
1308               SSL_CTX_set_mode(sslContext, SSL_MODE_ENABLE_PARTIAL_WRITE);
1309               SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
1310           
1311               /* Check if there is a certificate file (file containing server
1312               ** certificate) specified. If specified, validate and load the
1313               ** certificate.
1314               */
1315               {
1316                   /* load the specified server certificates */
1317                   LOGI_CHAR(("---> SSL: Loading server certificate from: %s", 
1318                       GetPath(ID_PEMFILE)));
1319           
1320                   if (SSL_CTX_use_certificate_file(sslContext,
1321                       GetPath(ID_PEMFILE), SSL_FILETYPE_PEM) <=0)
1322                   {
1323                       LOGE_CHAR(("---> SSL: No server certificate found in %s", 
1324 mike  1.1                 GetPath(ID_PEMFILE)));
1325                       SSL_CTX_free(sslContext);
1326                       return MI_RESULT_FAILED;
1327                   }
1328               }
1329           
1330               /*
1331               ** Check if there is a key file (file containing server
1332               ** private key) specified and the key was not already loaded.
1333               ** If specified, validate and load the key.
1334               */
1335               {
1336                   /* load the specified server certificates */
1337                   LOGI_CHAR(("---> SSL: Loading certificate's private key from: %s",
1338                       GetPath(ID_KEYFILE)));
1339           
1340                   //
1341                   // load given private key and check for validity
1342                   //
1343                   if (!_verifyPrivateKey(sslContext, GetPath(ID_KEYFILE)))
1344                   {
1345 mike  1.1             LOGE_CHAR((
1346                           "---> SSL: No server certificate found in %s",
1347                           GetPath(ID_KEYFILE)));
1348                       SSL_CTX_free(sslContext);
1349                       return MI_RESULT_FAILED;
1350                   }
1351               }
1352           
1353               self->sslContext = sslContext;
1354               return MI_RESULT_OK;
1355           }
1356           #endif
1357           
1358           static MI_Result _CreateAddListenerSocket(
1359               Http* self,
1360               unsigned short port,
1361               MI_Boolean  secure
1362               )
1363           {
1364               Addr addr;
1365               Sock listener;
1366 mike  1.1     MI_Result r;
1367           
1368               /* Create listener socket */
1369               {
1370                   Addr_InitAny(&addr, port);
1371                   r = Sock_CreateListener(&listener, &addr);
1372           
1373                   if (r != MI_RESULT_OK)
1374                   {
1375                       return r;
1376                   }
1377           
1378                   r = Sock_SetBlocking(listener, MI_FALSE);
1379           
1380                   if (r != MI_RESULT_OK)
1381                   {
1382                       Sock_Close(listener);
1383                       return r;
1384                   }
1385               }
1386           
1387 mike  1.1     /* Watch for read events on the listener socket (client connections) */
1388               {
1389                   Http_Listener_SocketData* h = (Http_Listener_SocketData*)calloc(1, sizeof(Http_Listener_SocketData));
1390           
1391                   if (!h)
1392                   {
1393                       Sock_Close(listener);
1394                       return MI_RESULT_FAILED;
1395                   }
1396           
1397                   h->base.sock = listener;
1398                   h->base.mask = SELECTOR_READ | SELECTOR_EXCEPTION;
1399                   h->base.callback = _ListenerCallback;
1400                   h->base.data = self;
1401                   h->secure = secure;
1402           
1403                   r = Selector_AddHandler(self->selector, &h->base);
1404           
1405                   if (r != MI_RESULT_OK)
1406                   {
1407                       Sock_Close(listener);
1408 mike  1.1             free(h);
1409                       return r;
1410                   }
1411               }
1412           
1413               return MI_RESULT_OK;
1414           }
1415           
1416           MI_Result Http_New_Server(
1417               Http** selfOut,
1418               Selector* selector, /*optional, maybe NULL*/
1419               unsigned short http_port,   /* 0 to disable */
1420               unsigned short https_port,  /* 0 to disable */
1421               HttpCallbackOnNewConnection callbackOnNewConnection,
1422               HttpCallbackOnCloseConnection callbackOnCloseConnection,
1423               HttpCallbackOnRequest callbackOnRequest,
1424               void* callbackData)
1425           {
1426               Http* self;
1427               MI_Result r;
1428           
1429 mike  1.1     /* allocate this, inits selector */
1430               r = _New_Http(selfOut, selector, callbackOnNewConnection, 
1431                   callbackOnCloseConnection, callbackOnRequest, callbackData);
1432           
1433               if (MI_RESULT_OK != r)
1434                   return r;
1435           
1436               self = *selfOut;
1437           
1438               /* Create http listener socket */
1439               if (http_port)
1440               {
1441                   r = _CreateAddListenerSocket(self, http_port, MI_FALSE);
1442           
1443                   if (r != MI_RESULT_OK)
1444                   {
1445                       Http_Delete(self);
1446                       return r;
1447                   }
1448               }
1449           
1450 mike  1.1 #ifdef CONFIG_POSIX
1451               /* Create https listener socket */
1452               if (https_port)
1453               {
1454                   /* init ssl */
1455                   SSL_library_init();
1456           
1457                   /* create context */
1458                   r = _CreateSSLContext(self);
1459           
1460                   if (r != MI_RESULT_OK)
1461                   {
1462                       Http_Delete(self);
1463                       return r;
1464                   }
1465           
1466                   /* create a socket */
1467                   r = _CreateAddListenerSocket(self, https_port, MI_TRUE);
1468           
1469                   if (r != MI_RESULT_OK)
1470                   {
1471 mike  1.1             Http_Delete(self);
1472                       return r;
1473                   }
1474               }
1475           #else
1476               MI_UNUSED(https_port);
1477           #endif
1478           
1479               return MI_RESULT_OK;
1480           }
1481           
1482           MI_Result Http_Delete(
1483               Http* self)
1484           {
1485               /* Check parameters */
1486               if (!self)
1487                   return MI_RESULT_INVALID_PARAMETER;
1488           
1489               /* Check magic number */
1490               if (self->magic != _MAGIC)
1491                   return MI_RESULT_INVALID_PARAMETER;
1492 mike  1.1 
1493               if (self->internalSelectorUsed)
1494               {
1495                   /* Release selector;
1496                   Note: selector-destory closes all sockects in a list including connector and listener */
1497                   Selector_Destroy(self->selector);
1498           
1499                   /* Shutdown the network */
1500                   Sock_Stop();
1501               }
1502           
1503               if (self->sslContext)
1504                   SSL_CTX_free(self->sslContext);
1505           
1506               /* Clear magic number */
1507               self->magic = 0xDDDDDDDD;
1508           
1509               /* Free self pointer */
1510               free(self);
1511           
1512               return MI_RESULT_OK;
1513 mike  1.1 }
1514           
1515           MI_Result Http_Run(
1516               Http* self,
1517               MI_Uint64 timeoutUsec)
1518           {
1519               /* Run the selector */
1520               return Selector_Run(self->selector, timeoutUsec);
1521           }
1522           
1523           /* sends 'ok' response with provided content;
1524            if message is accepted to be sent, on return *data == null (taking memory ownership)*/
1525           MI_Result Http_SendResponse(
1526               Http* self,
1527               void* httpConnectionHanlde,
1528               int httpErrorCode,
1529               Page** data)
1530           {
1531               Http_SR_SocketData* sendSock;
1532           
1533               /* check params */
1534 mike  1.1     if (!self)
1535                   return MI_RESULT_INVALID_PARAMETER;
1536           
1537               if (self->magic != _MAGIC)
1538               {
1539                   LOGW((T("_SendIN_IO_thread: invalid magic!") ));
1540                   return MI_RESULT_INVALID_PARAMETER;
1541               }
1542           
1543               sendSock = (Http_SR_SocketData*)httpConnectionHanlde;
1544           
1545               /* validate handler */
1546           
1547               if (MI_RESULT_OK != Selector_ContainsHandler(
1548                       self->selector, (Handler*)sendSock ) )
1549               {
1550                   LOGW((T("cannot send message: invalid handler (msg->clientID) %p\n"), sendSock));
1551                   return MI_RESULT_INVALID_PARAMETER;
1552               }
1553           
1554               sendSock->requestIsBeingProcessed = MI_FALSE;
1555 mike  1.1 
1556               sendSock->base.mask |= SELECTOR_WRITE;
1557               sendSock->base.mask &= ~SELECTOR_READ;
1558           
1559               if (data)
1560               {
1561                   sendSock->sendPage = *data;
1562                   *data = 0;
1563               }
1564               else
1565               {
1566                   sendSock->sendPage = 0;
1567               }
1568               sendSock->httpErrorCode = httpErrorCode;
1569           
1570               sendSock->sentSize = 0;
1571               sendSock->sendingState = RECV_STATE_HEADER;
1572           
1573               _RequestCallbackWrite(sendSock);
1574           
1575               return MI_RESULT_OK;
1576 mike  1.1 }
1577           
1578           /* Sets http options (mostly unit-test support) */
1579           MI_Result Http_SetOptions(
1580               Http* self,
1581               const HttpOptions* options)
1582           {
1583               /* check params */
1584               if (!self || !options)
1585                   return MI_RESULT_INVALID_PARAMETER;
1586           
1587               if (self->magic != _MAGIC)
1588               {
1589                   LOGW((T("Http_SetOptions: invalid magic!") ));
1590                   return MI_RESULT_INVALID_PARAMETER;
1591               }
1592           
1593               self->options = *options;
1594               return MI_RESULT_OK;
1595           }

ViewCVS 0.9.2