OSDN Git Service

fix state transition mistake.
[bbk/bchanf.git] / src / http / http_connector.c
1 /*
2  * http_connector.c
3  *
4  * Copyright (c) 2012 project bchan
5  *
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.
9  *
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:
13  *
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.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source
23  *    distribution.
24  *
25  */
26
27 #include "http_connector.h"
28
29 #include        <basic.h>
30 #include        <bstdio.h>
31 #include        <bstdlib.h>
32 #include        <errcode.h>
33 #include        <btron/btron.h>
34 #include        <btron/bsocket.h>
35
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"
44
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)
48 #else
49 # define DP(arg) /**/
50 # define DP_ER(msg, err) /**/
51 #endif
52
53 #if 0
54 # define DP_STATE(state) printf("%s\n", state)
55 #else
56 # define DP_STATE(state) /**/
57 #endif
58
59 struct http_reqentry_t_ {
60         idtocb_entry_t base;
61         enum {
62                 NON_EXISTENT,
63                 WAITING_TRANSPORT,
64                 SENDING_REQUEST,
65                 WAITING_RESPONSE,
66                 RECEIVING_RESPONSE,
67                 ABORTED_BY_TRANSPORT,
68                 COMPLETED
69         } status;
70         enum {
71                 SEND_REQUEST_LINE,
72                 SEND_HEADER_MINE,
73                 SEND_HEADER_USER,
74                 SEND_MESSAGE_BODY,
75                 SEND_COMPLETED,
76         } snd_state;
77         enum {
78                 RECEIVE_STATUS_LINE,
79                 RECEIVE_HEADER,
80                 RECEIVE_HEADER_END,
81                 RECEIVE_MESSAGE_BODY,
82                 RECEIVE_MESSAGE_BODY_TRANSFERDECODE,
83                 RECEIVE_MESSAGE_BODY_CONTENTDECODE,
84                 RECEIVE_MESSAGE_END,
85                 RECEIVE_COMPLETED,
86         } rcv_state;
87         Bool aborted_by_user;
88         HTTP_METHOD method;
89         UB *host;
90         W host_len;
91         SOCKADDR addr;
92         ID transport;
93         struct {
94                 http_statuslineparser_t sl;
95                 http_defaultheaderparser_t dh;
96                 http_transferdecoder_t tc;
97                 http_contentdecoder_t cc;
98                 struct {
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;
105                 } body;
106         } rcv_reader;
107 };
108 typedef struct http_reqentry_t_ http_reqentry_t;
109
110 LOCAL VOID http_reqentry_attachendpoint(http_reqentry_t *entry, http_transport_t *transport, ID endpoint)
111 {
112         http_transport_holdendpoint(transport, endpoint);
113         entry->status = SENDING_REQUEST;
114         entry->transport = endpoint;
115         return;
116 }
117
118 LOCAL VOID http_reqentry_detachendpoint(http_reqentry_t *entry, http_transport_t *transport, Bool transport_close)
119 {
120         http_transport_releaseendpoint(transport, entry->transport, transport_close);
121         entry->transport = -1;
122         return;
123 }
124
125 LOCAL W http_reqentry_initialize(http_reqentry_t *entry, UB *host, W host_len, UH port, HTTP_METHOD method)
126 {
127         W err;
128         B buf[HBUFLEN];
129         HOSTENT ent;
130         struct sockaddr_in *addr_in;
131
132         entry->host = malloc(sizeof(UB)*(host_len+1));
133         if (entry->host == NULL) {
134                 err = ER_NOMEM; /* TODO: detail error code */
135                 goto error_host;
136         }
137         memcpy(entry->host, host, host_len);
138         entry->host[host_len] = '\0';
139         entry->host_len = host_len;
140
141         err = so_gethostbyname(entry->host, &ent, buf);
142         if (err < 0) {
143                 goto error_gethostbyname;
144         }
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]);
149
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;
156
157         http_statuslineparser_initialize(&entry->rcv_reader.sl);
158         http_defaultheaderparser_initialize(&entry->rcv_reader.dh);
159
160         return 0;
161
162 error_gethostbyname:
163         free(entry->host);
164 error_host:
165         entry->status = NON_EXISTENT;
166         return err;
167 }
168
169 LOCAL VOID http_reqentry_finalize(http_reqentry_t *entry)
170 {
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);
178                 break;
179         case RECEIVE_STATUS_LINE:
180         case RECEIVE_HEADER:
181         case RECEIVE_HEADER_END:
182         case RECEIVE_COMPLETED:
183                 break;
184         }
185         http_defaultheaderparser_finalize(&entry->rcv_reader.dh);
186         http_statuslineparser_finalize(&entry->rcv_reader.sl);
187         if (entry->host != NULL) {
188                 free(entry->host);
189         }
190 }
191
192 struct http_reqdict_t_ {
193         idtocb_t *base;
194         W entries;
195         http_reqentry_t entry[1];
196 };
197 typedef struct http_reqdict_t_ http_reqdict_t;
198
199 typedef struct {
200         idtocb_iterator_t base;
201 } http_recdictiterator_t;
202
203 LOCAL Bool http_reqdictiterator_next(http_recdictiterator_t *iter, http_reqentry_t **entry)
204 {
205         return idtocb_iterator_next(&iter->base, (idtocb_entry_t**)entry);
206 }
207
208 LOCAL VOID http_reqdictiterator_initialize(http_recdictiterator_t *iter, http_reqdict_t *dict)
209 {
210         idtocb_iterator_initialize(&iter->base, dict->base);
211 }
212
213 LOCAL VOID http_reqdictiterator_finalize(http_recdictiterator_t *iter)
214 {
215         idtocb_iterator_finalize(&iter->base);
216 }
217
218 LOCAL ID http_reqdict_allocate(http_reqdict_t *dict, UB *host, W host_len, UH port, HTTP_METHOD method)
219 {
220         ID id;
221         http_reqentry_t *cb;
222         W err;
223
224         id = idtocb_allocate(dict->base);
225         if (id < 0) {
226                 return id;
227         }
228         err = idtocb_getcontrolblock(dict->base, id, (idtocb_entry_t**)&cb);
229         if (err < 0) {
230                 idtocb_free(dict->base, id);
231                 return err;
232         }
233
234         err = http_reqentry_initialize(cb, host, host_len, port, method);
235         if (err < 0) {
236                 idtocb_free(dict->base, id);
237                 return err;
238         }
239
240         return id;
241 }
242
243 LOCAL http_reqentry_t* http_reqdict_getentrybyID(http_reqdict_t *dict, ID id)
244 {
245         http_reqentry_t *entry;
246         W err;
247
248         err = idtocb_getcontrolblock(dict->base, id, (idtocb_entry_t**)&entry);
249         if (err < 0) {
250                 return NULL;
251         }
252         return entry;
253 }
254
255 LOCAL VOID http_reqdict_free(http_reqdict_t *dict, ID id)
256 {
257         http_reqentry_t *entry;
258         W err;
259
260         err = idtocb_getcontrolblock(dict->base, id, (idtocb_entry_t**)&entry);
261         if (err < 0) {
262                 return;
263         }
264         http_reqentry_finalize(entry);
265         idtocb_free(dict->base, id);
266 }
267
268 LOCAL http_reqdict_t* http_reqdict_new(W max_entries)
269 {
270         http_reqdict_t *dict;
271
272         dict = (http_reqdict_t*)malloc(sizeof(http_reqdict_t));
273         if (dict == NULL) {
274                 return NULL;
275         }
276         dict->base = idtocb_new(sizeof(http_reqentry_t), max_entries);
277         if (dict->base == NULL) {
278                 free(dict);
279                 return NULL;
280         }
281         return dict;
282 }
283
284 LOCAL VOID http_reqdict_delete(http_reqdict_t *dict)
285 {
286         http_recdictiterator_t iter;
287         http_reqentry_t *entry;
288         Bool cont;
289
290         http_reqdictiterator_initialize(&iter, dict);
291         for (;;) {
292                 cont = http_reqdictiterator_next(&iter, &entry);
293                 if (cont == False) {
294                         break;
295                 }
296                 http_reqentry_finalize(entry);
297         }
298         http_reqdictiterator_finalize(&iter);
299
300         idtocb_delete(dict->base);
301         free(dict);
302 }
303
304 struct http_connector_t_ {
305         http_reqdict_t *dict;
306         http_transport_t *transport;
307         ID flg;
308 };
309
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)
315
316 EXPORT ID http_connector_createendpoint(http_connector_t *connector, UB *host, W host_len, UH port, HTTP_METHOD method)
317 {
318         ID id;
319         W err;
320
321         id = http_reqdict_allocate(connector->dict, host, host_len, port, method);
322         if (id < 0) {
323                 DP_ER("http_reqdict_allocate", id);
324                 return id; /* TODO */
325         }
326
327         err = set_flg(connector->flg, HTTP_CONNECTOR_FLAG_REQUEST);
328         if (err < 0) {
329                 DP_ER("set_flg", err);
330                 http_reqdict_free(connector->dict, id);
331                 return err;
332         }
333
334         return id;
335 }
336
337 EXPORT VOID http_connector_deleteendpoint(http_connector_t *connector, ID endpoint)
338 {
339         http_reqentry_t *entry;
340
341         entry = http_reqdict_getentrybyID(connector->dict, endpoint);
342         if (entry == NULL) {
343                 return;
344         }
345         entry->aborted_by_user = True;
346 }
347
348 LOCAL VOID http_connector_collect(http_connector_t *connector)
349 {
350         http_reqentry_t *entry;
351         http_recdictiterator_t iter;
352         Bool cont;
353
354         http_reqdictiterator_initialize(&iter, connector->dict);
355         for (;;) {
356                 cont = http_reqdictiterator_next(&iter, &entry);
357                 if (cont == False) {
358                         break;
359                 }
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);
364                 }
365         }
366         http_reqdictiterator_finalize(&iter);
367 }
368
369 LOCAL W http_connector_searchwaiting(http_connector_t *connector)
370 {
371         W ret = 0;
372         http_reqentry_t *entry;
373         http_recdictiterator_t iter;
374         Bool cont, holded;
375         ID endpoint;
376
377         http_reqdictiterator_initialize(&iter, connector->dict);
378         for (;;) {
379                 cont = http_reqdictiterator_next(&iter, &entry);
380                 if (cont == False) {
381                         break;
382                 }
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);
387                                 if (endpoint < 0) {
388                                         continue;
389                                 }
390                         } else if (endpoint < 0) {
391                                 continue;
392                         }
393                         http_transport_isholdedendpoint(connector->transport, endpoint, &holded);
394                         if (holded != False) {
395                                 continue;
396                         }
397                         http_reqentry_attachendpoint(entry, connector->transport, endpoint);
398                         ret++;
399                 }
400         }
401         http_reqdictiterator_finalize(&iter);
402
403         return ret;
404 }
405
406 LOCAL W http_connector_waitreceiving(http_connector_t *connector, TMOUT tmout)
407 {
408         W ret = 0;
409         http_reqentry_t *entry;
410         http_recdictiterator_t iter;
411         Bool cont, is_ready;
412
413         http_reqdictiterator_initialize(&iter, connector->dict);
414         for (;;) {
415                 cont = http_reqdictiterator_next(&iter, &entry);
416                 if (cont == False) {
417                         break;
418                 }
419                 if (entry->status == WAITING_RESPONSE) {
420                         http_transport_setwaitingreceive(connector->transport, entry->transport);
421                 }
422         }
423         http_reqdictiterator_finalize(&iter);
424
425         http_transport_waitreceive(connector->transport, tmout);
426
427         http_reqdictiterator_initialize(&iter, connector->dict);
428         for (;;) {
429                 cont = http_reqdictiterator_next(&iter, &entry);
430                 if (cont == False) {
431                         break;
432                 }
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;
437                                 ret++;
438                         }
439                 }
440         }
441         http_reqdictiterator_finalize(&iter);
442
443         return ret;
444 }
445
446 EXPORT W http_connector_waitconnection(http_connector_t *connector, TMOUT tmout)
447 {
448         W err;
449         Bool evt = False;
450
451         /**/
452         http_connector_collect(connector);
453
454         err = http_connector_searchwaiting(connector);
455         if (err < 0) {
456                 return err;
457         }
458         if (err > 0) {
459                 evt = True;
460         }
461         http_transport_releaseunusedendpoint(connector->transport);
462
463         err = http_connector_waitreceiving(connector, tmout);
464         if (err < 0) {
465                 return err;
466         }
467         if (err > 0) {
468                 evt = True;
469         }
470
471         if (evt != False) {
472                 err = set_flg(connector->flg, HTTP_CONNECTOR_FLAG_EVENT);
473                 if (err < 0) {
474                         DP_ER("set_flg", err);
475                 }
476         }
477
478         return 0;
479 }
480
481 LOCAL W http_connector_rcv_status_line(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
482 {
483         http_statuslineparser_result result;
484         UB *bin;
485         W i, len, err;
486         Bool end = False;
487
488         err = http_transport_read(connector->transport, entry->transport, &bin, &len);
489         if (err < 0) {
490                 DP_ER("http_transport_read", err);
491                 return err;
492         }
493
494         for (i = 0; i < len; i++) {
495                 end = http_statuslineparser_inputchar(&entry->rcv_reader.sl, bin[i], &result);
496                 if (end != False) {
497                         i++;
498                         break;
499                 }
500         }
501
502         http_transport_consumereadbuffer(connector->transport, entry->transport, i);
503
504         if (end != False) {
505                 if (result.error != HTTP_STATUSLINEPARSER_ERROR_NONE) {
506                         return -1; /* TODO */
507                 }
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;
513                 return 1;
514         }
515
516         return 0;
517 }
518
519 LOCAL W http_connector_rcv_header(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
520 {
521         HTTP_DEFAULTHEADERPARSER_RESULT result;
522         UB *bin;
523         W i, len, err;
524         Bool end = False;
525
526         err = http_transport_read(connector->transport, entry->transport, &bin, &len);
527         if (err < 0) {
528                 DP_ER("http_transport_read", err);
529                 return err;
530         }
531
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) {
535                         end = True;
536                         i++;
537                         break;
538                 }
539         }
540
541         http_transport_consumereadbuffer(connector->transport, entry->transport, i);
542
543         if (end != False) {
544                 entry->rcv_state = RECEIVE_HEADER_END;
545         }
546
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;
551
552         return 1;
553 }
554
555 LOCAL W http_connector_rcv_header_end(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
556 {
557         W err;
558         W content_length;
559         HTTP_TRANSFERCODING_TYPE transfer_coding;
560         HTTP_CONTENTCODING_VALUE content_coding;
561
562         entry->rcv_state = RECEIVE_MESSAGE_BODY;
563         event->endpoint = entry->base.id;
564         event->type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE_HEADER_END;
565
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);
569
570         http_transferdecoder_initialize(&entry->rcv_reader.tc, transfer_coding, content_length);
571         err = http_contentdecoder_initialize(&entry->rcv_reader.cc, content_coding);
572         if (err < 0) {
573                 return err;
574         }
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;
581
582         return 1;
583 }
584
585 LOCAL W http_connector_rcv_message_body_contentdecode(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
586 {
587         W err;
588         http_contentdecoder_result *result;
589
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);
592                 if (err < 0) {
593                         DP_ER("http_contentdecoder_outputdata", err);
594                         return err;
595                 }
596                 entry->rcv_reader.body.content_result_consumed = 0;
597         }
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;
606                 return 1;
607         case HTTP_CONTENTDECODER_RESULTTYPE_NEED_INPUT:
608                 entry->rcv_state = RECEIVE_MESSAGE_BODY_TRANSFERDECODE;
609                 break;
610         case HTTP_CONTENTDECODER_RESULTTYPE_END:
611                 entry->rcv_state = RECEIVE_MESSAGE_END;
612                 break;
613         }
614
615         return 0;
616 }
617
618 LOCAL W http_connector_rcv_message_body_transferdecode(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
619 {
620         http_transferdecoder_result *result;
621         W err;
622
623         if (entry->rcv_reader.body.transfer_result_consumed == entry->rcv_reader.body.transfer_result_len) {
624                 entry->rcv_state = RECEIVE_MESSAGE_BODY;
625                 return 0;
626         }
627
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);
632                 break;
633         case HTTP_TRANSFERDECODER_RESULTTYPE_END:
634                 err = http_contentdecoder_inputendofdata(&entry->rcv_reader.cc);
635                 break;
636         default:
637                 err = 0;
638         }
639         entry->rcv_reader.body.transfer_result_consumed++;
640         if (err < 0) {
641                 DP_ER("http_contentdecoder_inputXXX", err);
642                 return err;
643         }
644         entry->rcv_state = RECEIVE_MESSAGE_BODY_CONTENTDECODE;
645
646         return http_connector_rcv_message_body_contentdecode(connector, entry, event);
647 }
648
649 LOCAL W http_connector_rcv_message_body(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
650 {
651         UB *bin;
652         W len, err;
653
654         err = http_transport_read(connector->transport, entry->transport, &bin, &len);
655         if (err < 0) {
656                 DP_ER("http_transport_read", err);
657                 return err;
658         }
659
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);
663
664         entry->rcv_state = RECEIVE_MESSAGE_BODY_TRANSFERDECODE;
665
666         return http_connector_rcv_message_body_transferdecode(connector, entry, event);
667 }
668
669 LOCAL W http_connector_rcv_message_end(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
670 {
671         Bool connection_closed;
672
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);
676
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;
681
682         /* TODO: Connection: close */
683         http_reqentry_detachendpoint(entry, connector->transport, connection_closed);
684
685         return 1;
686 }
687
688 LOCAL W http_connector_handleevent_receiving_response(http_connector_t *connector, http_reqentry_t *entry, http_connector_event *event)
689 {
690         W err = 0;
691
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);
696                 break;
697         case RECEIVE_HEADER:
698                 DP_STATE("RECEIVE_RECEIVE_HEADER");
699                 err = http_connector_rcv_header(connector, entry, event);
700                 break;
701         case RECEIVE_HEADER_END:
702                 DP_STATE("RECEIVE_HEADER_END");
703                 err = http_connector_rcv_header_end(connector, entry, event);
704                 break;
705         case RECEIVE_MESSAGE_BODY:
706                 DP_STATE("RECEIVE_MESSAGE_BODY");
707                 err = http_connector_rcv_message_body(connector, entry, event);
708                 break;
709         case RECEIVE_MESSAGE_BODY_TRANSFERDECODE:
710                 DP_STATE("RECEIVE_MESSAGE_BODY_TRANSFERDECODE");
711                 err = http_connector_rcv_message_body_transferdecode(connector, entry, event);
712                 break;
713         case RECEIVE_MESSAGE_BODY_CONTENTDECODE:
714                 DP_STATE("RECEIVE_MESSAGE_BODY_CONTENTDECDE");
715                 err = http_connector_rcv_message_body_contentdecode(connector, entry, event);
716                 break;
717         case RECEIVE_MESSAGE_END:
718                 DP_STATE("RECEIVE_MESSAGE_END");
719                 err = http_connector_rcv_message_end(connector, entry, event);
720                 break;
721         case RECEIVE_COMPLETED:
722                 DP_STATE("RECEIVE_COMPLETED");
723                 err = 0;
724                 break;
725         }
726
727         return err;
728 }
729
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)
732 {
733         http_reqentry_t *entry;
734         http_recdictiterator_t iter;
735         Bool cont, found = False;
736         W err;
737
738         event->type = HTTP_CONNECTOR_EVENTTYPE_NONE;
739
740         http_reqdictiterator_initialize(&iter, connector->dict);
741         for (;;) {
742                 cont = http_reqdictiterator_next(&iter, &entry);
743                 if (cont == False) {
744                         break;
745                 }
746                 if (entry->status == SENDING_REQUEST) {
747                         event->type = HTTP_CONNECTOR_EVENTTYPE_SEND;
748                         event->endpoint = entry->base.id;
749                         found = True;
750                         break;
751                 }
752                 if (entry->status == RECEIVING_RESPONSE) {
753                         err = http_connector_handleevent_receiving_response(connector, entry, event);
754                         if (err < 0) {
755                                 /* TODO */
756                                 break;
757                         }
758                         found = True;
759                         if (err > 0) {
760                                 break;
761                         }
762                 }
763         }
764         http_reqdictiterator_finalize(&iter);
765
766         return found;
767 }
768
769 EXPORT W http_connector_getevent(http_connector_t *connector, http_connector_event *event)
770 {
771         W err;
772         Bool found;
773
774         err = wai_flg(connector->flg, HTTP_CONNECTOR_FLAG_EVENT, WF_AND|NOCLR, T_NOWAIT);
775         if ((err & 0xFFFF0000) == ER_NONE) {
776                 return err;
777         }
778         if (err < 0) {
779                 DP_ER("wai_flg", err);
780                 return err;
781         }
782         found = http_connector_searcheventtarget(connector, event);
783         if (found == False) {
784                 err = clr_flg(connector->flg, HTTP_CONNECTOR_FLAG_CLEARMASK_EVENT);
785                 if (err < 0) {
786                         DP_ER("clr_flg", err);
787                         return err;
788                 }
789                 return ER_NONE; /* TODO: detail error code */
790         }
791         if (event->type == HTTP_CONNECTOR_EVENTTYPE_NONE) {
792                 return ER_NONE; /* TODO: detail error code */
793         }
794         return 0;
795 }
796
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 */ \
801         } \
802         if ((entry)->status != SENDING_REQUEST) { \
803                 return ER_PAR; /* TODO: suitable error code */ \
804         } \
805         if ((entry)->snd_state != (state)) { \
806                 return ER_PAR; /* TODO: suitable error code */ \
807         } \
808
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 */ \
813         } \
814         if ((entry)->status != SENDING_REQUEST) { \
815                 return ER_PAR; /* TODO: suitable error code */ \
816         } \
817         if (((entry)->snd_state != (state1))&&((entry)->snd_state != (state2))) { \
818                 return ER_PAR; /* TODO: suitable error code */ \
819         } \
820
821 EXPORT W http_connector_sendrequestline(http_connector_t *connector, ID endpoint, UB *path, W path_len)
822 {
823         http_reqentry_t *entry;
824         http_requestlinestream_t reqline;
825         W err, len;
826         Bool cont;
827         CONST UB *str;
828
829         HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_REQUEST_LINE, entry);
830
831         err = http_requestlinestream_initialize(&reqline, entry->method, path, path_len);
832         if (err < 0) {
833                 return err;
834         }
835         for (;;) {
836                 cont = http_requestlinestream_make(&reqline, &str, &len);
837                 if (cont == False) {
838                         break;
839                 }
840                 err = http_transport_write(connector->transport, entry->transport, str, len);
841                 if (err < 0) {
842                         break;
843                 }
844         }
845         http_requestlinestream_finalize(&reqline);
846
847         if (err < 0) {
848                 return err;
849         }
850
851         entry->snd_state = SEND_HEADER_MINE;
852
853         return 0;
854 }
855
856 LOCAL W http_connector_writedefaultheader(http_connector_t *connector, ID transport, UB *host, W host_len)
857 {
858         http_defaultheaderstream_t defaultheader;
859         W err = 0, len;
860         Bool cont;
861         CONST UB *str;
862
863         http_defaultheaderstream_initialize(&defaultheader, host, host_len);
864         for (;;) {
865                 cont = http_defaultheaderstream_make(&defaultheader, &str, &len);
866                 if (cont == False) {
867                         break;
868                 }
869                 err = http_transport_write(connector->transport, transport, str, len);
870                 if (err < 0) {
871                         break;
872                 }
873         }
874         http_defaultheaderstream_finalize(&defaultheader);
875
876         return err;
877 }
878
879 EXPORT W http_connector_sendheader(http_connector_t *connector, ID endpoint, UB *p, W len)
880 {
881         http_reqentry_t *entry;
882         W err;
883
884         HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, SEND_HEADER_MINE, SEND_HEADER_USER, entry);
885
886         if (entry->snd_state == SEND_HEADER_MINE) {
887                 err = http_connector_writedefaultheader(connector, entry->transport, entry->host, entry->host_len);
888                 if (err < 0) {
889                         return err;
890                 }
891                 entry->snd_state = SEND_HEADER_USER;
892         }
893
894         return 0;
895 }
896
897 EXPORT W http_connector_sendheaderend(http_connector_t *connector, ID endpoint)
898 {
899         http_reqentry_t *entry;
900         W err;
901
902         HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, SEND_HEADER_MINE, SEND_HEADER_USER, entry);
903
904         if (entry->snd_state == SEND_HEADER_MINE) {
905                 err = http_connector_writedefaultheader(connector, entry->transport, entry->host, entry->host_len);
906                 if (err < 0) {
907                         return err;
908                 }
909         }
910         err = http_transport_write(connector->transport, entry->transport, "\r\n", 2);
911         if (err < 0) {
912                 return err;
913         }
914
915         entry->snd_state = SEND_MESSAGE_BODY;
916
917         return 0;
918 }
919
920 EXPORT W http_connector_sendmessagebody(http_connector_t *connector, ID endpoint, UB *p, W len)
921 {
922         http_reqentry_t *entry;
923         W err;
924
925         HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_MESSAGE_BODY, entry);
926
927         err = http_transport_write(connector->transport, entry->transport, p, len);
928         if (err < 0) {
929                 return err;
930         }
931
932         return 0;
933 }
934
935 EXPORT W http_connector_sendmessagebodyend(http_connector_t *connector, ID endpoint)
936 {
937         http_reqentry_t *entry;
938
939         HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_MESSAGE_BODY, entry);
940
941         entry->status = WAITING_RESPONSE;
942
943         return 0;
944 }
945
946 EXPORT http_connector_t* http_connector_new()
947 {
948         http_connector_t *connector;
949
950         connector = (http_connector_t*)malloc(sizeof(http_connector_t));
951         if (connector == NULL) {
952                 DP_ER("malloc", 0);
953                 return NULL;
954         }
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;
959         }
960         connector->flg = cre_flg(0, DELEXIT);
961         if (connector->flg < 0) {
962                 DP_ER("cre_flg", connector->flg);
963                 goto error_flg;
964         }
965         connector->transport = http_transport_new(10/*tmp*/);
966         if (connector->transport == NULL) {
967                 DP_ER("http_transport_new", -1);
968                 goto error_transport;
969         }
970
971         return connector;
972
973         http_transport_delete(connector->transport);
974 error_transport:
975         del_flg(connector->flg);
976 error_flg:
977         http_reqdict_delete(connector->dict);
978 error_http_reqdict:
979         free(connector);
980         return NULL;
981 }
982
983 EXPORT VOID http_connector_delete(http_connector_t *connector)
984 {
985         http_transport_delete(connector->transport);
986         del_flg(connector->flg);
987         http_reqdict_delete(connector->dict);
988         free(connector);
989 }