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

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

ViewCVS 0.9.2