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;
311 #define HTTP_CONNECTOR_FLAG_CREARMASK(flag) (~(flag))
312 #define HTTP_CONNECTOR_FLAG_REQUEST 0x00000001
313 #define HTTP_CONNECTOR_FLAG_EVENT 0x00000002
314 #define HTTP_CONNECTOR_FLAG_CLEARMASK_REQUEST HTTP_CONNECTOR_FLAG_CREARMASK(HTTP_CONNECTOR_FLAG_REQUEST)
315 #define HTTP_CONNECTOR_FLAG_CLEARMASK_EVENT HTTP_CONNECTOR_FLAG_CREARMASK(HTTP_CONNECTOR_FLAG_EVENT)
317 EXPORT ID http_connector_createendpoint(http_connector_t *connector, UB *host, W host_len, UH port, HTTP_METHOD method)
322 err = wai_sem(connector->sem, T_FOREVER);
326 id = http_reqdict_allocate(connector->dict, host, host_len, port, method);
327 sig_sem(connector->sem);
329 DP_ER("http_reqdict_allocate", id);
330 return id; /* TODO */
333 err = set_flg(connector->flg, HTTP_CONNECTOR_FLAG_REQUEST);
335 DP_ER("set_flg", err);
336 http_reqdict_free(connector->dict, id);
343 EXPORT VOID http_connector_deleteendpoint(http_connector_t *connector, ID endpoint)
345 http_reqentry_t *entry;
346 Bool transport_close = True;
349 err = wai_sem(connector->sem, T_FOREVER);
354 entry = http_reqdict_getentrybyID(connector->dict, endpoint);
356 sig_sem(connector->sem);
360 switch (entry->status) {
361 case SENDING_REQUEST:
362 if (entry->snd_state == SEND_REQUEST_LINE) {
363 transport_close = False;
367 case WAITING_RESPONSE:
368 case RECEIVING_RESPONSE:
369 http_reqentry_detachendpoint(entry, connector->transport, transport_close);
372 case WAITING_TRANSPORT:
373 case ABORTED_BY_TRANSPORT:
377 http_reqdict_free(connector->dict, endpoint);
379 sig_sem(connector->sem);
382 LOCAL W http_connector_searchwaiting(http_connector_t *connector)
385 http_reqentry_t *entry;
386 http_recdictiterator_t iter;
390 http_reqdictiterator_initialize(&iter, connector->dict);
392 cont = http_reqdictiterator_next(&iter, &entry);
396 if (entry->status == WAITING_TRANSPORT) {
397 endpoint = http_transport_searchendpoint(connector->transport, &entry->addr);
398 if ((endpoint & 0xFFFF0000) == ER_NOEXS) {
399 endpoint = http_transport_prepairendpoint(connector->transport, &entry->addr);
403 } else if (endpoint < 0) {
406 http_transport_isholdedendpoint(connector->transport, endpoint, &holded);
407 if (holded != False) {
410 http_reqentry_attachendpoint(entry, connector->transport, endpoint);
414 http_reqdictiterator_finalize(&iter);
419 LOCAL W http_connector_waitreceiving(http_connector_t *connector, TMOUT tmout)
422 http_reqentry_t *entry;
423 http_recdictiterator_t iter;
426 http_reqdictiterator_initialize(&iter, connector->dict);
428 cont = http_reqdictiterator_next(&iter, &entry);
432 if (entry->status == WAITING_RESPONSE) {
433 http_transport_setwaitingreceive(connector->transport, entry->transport);
436 http_reqdictiterator_finalize(&iter);
438 http_transport_waitreceive(connector->transport, tmout);
440 http_reqdictiterator_initialize(&iter, connector->dict);
442 cont = http_reqdictiterator_next(&iter, &entry);
446 if (entry->status == WAITING_RESPONSE) {
447 http_transport_isreadready(connector->transport, entry->transport, &is_ready);
448 if (is_ready != False) {
449 entry->status = RECEIVING_RESPONSE;
454 http_reqdictiterator_finalize(&iter);
459 EXPORT W http_connector_waitconnection(http_connector_t *connector, TMOUT tmout)
464 err = wai_sem(connector->sem, tmout);
468 err = http_connector_searchwaiting(connector);
470 sig_sem(connector->sem);
476 http_transport_releaseunusedendpoint(connector->transport);
478 err = http_connector_waitreceiving(connector, tmout);
479 sig_sem(connector->sem);
488 err = set_flg(connector->flg, HTTP_CONNECTOR_FLAG_EVENT);
490 DP_ER("set_flg", err);
497 LOCAL W http_connector_rcv_status_line(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
499 http_statuslineparser_result result;
504 err = http_transport_read(connector->transport, entry->transport, &bin, &len);
506 DP_ER("http_transport_read", err);
510 for (i = 0; i < len; i++) {
511 end = http_statuslineparser_inputchar(&entry->rcv_reader.sl, bin[i], &result);
518 http_transport_consumereadbuffer(connector->transport, entry->transport, i);
521 if (result.error != HTTP_STATUSLINEPARSER_ERROR_NONE) {
522 return -1; /* TODO */
524 entry->rcv_state = RECEIVE_HEADER;
525 event->endpoint = entry->base.id;
526 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_STATUSLINE;
527 event->data.receive_statusline.version = result.version;
528 event->data.receive_statusline.statuscode = result.statuscode;
535 LOCAL W http_connector_rcv_header(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
537 HTTP_DEFAULTHEADERPARSER_RESULT result;
542 err = http_transport_read(connector->transport, entry->transport, &bin, &len);
544 DP_ER("http_transport_read", err);
548 for (i = 0; i < len; i++) {
549 http_defaultheaderparser_inputchar(&entry->rcv_reader.dh, bin[i], &result);
550 if (result == HTTP_DEFAULTHEADERPARSER_RESULT_MESSAGE_HEADER_END) {
557 http_transport_consumereadbuffer(connector->transport, entry->transport, i);
560 entry->rcv_state = RECEIVE_HEADER_END;
563 event->endpoint = entry->base.id;
564 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_HEADER;
565 event->data.receive_header.bin = bin;
566 event->data.receive_header.len = i;
571 LOCAL W http_connector_rcv_header_end(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
575 HTTP_TRANSFERCODING_TYPE transfer_coding;
576 HTTP_CONTENTCODING_VALUE content_coding;
578 entry->rcv_state = RECEIVE_MESSAGE_BODY;
579 event->endpoint = entry->base.id;
580 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_HEADER_END;
582 content_length = http_defaultheaderparsr_contentlength(&entry->rcv_reader.dh);
583 transfer_coding = http_defaultheaderparsr_transferencoding(&entry->rcv_reader.dh);
584 content_coding = http_defaultheaderparsr_contentencoding(&entry->rcv_reader.dh);
586 http_transferdecoder_initialize(&entry->rcv_reader.tc, transfer_coding, content_length);
587 err = http_contentdecoder_initialize(&entry->rcv_reader.cc, content_coding);
591 entry->rcv_reader.body.transfer_result = NULL;
592 entry->rcv_reader.body.transfer_result_len = 0;
593 entry->rcv_reader.body.transfer_result_consumed = 0;
594 entry->rcv_reader.body.content_result = NULL;
595 entry->rcv_reader.body.content_result_len = 0;
596 entry->rcv_reader.body.content_result_consumed = 0;
601 LOCAL W http_connector_rcv_message_body_contentdecode(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
604 http_contentdecoder_result *result;
606 if (entry->rcv_reader.body.content_result_consumed == entry->rcv_reader.body.content_result_len) {
607 err = http_contentdecoder_outputdata(&entry->rcv_reader.cc, &entry->rcv_reader.body.content_result, &entry->rcv_reader.body.content_result_len);
609 DP_ER("http_contentdecoder_outputdata", err);
612 entry->rcv_reader.body.content_result_consumed = 0;
614 result = entry->rcv_reader.body.content_result + entry->rcv_reader.body.content_result_consumed;
615 entry->rcv_reader.body.content_result_consumed++;
616 switch (result->type) {
617 case HTTP_CONTENTDECODER_RESULTTYPE_DATA:
618 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_MESSAGEBODY;
619 event->endpoint = entry->base.id;
620 event->data.receive_messagebody.bin = result->data;
621 event->data.receive_messagebody.len = result->len;
623 case HTTP_CONTENTDECODER_RESULTTYPE_NEED_INPUT:
624 entry->rcv_state = RECEIVE_MESSAGE_BODY_TRANSFERDECODE;
626 case HTTP_CONTENTDECODER_RESULTTYPE_END:
627 entry->rcv_state = RECEIVE_MESSAGE_END;
634 LOCAL W http_connector_rcv_message_body_transferdecode(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
636 http_transferdecoder_result *result;
639 if (entry->rcv_reader.body.transfer_result_consumed == entry->rcv_reader.body.transfer_result_len) {
640 entry->rcv_state = RECEIVE_MESSAGE_BODY;
644 result = entry->rcv_reader.body.transfer_result + entry->rcv_reader.body.transfer_result_consumed;
645 switch (result->type) {
646 case HTTP_TRANSFERDECODER_RESULTTYPE_DATA:
647 err = http_contentdecoder_inputentitybody(&entry->rcv_reader.cc, result->data, result->len);
649 case HTTP_TRANSFERDECODER_RESULTTYPE_END:
650 err = http_contentdecoder_inputendofdata(&entry->rcv_reader.cc);
655 entry->rcv_reader.body.transfer_result_consumed++;
657 DP_ER("http_contentdecoder_inputXXX", err);
660 entry->rcv_state = RECEIVE_MESSAGE_BODY_CONTENTDECODE;
662 return http_connector_rcv_message_body_contentdecode(connector, entry, event);
665 LOCAL W http_connector_rcv_message_body(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
670 err = http_transport_read(connector->transport, entry->transport, &bin, &len);
672 DP_ER("http_transport_read", err);
676 len = http_transferdecoder_inputentitybody(&entry->rcv_reader.tc, bin, len, &entry->rcv_reader.body.transfer_result, &entry->rcv_reader.body.transfer_result_len);
677 entry->rcv_reader.body.transfer_result_consumed = 0;
678 http_transport_consumereadbuffer(connector->transport, entry->transport, len);
680 entry->rcv_state = RECEIVE_MESSAGE_BODY_TRANSFERDECODE;
682 return http_connector_rcv_message_body_transferdecode(connector, entry, event);
685 LOCAL W http_connector_rcv_message_end(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
687 Bool connection_closed;
689 http_contentdecoder_finalize(&entry->rcv_reader.cc);
690 http_transferdecoder_finalize(&entry->rcv_reader.tc);
691 connection_closed = http_defaultheaderparser_connectionclosed(&entry->rcv_reader.dh);
693 entry->status = COMPLETED;
694 entry->rcv_state = RECEIVE_COMPLETED;
695 event->endpoint = entry->base.id;
696 event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_MESSAGEBODY_END;
698 http_reqentry_detachendpoint(entry, connector->transport, connection_closed);
703 LOCAL W http_connector_handleevent_receiving_response(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
707 switch (entry->rcv_state) {
708 case RECEIVE_STATUS_LINE:
709 DP_STATE("RECEIVE_STATUS_LINE");
710 err = http_connector_rcv_status_line(connector, entry, event);
713 DP_STATE("RECEIVE_RECEIVE_HEADER");
714 err = http_connector_rcv_header(connector, entry, event);
716 case RECEIVE_HEADER_END:
717 DP_STATE("RECEIVE_HEADER_END");
718 err = http_connector_rcv_header_end(connector, entry, event);
720 case RECEIVE_MESSAGE_BODY:
721 DP_STATE("RECEIVE_MESSAGE_BODY");
722 err = http_connector_rcv_message_body(connector, entry, event);
724 case RECEIVE_MESSAGE_BODY_TRANSFERDECODE:
725 DP_STATE("RECEIVE_MESSAGE_BODY_TRANSFERDECODE");
726 err = http_connector_rcv_message_body_transferdecode(connector, entry, event);
728 case RECEIVE_MESSAGE_BODY_CONTENTDECODE:
729 DP_STATE("RECEIVE_MESSAGE_BODY_CONTENTDECDE");
730 err = http_connector_rcv_message_body_contentdecode(connector, entry, event);
732 case RECEIVE_MESSAGE_END:
733 DP_STATE("RECEIVE_MESSAGE_END");
734 err = http_connector_rcv_message_end(connector, entry, event);
736 case RECEIVE_COMPLETED:
737 DP_STATE("RECEIVE_COMPLETED");
745 /* TODO: devide event found and need loop for state transition */
746 EXPORT Bool http_connector_searcheventtarget(http_connector_t *connector, http_connector_event *event)
748 http_reqentry_t *entry;
749 http_recdictiterator_t iter;
750 Bool cont, found = False;
753 event->type = HTTP_CONNECTOR_EVENTTYPE_NONE;
755 http_reqdictiterator_initialize(&iter, connector->dict);
757 cont = http_reqdictiterator_next(&iter, &entry);
761 if (entry->status == SENDING_REQUEST) {
762 event->type = HTTP_CONNECTOR_EVENTTYPE_SEND;
763 event->endpoint = entry->base.id;
767 if (entry->status == RECEIVING_RESPONSE) {
768 err = http_connector_handleevent_receiving_response(connector, entry, event);
769 if ((err < 0)&&((err & 0xFFFF0000) != EX_WOULDBLOCK)) {
770 event->type = HTTP_CONNECTOR_EVENTTYPE_ERROR;
771 event->endpoint = entry->base.id;
772 entry->status = ABORTED_BY_TRANSPORT;
773 http_reqentry_detachendpoint(entry, connector->transport, True);
782 http_reqdictiterator_finalize(&iter);
787 EXPORT W http_connector_getevent(http_connector_t *connector, http_connector_event *event)
792 err = wai_flg(connector->flg, HTTP_CONNECTOR_FLAG_EVENT, WF_AND|NOCLR, T_NOWAIT);
793 if ((err & 0xFFFF0000) == ER_NONE) {
797 DP_ER("wai_flg", err);
800 err = wai_sem(connector->sem, T_FOREVER);
804 found = http_connector_searcheventtarget(connector, event);
805 sig_sem(connector->sem);
806 if (found == False) {
807 err = clr_flg(connector->flg, HTTP_CONNECTOR_FLAG_CLEARMASK_EVENT);
809 DP_ER("clr_flg", err);
812 return ER_NONE; /* TODO: detail error code */
814 if (event->type == HTTP_CONNECTOR_EVENTTYPE_NONE) {
815 return ER_NONE; /* TODO: detail error code */
820 #define HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, state, entry) \
821 (entry) = http_reqdict_getentrybyID((connector)->dict, (endpoint)); \
822 if ((entry) == NULL) { \
823 return ER_NOEXS; /* TODO: detail error code */ \
825 if ((entry)->status != SENDING_REQUEST) { \
826 return ER_PAR; /* TODO: suitable error code */ \
828 if ((entry)->snd_state != (state)) { \
829 return ER_PAR; /* TODO: suitable error code */ \
832 #define HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, state1, state2, entry) \
833 (entry) = http_reqdict_getentrybyID((connector)->dict, (endpoint)); \
834 if ((entry) == NULL) { \
835 return ER_NOEXS; /* TODO: detail error code */ \
837 if ((entry)->status != SENDING_REQUEST) { \
838 return ER_PAR; /* TODO: suitable error code */ \
840 if (((entry)->snd_state != (state1))&&((entry)->snd_state != (state2))) { \
841 return ER_PAR; /* TODO: suitable error code */ \
844 EXPORT W http_connector_sendrequestline(http_connector_t *connector, ID endpoint, UB *path, W path_len)
846 http_reqentry_t *entry;
847 http_requestlinestream_t reqline;
852 err = wai_sem(connector->sem, T_FOREVER);
857 HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_REQUEST_LINE, entry);
859 err = http_requestlinestream_initialize(&reqline, entry->method, path, path_len);
861 sig_sem(connector->sem);
865 cont = http_requestlinestream_make(&reqline, &str, &len);
869 err = http_transport_write(connector->transport, entry->transport, str, len);
874 http_requestlinestream_finalize(&reqline);
877 sig_sem(connector->sem);
881 entry->snd_state = SEND_HEADER_MINE;
883 sig_sem(connector->sem);
888 LOCAL W http_connector_writedefaultheader(http_connector_t *connector, ID transport, UB *host, W host_len)
890 http_defaultheaderstream_t defaultheader;
895 http_defaultheaderstream_initialize(&defaultheader, host, host_len);
897 cont = http_defaultheaderstream_make(&defaultheader, &str, &len);
901 err = http_transport_write(connector->transport, transport, str, len);
906 http_defaultheaderstream_finalize(&defaultheader);
911 EXPORT W http_connector_sendheader(http_connector_t *connector, ID endpoint, UB *p, W len)
913 http_reqentry_t *entry;
916 err = wai_sem(connector->sem, T_FOREVER);
921 HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, SEND_HEADER_MINE, SEND_HEADER_USER, entry);
923 if (entry->snd_state == SEND_HEADER_MINE) {
924 err = http_connector_writedefaultheader(connector, entry->transport, entry->host, entry->host_len);
926 sig_sem(connector->sem);
929 entry->snd_state = SEND_HEADER_USER;
932 sig_sem(connector->sem);
937 EXPORT W http_connector_sendheaderend(http_connector_t *connector, ID endpoint)
939 http_reqentry_t *entry;
942 err = wai_sem(connector->sem, T_FOREVER);
947 HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, SEND_HEADER_MINE, SEND_HEADER_USER, entry);
949 if (entry->snd_state == SEND_HEADER_MINE) {
950 err = http_connector_writedefaultheader(connector, entry->transport, entry->host, entry->host_len);
952 sig_sem(connector->sem);
956 err = http_transport_write(connector->transport, entry->transport, "\r\n", 2);
958 sig_sem(connector->sem);
962 entry->snd_state = SEND_MESSAGE_BODY;
964 sig_sem(connector->sem);
969 EXPORT W http_connector_sendmessagebody(http_connector_t *connector, ID endpoint, UB *p, W len)
971 http_reqentry_t *entry;
974 err = wai_sem(connector->sem, T_FOREVER);
979 HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_MESSAGE_BODY, entry);
981 err = http_transport_write(connector->transport, entry->transport, p, len);
982 sig_sem(connector->sem);
990 EXPORT W http_connector_sendmessagebodyend(http_connector_t *connector, ID endpoint)
992 http_reqentry_t *entry;
995 err = wai_sem(connector->sem, T_FOREVER);
1000 HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_MESSAGE_BODY, entry);
1002 entry->status = WAITING_RESPONSE;
1004 sig_sem(connector->sem);
1009 EXPORT http_connector_t* http_connector_new()
1011 http_connector_t *connector;
1013 connector = (http_connector_t*)malloc(sizeof(http_connector_t));
1014 if (connector == NULL) {
1018 connector->dict = http_reqdict_new(10/*tmp*/);
1019 if (connector->dict == NULL) {
1020 DP_ER("http_recdict_new", 0);
1021 goto error_http_reqdict;
1023 connector->flg = cre_flg(0, DELEXIT);
1024 if (connector->flg < 0) {
1025 DP_ER("cre_flg", connector->flg);
1028 connector->sem = cre_sem(1, SEM_EXCL|DELEXIT);
1029 if (connector->sem < 0) {
1030 DP_ER("cre_sem", connector->sem);
1033 connector->transport = http_transport_new(10/*tmp*/);
1034 if (connector->transport == NULL) {
1035 DP_ER("http_transport_new", -1);
1036 goto error_transport;
1041 http_transport_delete(connector->transport);
1043 del_sem(connector->sem);
1045 del_flg(connector->flg);
1047 http_reqdict_delete(connector->dict);
1053 EXPORT VOID http_connector_delete(http_connector_t *connector)
1055 http_transport_delete(connector->transport);
1056 del_sem(connector->sem);
1057 del_flg(connector->flg);
1058 http_reqdict_delete(connector->dict);