4 * Copyright (c) 2012 project bchan
6 * This software is provided 'as-is', without any express or implied
7 * warranty. In no event will the authors be held liable for any damages
8 * arising from the use of this software.
10 * Permission is granted to anyone to use this software for any purpose,
11 * including commercial applications, and to alter it and redistribute it
12 * freely, subject to the following restrictions:
14 * 1. The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software
16 * in a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source
27 #include "http_connector.h"
33 #include <btron/btron.h>
34 #include <btron/bsocket.h>
36 #include <coll/idtocb.h>
37 #include "http_transport.h"
38 #include "http_requestlinestream.h"
39 #include "http_defaultheaderstream.h"
40 #include "http_statuslineparser.h"
41 #include "http_defaultheaderparser.h"
42 #include "http_transferdecoder.h"
43 #include "http_contentdecoder.h"
45 #ifdef BCHAN_CONFIG_DEBUG
46 # define DP(arg) printf arg
47 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
50 # define DP_ER(msg, err) /**/
54 # define DP_STATE(state) printf("%s\n", state)
56 # define DP_STATE(state) /**/
59 struct http_reqentry_t_ {
82 RECEIVE_MESSAGE_BODY_TRANSFERDECODE,
83 RECEIVE_MESSAGE_BODY_CONTENTDECODE,
94 http_statuslineparser_t sl;
95 http_defaultheaderparser_t dh;
96 http_transferdecoder_t tc;
97 http_contentdecoder_t cc;
99 http_transferdecoder_result *transfer_result;
100 W transfer_result_len;
101 W transfer_result_consumed;
102 http_contentdecoder_result *content_result;
103 W content_result_len;
104 W content_result_consumed;
108 typedef struct http_reqentry_t_ http_reqentry_t;
110 LOCAL VOID http_reqentry_attachendpoint(http_reqentry_t *entry, http_transport_t *transport, ID endpoint)
112 http_transport_holdendpoint(transport, endpoint);
113 entry->status = SENDING_REQUEST;
114 entry->transport = endpoint;
118 LOCAL VOID http_reqentry_detachendpoint(http_reqentry_t *entry, http_transport_t *transport, Bool transport_close)
120 http_transport_releaseendpoint(transport, entry->transport, transport_close);
121 entry->transport = -1;
125 LOCAL W http_reqentry_initialize(http_reqentry_t *entry, UB *host, W host_len, UH port, HTTP_METHOD method)
130 struct sockaddr_in *addr_in;
132 entry->host = malloc(sizeof(UB)*(host_len+1));
133 if (entry->host == NULL) {
134 err = ER_NOMEM; /* TODO: detail error code */
137 memcpy(entry->host, host, host_len);
138 entry->host[host_len] = '\0';
139 entry->host_len = host_len;
141 err = so_gethostbyname(entry->host, &ent, buf);
143 goto error_gethostbyname;
145 addr_in = (struct sockaddr_in *)&(entry->addr);
146 addr_in->sin_family = AF_INET;
147 addr_in->sin_port = htons( port );
148 addr_in->sin_addr.s_addr = *(unsigned int *)(ent.h_addr_list[0]);
150 entry->aborted_by_user = False;
151 entry->status = WAITING_TRANSPORT;
152 entry->snd_state = SEND_REQUEST_LINE;
153 entry->rcv_state = RECEIVE_STATUS_LINE;
154 entry->method = method;
155 entry->transport = -1;
157 http_statuslineparser_initialize(&entry->rcv_reader.sl);
158 http_defaultheaderparser_initialize(&entry->rcv_reader.dh);
165 entry->status = NON_EXISTENT;
169 LOCAL VOID http_reqentry_finalize(http_reqentry_t *entry)
171 switch (entry->rcv_state) {
172 case RECEIVE_MESSAGE_BODY:
173 case RECEIVE_MESSAGE_BODY_TRANSFERDECODE:
174 case RECEIVE_MESSAGE_BODY_CONTENTDECODE:
175 case RECEIVE_MESSAGE_END:
176 http_contentdecoder_finalize(&entry->rcv_reader.cc);
177 http_transferdecoder_finalize(&entry->rcv_reader.tc);
179 case RECEIVE_STATUS_LINE:
181 case RECEIVE_HEADER_END:
182 case RECEIVE_COMPLETED:
185 http_defaultheaderparser_finalize(&entry->rcv_reader.dh);
186 http_statuslineparser_finalize(&entry->rcv_reader.sl);
187 if (entry->host != NULL) {
192 struct http_reqdict_t_ {
195 http_reqentry_t entry[1];
197 typedef struct http_reqdict_t_ http_reqdict_t;
200 idtocb_iterator_t base;
201 } http_recdictiterator_t;
203 LOCAL Bool http_reqdictiterator_next(http_recdictiterator_t *iter, http_reqentry_t **entry)
205 return idtocb_iterator_next(&iter->base, (idtocb_entry_t**)entry);
208 LOCAL VOID http_reqdictiterator_initialize(http_recdictiterator_t *iter, http_reqdict_t *dict)
210 idtocb_iterator_initialize(&iter->base, dict->base);
213 LOCAL VOID http_reqdictiterator_finalize(http_recdictiterator_t *iter)
215 idtocb_iterator_finalize(&iter->base);
218 LOCAL ID http_reqdict_allocate(http_reqdict_t *dict, UB *host, W host_len, UH port, HTTP_METHOD method)
224 id = idtocb_allocate(dict->base);
228 err = idtocb_getcontrolblock(dict->base, id, (idtocb_entry_t**)&cb);
230 idtocb_free(dict->base, id);
234 err = http_reqentry_initialize(cb, host, host_len, port, method);
236 idtocb_free(dict->base, id);
243 LOCAL http_reqentry_t* http_reqdict_getentrybyID(http_reqdict_t *dict, ID id)
245 http_reqentry_t *entry;
248 err = idtocb_getcontrolblock(dict->base, id, (idtocb_entry_t**)&entry);
255 LOCAL VOID http_reqdict_free(http_reqdict_t *dict, ID id)
257 http_reqentry_t *entry;
260 err = idtocb_getcontrolblock(dict->base, id, (idtocb_entry_t**)&entry);
264 http_reqentry_finalize(entry);
265 idtocb_free(dict->base, id);
268 LOCAL http_reqdict_t* http_reqdict_new(W max_entries)
270 http_reqdict_t *dict;
272 dict = (http_reqdict_t*)malloc(sizeof(http_reqdict_t));
276 dict->base = idtocb_new(sizeof(http_reqentry_t), max_entries);
277 if (dict->base == NULL) {
284 LOCAL VOID http_reqdict_delete(http_reqdict_t *dict)
286 http_recdictiterator_t iter;
287 http_reqentry_t *entry;
290 http_reqdictiterator_initialize(&iter, dict);
292 cont = http_reqdictiterator_next(&iter, &entry);
296 http_reqentry_finalize(entry);
298 http_reqdictiterator_finalize(&iter);
300 idtocb_delete(dict->base);
304 struct http_connector_t_ {
305 http_reqdict_t *dict;
306 http_transport_t *transport;
310 #define HTTP_CONNECTOR_FLAG_CREARMASK(flag) (~(flag))
311 #define HTTP_CONNECTOR_FLAG_REQUEST 0x00000001
312 #define HTTP_CONNECTOR_FLAG_EVENT 0x00000002
313 #define HTTP_CONNECTOR_FLAG_CLEARMASK_REQUEST HTTP_CONNECTOR_FLAG_CREARMASK(HTTP_CONNECTOR_FLAG_REQUEST)
314 #define HTTP_CONNECTOR_FLAG_CLEARMASK_EVENT HTTP_CONNECTOR_FLAG_CREARMASK(HTTP_CONNECTOR_FLAG_EVENT)
316 EXPORT ID http_connector_createendpoint(http_connector_t *connector, UB *host, W host_len, UH port, HTTP_METHOD method)
321 id = http_reqdict_allocate(connector->dict, host, host_len, port, method);
323 DP_ER("http_reqdict_allocate", id);
324 return id; /* TODO */
327 err = set_flg(connector->flg, HTTP_CONNECTOR_FLAG_REQUEST);
329 DP_ER("set_flg", err);
330 http_reqdict_free(connector->dict, id);
337 EXPORT VOID http_connector_deleteendpoint(http_connector_t *connector, ID endpoint)
339 http_reqentry_t *entry;
341 entry = http_reqdict_getentrybyID(connector->dict, endpoint);
345 entry->aborted_by_user = True;
348 LOCAL VOID http_connector_collect(http_connector_t *connector)
350 http_reqentry_t *entry;
351 http_recdictiterator_t iter;
354 http_reqdictiterator_initialize(&iter, connector->dict);
356 cont = http_reqdictiterator_next(&iter, &entry);
360 if (entry->status == ABORTED_BY_TRANSPORT) {
361 http_reqdict_free(connector->dict, entry->base.id);
362 } else if (entry->status == COMPLETED) {
363 http_reqdict_free(connector->dict, entry->base.id);
366 http_reqdictiterator_finalize(&iter);
369 LOCAL W http_connector_searchwaiting(http_connector_t *connector)
372 http_reqentry_t *entry;
373 http_recdictiterator_t iter;
377 http_reqdictiterator_initialize(&iter, connector->dict);
379 cont = http_reqdictiterator_next(&iter, &entry);
383 if (entry->status == WAITING_TRANSPORT) {
384 endpoint = http_transport_searchendpoint(connector->transport, &entry->addr);
385 if ((endpoint & 0xFFFF0000) == ER_NOEXS) {
386 endpoint = http_transport_prepairendpoint(connector->transport, &entry->addr);
390 } else if (endpoint < 0) {
393 http_transport_isholdedendpoint(connector->transport, endpoint, &holded);
394 if (holded != False) {
397 http_reqentry_attachendpoint(entry, connector->transport, endpoint);
401 http_reqdictiterator_finalize(&iter);
406 LOCAL W http_connector_waitreceiving(http_connector_t *connector, TMOUT tmout)
409 http_reqentry_t *entry;
410 http_recdictiterator_t iter;
413 http_reqdictiterator_initialize(&iter, connector->dict);
415 cont = http_reqdictiterator_next(&iter, &entry);
419 if (entry->status == WAITING_RESPONSE) {
420 http_transport_setwaitingreceive(connector->transport, entry->transport);
423 http_reqdictiterator_finalize(&iter);
425 http_transport_waitreceive(connector->transport, tmout);
427 http_reqdictiterator_initialize(&iter, connector->dict);
429 cont = http_reqdictiterator_next(&iter, &entry);
433 if (entry->status == WAITING_RESPONSE) {
434 http_transport_isreadready(connector->transport, entry->transport, &is_ready);
435 if (is_ready != False) {
436 entry->status = RECEIVING_RESPONSE;
441 http_reqdictiterator_finalize(&iter);
446 EXPORT W http_connector_waitconnection(http_connector_t *connector, TMOUT tmout)
452 http_connector_collect(connector);
454 err = http_connector_searchwaiting(connector);
461 http_transport_releaseunusedendpoint(connector->transport);
463 err = http_connector_waitreceiving(connector, tmout);
472 err = set_flg(connector->flg, HTTP_CONNECTOR_FLAG_EVENT);
474 DP_ER("set_flg", err);
481 LOCAL W http_connector_rcv_status_line(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
483 http_statuslineparser_result result;
488 err = http_transport_read(connector->transport, entry->transport, &bin, &len);
490 DP_ER("http_transport_read", err);
494 for (i = 0; i < len; i++) {
495 end = http_statuslineparser_inputchar(&entry->rcv_reader.sl, bin[i], &result);
502 http_transport_consumereadbuffer(connector->transport, entry->transport, i);
505 if (result.error != HTTP_STATUSLINEPARSER_ERROR_NONE) {
506 return -1; /* TODO */
508 entry->rcv_state = RECEIVE_HEADER;
509 event->endpoint = entry->base.id;
510 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_STATUSLINE;
511 event->data.receive_statusline.version = result.version;
512 event->data.receive_statusline.statuscode = result.statuscode;
519 LOCAL W http_connector_rcv_header(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
521 HTTP_DEFAULTHEADERPARSER_RESULT result;
526 err = http_transport_read(connector->transport, entry->transport, &bin, &len);
528 DP_ER("http_transport_read", err);
532 for (i = 0; i < len; i++) {
533 http_defaultheaderparser_inputchar(&entry->rcv_reader.dh, bin[i], &result);
534 if (result == HTTP_DEFAULTHEADERPARSER_RESULT_MESSAGE_HEADER_END) {
541 http_transport_consumereadbuffer(connector->transport, entry->transport, i);
544 entry->rcv_state = RECEIVE_HEADER_END;
547 event->endpoint = entry->base.id;
548 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_HEADER;
549 event->data.receive_header.bin = bin;
550 event->data.receive_header.len = i;
555 LOCAL W http_connector_rcv_header_end(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
559 HTTP_TRANSFERCODING_TYPE transfer_coding;
560 HTTP_CONTENTCODING_VALUE content_coding;
562 entry->rcv_state = RECEIVE_MESSAGE_BODY;
563 event->endpoint = entry->base.id;
564 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_HEADER_END;
566 content_length = http_defaultheaderparsr_contentlength(&entry->rcv_reader.dh);
567 transfer_coding = http_defaultheaderparsr_transferencoding(&entry->rcv_reader.dh);
568 content_coding = http_defaultheaderparsr_contentencoding(&entry->rcv_reader.dh);
570 http_transferdecoder_initialize(&entry->rcv_reader.tc, transfer_coding, content_length);
571 err = http_contentdecoder_initialize(&entry->rcv_reader.cc, content_coding);
575 entry->rcv_reader.body.transfer_result = NULL;
576 entry->rcv_reader.body.transfer_result_len = 0;
577 entry->rcv_reader.body.transfer_result_consumed = 0;
578 entry->rcv_reader.body.content_result = NULL;
579 entry->rcv_reader.body.content_result_len = 0;
580 entry->rcv_reader.body.content_result_consumed = 0;
585 LOCAL W http_connector_rcv_message_body_contentdecode(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
588 http_contentdecoder_result *result;
590 if (entry->rcv_reader.body.content_result_consumed == entry->rcv_reader.body.content_result_len) {
591 err = http_contentdecoder_outputdata(&entry->rcv_reader.cc, &entry->rcv_reader.body.content_result, &entry->rcv_reader.body.content_result_len);
593 DP_ER("http_contentdecoder_outputdata", err);
596 entry->rcv_reader.body.content_result_consumed = 0;
598 result = entry->rcv_reader.body.content_result + entry->rcv_reader.body.content_result_consumed;
599 entry->rcv_reader.body.content_result_consumed++;
600 switch (result->type) {
601 case HTTP_CONTENTDECODER_RESULTTYPE_DATA:
602 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_MESSAGEBODY;
603 event->endpoint = entry->base.id;
604 event->data.receive_messagebody.bin = result->data;
605 event->data.receive_messagebody.len = result->len;
607 case HTTP_CONTENTDECODER_RESULTTYPE_NEED_INPUT:
608 entry->rcv_state = RECEIVE_MESSAGE_BODY_TRANSFERDECODE;
610 case HTTP_CONTENTDECODER_RESULTTYPE_END:
611 entry->rcv_state = RECEIVE_MESSAGE_END;
618 LOCAL W http_connector_rcv_message_body_transferdecode(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
620 http_transferdecoder_result *result;
623 if (entry->rcv_reader.body.transfer_result_consumed == entry->rcv_reader.body.transfer_result_len) {
624 entry->rcv_state = RECEIVE_MESSAGE_BODY;
628 result = entry->rcv_reader.body.transfer_result + entry->rcv_reader.body.transfer_result_consumed;
629 switch (result->type) {
630 case HTTP_TRANSFERDECODER_RESULTTYPE_DATA:
631 err = http_contentdecoder_inputentitybody(&entry->rcv_reader.cc, result->data, result->len);
633 case HTTP_TRANSFERDECODER_RESULTTYPE_END:
634 err = http_contentdecoder_inputendofdata(&entry->rcv_reader.cc);
639 entry->rcv_reader.body.transfer_result_consumed++;
641 DP_ER("http_contentdecoder_inputXXX", err);
644 entry->rcv_state = RECEIVE_MESSAGE_BODY_CONTENTDECODE;
646 return http_connector_rcv_message_body_contentdecode(connector, entry, event);
649 LOCAL W http_connector_rcv_message_body(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
654 err = http_transport_read(connector->transport, entry->transport, &bin, &len);
656 DP_ER("http_transport_read", err);
660 len = http_transferdecoder_inputentitybody(&entry->rcv_reader.tc, bin, len, &entry->rcv_reader.body.transfer_result, &entry->rcv_reader.body.transfer_result_len);
661 entry->rcv_reader.body.transfer_result_consumed = 0;
662 http_transport_consumereadbuffer(connector->transport, entry->transport, len);
664 entry->rcv_state = RECEIVE_MESSAGE_BODY_TRANSFERDECODE;
666 return http_connector_rcv_message_body_transferdecode(connector, entry, event);
669 LOCAL W http_connector_rcv_message_end(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
671 Bool connection_closed;
673 http_contentdecoder_finalize(&entry->rcv_reader.cc);
674 http_transferdecoder_finalize(&entry->rcv_reader.tc);
675 connection_closed = http_defaultheaderparser_connectionclosed(&entry->rcv_reader.dh);
677 entry->status = COMPLETED;
678 entry->rcv_state = RECEIVE_COMPLETED;
679 event->endpoint = entry->base.id;
680 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_MESSAGEBODY_END;
682 /* TODO: Connection: close */
683 http_reqentry_detachendpoint(entry, connector->transport, connection_closed);
688 LOCAL W http_connector_handleevent_receiving_response(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
692 switch (entry->rcv_state) {
693 case RECEIVE_STATUS_LINE:
694 DP_STATE("RECEIVE_STATUS_LINE");
695 err = http_connector_rcv_status_line(connector, entry, event);
698 DP_STATE("RECEIVE_RECEIVE_HEADER");
699 err = http_connector_rcv_header(connector, entry, event);
701 case RECEIVE_HEADER_END:
702 DP_STATE("RECEIVE_HEADER_END");
703 err = http_connector_rcv_header_end(connector, entry, event);
705 case RECEIVE_MESSAGE_BODY:
706 DP_STATE("RECEIVE_MESSAGE_BODY");
707 err = http_connector_rcv_message_body(connector, entry, event);
709 case RECEIVE_MESSAGE_BODY_TRANSFERDECODE:
710 DP_STATE("RECEIVE_MESSAGE_BODY_TRANSFERDECODE");
711 err = http_connector_rcv_message_body_transferdecode(connector, entry, event);
713 case RECEIVE_MESSAGE_BODY_CONTENTDECODE:
714 DP_STATE("RECEIVE_MESSAGE_BODY_CONTENTDECDE");
715 err = http_connector_rcv_message_body_contentdecode(connector, entry, event);
717 case RECEIVE_MESSAGE_END:
718 DP_STATE("RECEIVE_MESSAGE_END");
719 err = http_connector_rcv_message_end(connector, entry, event);
721 case RECEIVE_COMPLETED:
722 DP_STATE("RECEIVE_COMPLETED");
730 /* TODO: devide event found and need loop for state transition */
731 EXPORT Bool http_connector_searcheventtarget(http_connector_t *connector, http_connector_event *event)
733 http_reqentry_t *entry;
734 http_recdictiterator_t iter;
735 Bool cont, found = False;
738 event->type = HTTP_CONNECTOR_EVENTTYPE_NONE;
740 http_reqdictiterator_initialize(&iter, connector->dict);
742 cont = http_reqdictiterator_next(&iter, &entry);
746 if (entry->status == SENDING_REQUEST) {
747 event->type = HTTP_CONNECTOR_EVENTTYPE_SEND;
748 event->endpoint = entry->base.id;
752 if (entry->status == RECEIVING_RESPONSE) {
753 err = http_connector_handleevent_receiving_response(connector, entry, event);
764 http_reqdictiterator_finalize(&iter);
769 EXPORT W http_connector_getevent(http_connector_t *connector, http_connector_event *event)
774 err = wai_flg(connector->flg, HTTP_CONNECTOR_FLAG_EVENT, WF_AND|NOCLR, T_NOWAIT);
775 if ((err & 0xFFFF0000) == ER_NONE) {
779 DP_ER("wai_flg", err);
782 found = http_connector_searcheventtarget(connector, event);
783 if (found == False) {
784 err = clr_flg(connector->flg, HTTP_CONNECTOR_FLAG_CLEARMASK_EVENT);
786 DP_ER("clr_flg", err);
789 return ER_NONE; /* TODO: detail error code */
791 if (event->type == HTTP_CONNECTOR_EVENTTYPE_NONE) {
792 return ER_NONE; /* TODO: detail error code */
797 #define HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, state, entry) \
798 (entry) = http_reqdict_getentrybyID((connector)->dict, (endpoint)); \
799 if ((entry) == NULL) { \
800 return ER_NOEXS; /* TODO: detail error code */ \
802 if ((entry)->status != SENDING_REQUEST) { \
803 return ER_PAR; /* TODO: suitable error code */ \
805 if ((entry)->snd_state != (state)) { \
806 return ER_PAR; /* TODO: suitable error code */ \
809 #define HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, state1, state2, entry) \
810 (entry) = http_reqdict_getentrybyID((connector)->dict, (endpoint)); \
811 if ((entry) == NULL) { \
812 return ER_NOEXS; /* TODO: detail error code */ \
814 if ((entry)->status != SENDING_REQUEST) { \
815 return ER_PAR; /* TODO: suitable error code */ \
817 if (((entry)->snd_state != (state1))&&((entry)->snd_state != (state2))) { \
818 return ER_PAR; /* TODO: suitable error code */ \
821 EXPORT W http_connector_sendrequestline(http_connector_t *connector, ID endpoint, UB *path, W path_len)
823 http_reqentry_t *entry;
824 http_requestlinestream_t reqline;
829 HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_REQUEST_LINE, entry);
831 err = http_requestlinestream_initialize(&reqline, entry->method, path, path_len);
836 cont = http_requestlinestream_make(&reqline, &str, &len);
840 err = http_transport_write(connector->transport, entry->transport, str, len);
845 http_requestlinestream_finalize(&reqline);
851 entry->snd_state = SEND_HEADER_MINE;
856 LOCAL W http_connector_writedefaultheader(http_connector_t *connector, ID transport, UB *host, W host_len)
858 http_defaultheaderstream_t defaultheader;
863 http_defaultheaderstream_initialize(&defaultheader, host, host_len);
865 cont = http_defaultheaderstream_make(&defaultheader, &str, &len);
869 err = http_transport_write(connector->transport, transport, str, len);
874 http_defaultheaderstream_finalize(&defaultheader);
879 EXPORT W http_connector_sendheader(http_connector_t *connector, ID endpoint, UB *p, W len)
881 http_reqentry_t *entry;
884 HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, SEND_HEADER_MINE, SEND_HEADER_USER, entry);
886 if (entry->snd_state == SEND_HEADER_MINE) {
887 err = http_connector_writedefaultheader(connector, entry->transport, entry->host, entry->host_len);
891 entry->snd_state = SEND_HEADER_USER;
897 EXPORT W http_connector_sendheaderend(http_connector_t *connector, ID endpoint)
899 http_reqentry_t *entry;
902 HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, SEND_HEADER_MINE, SEND_HEADER_USER, entry);
904 if (entry->snd_state == SEND_HEADER_MINE) {
905 err = http_connector_writedefaultheader(connector, entry->transport, entry->host, entry->host_len);
910 err = http_transport_write(connector->transport, entry->transport, "\r\n", 2);
915 entry->snd_state = SEND_MESSAGE_BODY;
920 EXPORT W http_connector_sendmessagebody(http_connector_t *connector, ID endpoint, UB *p, W len)
922 http_reqentry_t *entry;
925 HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_MESSAGE_BODY, entry);
927 err = http_transport_write(connector->transport, entry->transport, p, len);
935 EXPORT W http_connector_sendmessagebodyend(http_connector_t *connector, ID endpoint)
937 http_reqentry_t *entry;
939 HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_MESSAGE_BODY, entry);
941 entry->status = WAITING_RESPONSE;
946 EXPORT http_connector_t* http_connector_new()
948 http_connector_t *connector;
950 connector = (http_connector_t*)malloc(sizeof(http_connector_t));
951 if (connector == NULL) {
955 connector->dict = http_reqdict_new(10/*tmp*/);
956 if (connector->dict == NULL) {
957 DP_ER("http_recdict_new", 0);
958 goto error_http_reqdict;
960 connector->flg = cre_flg(0, DELEXIT);
961 if (connector->flg < 0) {
962 DP_ER("cre_flg", connector->flg);
965 connector->transport = http_transport_new(10/*tmp*/);
966 if (connector->transport == NULL) {
967 DP_ER("http_transport_new", -1);
968 goto error_transport;
973 http_transport_delete(connector->transport);
975 del_flg(connector->flg);
977 http_reqdict_delete(connector->dict);
983 EXPORT VOID http_connector_delete(http_connector_t *connector)
985 http_transport_delete(connector->transport);
986 del_flg(connector->flg);
987 http_reqdict_delete(connector->dict);