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

ViewCVS 0.9.2