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, ¤tLine))
636 return PRT_RETURN_FALSE;
637
638
639 while ((data-currentLine) > 3)
640 {
641 if (!_getHeaderField(handler, ¤tLine))
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 }
|