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