• R/O
  • SSH
  • HTTPS

bchan: 提交


Commit MetaInfo

修訂347 (tree)
時間2012-01-15 17:50:14
作者ornse01

Log Message

implement http connection manager's some functions.
- only messeging and structures.

Change Summary

差異

--- bchanf/trunk/src/http/http_connection.c (revision 346)
+++ bchanf/trunk/src/http/http_connection.c (revision 347)
@@ -0,0 +1,555 @@
1+/*
2+ * http_connection.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_connection.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+#ifdef BCHAN_CONFIG_DEBUG
37+# define DP(arg) printf arg
38+# define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
39+#else
40+# define DP(arg) /**/
41+# define DP_ER(msg, err) /**/
42+#endif
43+
44+struct http_reqentry_t_ {
45+ enum {
46+ NON_EXISTENT,
47+ WAITING_ENDPOINT,
48+ SENDING,
49+ RECEIVING,
50+ ABORTED_BY_TRANSPORT,
51+ ABORTED_BY_USER,
52+ COMPLETED
53+ } status;
54+ UB *host;
55+ W host_len;
56+ UB *path;
57+ W path_len;
58+ SOCKADDR addr;
59+ VP arg;
60+};
61+typedef struct http_reqentry_t_ http_reqentry_t;
62+
63+LOCAL VOID http_reqentry_attachendpoint(http_reqentry_t *entry)
64+{
65+ entry->status = SENDING;
66+ /* TODO */
67+ return;
68+}
69+
70+LOCAL VOID http_reqentry_detachendpoint(http_reqentry_t *entry)
71+{
72+ entry->status = WAITING_ENDPOINT;
73+ /* TODO */
74+ return;
75+}
76+
77+LOCAL W http_reqentry_allocate(http_reqentry_t *entry, UB *host, W host_len, UH port, UB *path, W path_len, VP arg)
78+{
79+ W err;
80+ B buf[HBUFLEN];
81+ HOSTENT ent;
82+ struct sockaddr_in *addr_in;
83+
84+ entry->status = WAITING_ENDPOINT;
85+ entry->host = malloc(sizeof(UB)*(host_len+1));
86+ if (entry->host == NULL) {
87+ err = ER_NOMEM; /* TODO: detail error code */
88+ goto error_host;
89+ }
90+ memcpy(entry->host, host, host_len);
91+ entry->host[host_len] = '\0';
92+ entry->host_len = host_len;
93+ entry->path = malloc(sizeof(UB)*(path_len+1));
94+ if (entry->path == NULL) {
95+ err = ER_NOMEM; /* TODO: detail error code */
96+ goto error_path;
97+ }
98+ memcpy(entry->path, path, path_len);
99+ entry->path[path_len] = '\0';
100+ entry->path_len = path_len;
101+ entry->arg = arg;
102+
103+ err = so_gethostbyname(entry->host, &ent, buf);
104+ if (err < 0) {
105+ goto error_gethostbyname;
106+ }
107+ addr_in = (struct sockaddr_in *)&(entry->addr);
108+ addr_in->sin_family = AF_INET;
109+ addr_in->sin_port = htons( port );
110+ addr_in->sin_addr.s_addr = *(unsigned int *)(ent.h_addr_list[0]);
111+
112+ return 0;
113+
114+error_gethostbyname:
115+ free(entry->path);
116+error_path:
117+ free(entry->host);
118+error_host:
119+ entry->status = NON_EXISTENT;
120+ return err;
121+}
122+
123+LOCAL VOID http_reqentry_free(http_reqentry_t *entry)
124+{
125+ entry->path_len = 0;
126+ if (entry->path != NULL) {
127+ free(entry->path);
128+ }
129+ entry->host_len = 0;
130+ if (entry->host != NULL) {
131+ free(entry->host);
132+ }
133+ entry->status = NON_EXISTENT;
134+}
135+
136+LOCAL VOID http_reqentry_initialize(http_reqentry_t *entry)
137+{
138+ entry->status = NON_EXISTENT;
139+ entry->host = NULL;
140+ entry->host_len = 0;
141+ entry->path = NULL;
142+ entry->path_len = 0;
143+ entry->arg = NULL;
144+}
145+
146+LOCAL VOID http_reqentry_finalize(http_reqentry_t *entry)
147+{
148+ if (entry->path != NULL) {
149+ free(entry->path);
150+ }
151+ if (entry->host != NULL) {
152+ free(entry->host);
153+ }
154+}
155+
156+struct http_reqdict_t_ {
157+ W entries;
158+ http_reqentry_t entry[1];
159+};
160+typedef struct http_reqdict_t_ http_reqdict_t;
161+
162+LOCAL http_reqentry_t* http_reqdict_allocate(http_reqdict_t *dict, UB *host, W host_len, UH port, UB *path, W path_len, VP arg)
163+{
164+ W i, err;
165+
166+ for (i = 0; i < dict->entries; i++) {
167+ if (dict->entry[i].status == NON_EXISTENT) {
168+ break;
169+ }
170+ }
171+ if (i == dict->entries) {
172+ return NULL;
173+ }
174+
175+ err = http_reqentry_allocate(dict->entry + i, host, host_len, port, path, path_len, arg);
176+ if (err < 0) {
177+ return NULL;
178+ }
179+
180+ return dict->entry + i;
181+}
182+
183+LOCAL http_reqentry_t* http_reqdict_getentrybyindex(http_reqdict_t *dict, W i)
184+{
185+ return dict->entry + i;
186+}
187+
188+LOCAL W http_reqdict_length(http_reqdict_t *dict)
189+{
190+ return dict->entries;
191+}
192+
193+LOCAL VOID http_reqdict_free(http_reqdict_t *dict, http_reqentry_t *entry)
194+{
195+ http_reqentry_free(entry);
196+}
197+
198+LOCAL http_reqdict_t* http_reqdict_new(W max_entries)
199+{
200+ http_reqdict_t *dict;
201+ W i;
202+
203+ dict = (http_reqdict_t*)malloc(sizeof(W)*sizeof(http_reqdict_t)*max_entries);
204+ if (dict == NULL) {
205+ return NULL;
206+ }
207+ dict->entries = max_entries;
208+ for (i = 0; i < max_entries; i++) {
209+ http_reqentry_initialize(dict->entry+i);
210+ }
211+ return dict;
212+}
213+
214+LOCAL VOID http_reqdict_delete(http_reqdict_t *dict)
215+{
216+ W i;
217+ for (i = 0; i < dict->entries; i++) {
218+ http_reqentry_finalize(dict->entry+i);
219+ }
220+ free(dict);
221+}
222+
223+struct http_requestsending_t_ {
224+ enum {
225+ SND_NONEXISTENT,
226+ SND_ALLOCATED,
227+ } status;
228+ http_reqentry_t *entry;
229+};
230+
231+EXPORT W http_requestsending_sendheader(http_requestsending_t *request, UB *p, W len)
232+{
233+ /* TODO: transport */
234+ return 0;
235+}
236+
237+EXPORT W http_requestsending_headerend(http_requestsending_t *request)
238+{
239+ /* TODO: transport */
240+ return 0;
241+}
242+
243+EXPORT W http_requestsending_sendmessagebody(http_requestsending_t *request, UB *p, W len)
244+{
245+ /* TODO: transport */
246+ return 0;
247+}
248+
249+EXPORT W http_requestsending_messageend(http_requestsending_t *request)
250+{
251+ /* TODO: transport */
252+ request->entry->status = RECEIVING; /* tmp */
253+ return 0;
254+}
255+
256+LOCAL VOID http_requestsending_initialize(http_requestsending_t *snd)
257+{
258+ snd->status = SND_NONEXISTENT;
259+ snd->entry = NULL;
260+}
261+
262+LOCAL VOID http_requestsending_finalize(http_requestsending_t *snd)
263+{
264+}
265+
266+struct http_responsereceiving_t_ {
267+ enum {
268+ RCV_NONEXISTENT,
269+ RCV_ALLOCATED,
270+ } status;
271+ http_reqentry_t *entry;
272+};
273+
274+EXPORT W http_responsereceiving_getmessage(http_responsereceiving_t *response, http_responsereceiving_result *result)
275+{
276+ /* TODO: transport */
277+ result->type = HTTP_RESPONSERECEIVING_RESULTTYPE_MESSAGEBODY_END;
278+ result->data = NULL;
279+ result->len = 0;
280+ return 0;
281+}
282+
283+EXPORT W http_responsereceiving_messageend(http_responsereceiving_t *response)
284+{
285+ /* TODO: transport */
286+ response->entry->status = COMPLETED;
287+ return 0;
288+}
289+
290+LOCAL VOID http_responsereceiving_initialize(http_responsereceiving_t *rcv)
291+{
292+ rcv->status = SND_NONEXISTENT;
293+ rcv->entry = NULL;
294+}
295+
296+LOCAL VOID http_responsereceiving_finalize(http_responsereceiving_t *rcv)
297+{
298+}
299+
300+struct http_ctxbuf_t_ {
301+ http_requestsending_t *snd;
302+ http_responsereceiving_t *rcv;
303+ W buflen;
304+};
305+typedef struct http_ctxbuf_t_ http_ctxbuf_t;
306+
307+LOCAL http_requestsending_t* http_ctxbuf_allocatesend(http_ctxbuf_t *ctxbuf, http_reqentry_t *entry)
308+{
309+ W i;
310+
311+ for (i = 0; i < ctxbuf->buflen; i++) {
312+ if (ctxbuf->snd[i].status == SND_NONEXISTENT) {
313+ ctxbuf->snd[i].status = SND_ALLOCATED;
314+ ctxbuf->snd[i].entry = entry;
315+ return ctxbuf->snd + i;
316+ }
317+ }
318+
319+ return NULL;
320+}
321+
322+LOCAL http_responsereceiving_t* http_ctxbuf_allocatereceive(http_ctxbuf_t *ctxbuf, http_reqentry_t *entry)
323+{
324+ W i;
325+
326+ for (i = 0; i < ctxbuf->buflen; i++) {
327+ if (ctxbuf->rcv[i].status == RCV_NONEXISTENT) {
328+ ctxbuf->rcv[i].status = RCV_ALLOCATED;
329+ ctxbuf->rcv[i].entry = entry;
330+ return ctxbuf->rcv + i;
331+ }
332+ }
333+
334+ return NULL;
335+}
336+
337+LOCAL W http_ctxbuf_initialize(http_ctxbuf_t *ctxbuf, W buf_len)
338+{
339+ W i;
340+
341+ ctxbuf->snd = (http_requestsending_t *)malloc(sizeof(http_requestsending_t)*buf_len);
342+ if (ctxbuf->snd == NULL) {
343+ return ER_NOMEM;
344+ }
345+ ctxbuf->rcv = (http_responsereceiving_t *)malloc(sizeof(http_responsereceiving_t)*buf_len);
346+ if (ctxbuf->rcv == NULL) {
347+ free(ctxbuf->snd);
348+ return ER_NOMEM;
349+ }
350+ ctxbuf->buflen = buf_len;
351+
352+ for (i = 0; i < buf_len; i++) {
353+ http_requestsending_initialize(ctxbuf->snd + i);
354+ http_responsereceiving_initialize(ctxbuf->rcv + i);
355+ }
356+
357+ return 0;
358+}
359+
360+LOCAL VOID http_ctxbuf_finalize(http_ctxbuf_t *ctxbuf)
361+{
362+ W i = 0;
363+
364+ for (i = 0; i < ctxbuf->buflen; i++) {
365+ http_responsereceiving_finalize(ctxbuf->rcv + i);
366+ http_requestsending_finalize(ctxbuf->snd + i);
367+ }
368+}
369+
370+struct http_connector_t_ {
371+ http_reqdict_t *dict;
372+ http_ctxbuf_t ctxbuf;
373+ ID reqmbf;
374+ ID evtmbf;
375+};
376+
377+EXPORT W http_connector_request(http_connector_t *connector, UB *host, W host_len, UH port, UB *path, W path_len, VP arg)
378+{
379+ http_reqentry_t *entry;
380+
381+ entry = http_reqdict_allocate(connector->dict, host, host_len, port, path, path_len, arg);
382+ if (entry != NULL) {
383+ return -1; /* TODO */
384+ }
385+
386+ return snd_mbf(connector->reqmbf, NULL, 0, T_FOREVER/* tmp */);
387+}
388+
389+LOCAL VOID http_connector_collect(http_connector_t *connector)
390+{
391+ W i, len;
392+ http_reqentry_t *entry;
393+
394+ len = http_reqdict_length(connector->dict);
395+ for (i = 0; i < len ; i++) {
396+ entry = http_reqdict_getentrybyindex(connector->dict, i);
397+ if (entry->status == ABORTED_BY_TRANSPORT) {
398+ http_reqdict_free(connector->dict, entry);
399+ } else if (entry->status == COMPLETED) {
400+ /* TODO: release endpoint */
401+ http_reqdict_free(connector->dict, entry);
402+ }
403+ }
404+}
405+
406+LOCAL W http_connector_sendsendmessage(http_connector_t *connector, http_reqentry_t *entry)
407+{
408+ volatile http_connector_event evt;
409+ http_requestsending_t *snd;
410+
411+ snd = http_ctxbuf_allocatesend(&connector->ctxbuf, entry);
412+ if (snd == NULL) {
413+ return ER_NONE;
414+ }
415+
416+ evt.type = HTTP_CONNECTOR_EVENTTYPE_SEND;
417+ evt.ctx.request = snd;
418+ evt.arg = entry->arg;
419+
420+ return snd_mbf(connector->evtmbf, (VP)&evt, sizeof(http_connector_event), T_FOREVER);
421+}
422+
423+LOCAL W http_connector_searchwaiting(http_connector_t *connector)
424+{
425+ W i, len, err;
426+ http_reqentry_t *entry;
427+
428+ len = http_reqdict_length(connector->dict);
429+ for (i = 0; i < len ; i++) {
430+ entry = http_reqdict_getentrybyindex(connector->dict, i);
431+ if (entry->status == WAITING_ENDPOINT) {
432+ /* TODO: end point search */
433+ /* TODO: end point status change: HOLDED and sending */
434+ http_reqentry_attachendpoint(entry);
435+ err = http_connector_sendsendmessage(connector, entry);
436+ if (err < 0) {
437+ http_reqentry_detachendpoint(entry);
438+ }
439+ }
440+ }
441+
442+ return 0;
443+}
444+
445+LOCAL W http_connector_sendreceivemessage(http_connector_t *connector, http_reqentry_t *entry)
446+{
447+ volatile http_connector_event evt;
448+ http_responsereceiving_t *rcv;
449+
450+ rcv = http_ctxbuf_allocatereceive(&connector->ctxbuf, entry);
451+ if (rcv == NULL) {
452+ return ER_NONE;
453+ }
454+
455+ evt.type = HTTP_CONNECTOR_EVENTTYPE_RECEIVE;
456+ evt.ctx.response = rcv;
457+ evt.arg = entry->arg;
458+
459+ return snd_mbf(connector->evtmbf, (VP)&evt, sizeof(http_connector_event), T_FOREVER);
460+}
461+
462+LOCAL W http_connector_waitreceiving(http_connector_t *connector)
463+{
464+ W i, len, err;
465+ http_reqentry_t *entry;
466+
467+ len = http_reqdict_length(connector->dict);
468+ for (i = 0; i < len ; i++) {
469+ entry = http_reqdict_getentrybyindex(connector->dict, i);
470+ if (entry->status == RECEIVING) {
471+ /* TODO: end point status change: readinging */
472+ /* TODO: select() for end point */
473+ err = http_connector_sendreceivemessage(connector, entry);
474+ if (err < 0) {
475+ /* TODO */
476+ }
477+ }
478+ }
479+
480+ return 0;
481+}
482+
483+EXPORT W http_connector_waitconnection(http_connector_t *connector, TMOUT tmout)
484+{
485+ W err;
486+
487+ /**/
488+ http_connector_collect(connector);
489+
490+ err = http_connector_searchwaiting(connector);
491+ if (err < 0) {
492+ return err;
493+ }
494+
495+ err = http_connector_waitreceiving(connector);
496+ if (err < 0) {
497+ return err;
498+ }
499+
500+ return 0;
501+}
502+
503+EXPORT W http_connector_getevent(http_connector_t *connector, http_connector_event *event)
504+{
505+ return rcv_mbf(connector->evtmbf, event, T_NOWAIT);
506+}
507+
508+EXPORT http_connector_t* http_connector_new()
509+{
510+ http_connector_t *connector;
511+ W err;
512+
513+ connector = (http_connector_t*)malloc(sizeof(http_connector_t));
514+ if (connector == NULL) {
515+ return NULL;
516+ }
517+ connector->dict = http_reqdict_new(10/*tmp*/);
518+ if (connector->dict == NULL) {
519+ goto error_http_reqdict;
520+ return NULL;
521+ }
522+ err = http_ctxbuf_initialize(&connector->ctxbuf, 10/*tmp*/);
523+ if (err < 0) {
524+ goto error_http_ctxbuf;
525+ }
526+ connector->reqmbf = cre_mbf(0, 0, DELEXIT);
527+ if (connector->reqmbf < 0) {
528+ goto error_reqmbf;
529+ }
530+ connector->evtmbf = cre_mbf(sizeof(http_connector_event)*10, sizeof(http_connector_event), DELEXIT);
531+ if (connector->evtmbf < 0) {
532+ goto error_evtmbf;
533+ }
534+
535+ return connector;
536+
537+ del_mbf(connector->evtmbf);
538+error_evtmbf:
539+ del_mbf(connector->reqmbf);
540+error_reqmbf:
541+ http_reqdict_delete(connector->dict);
542+error_http_ctxbuf:
543+ free(connector);
544+error_http_reqdict:
545+ return NULL;
546+}
547+
548+EXPORT VOID http_connector_delete(http_connector_t *connector)
549+{
550+ del_mbf(connector->evtmbf);
551+ del_mbf(connector->reqmbf);
552+ http_ctxbuf_finalize(&connector->ctxbuf);
553+ http_reqdict_delete(connector->dict);
554+ free(connector);
555+}
--- bchanf/trunk/src/http/http_connection.h (revision 346)
+++ bchanf/trunk/src/http/http_connection.h (revision 347)
@@ -0,0 +1,94 @@
1+/*
2+ * http_connection.h
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+/* Vendor name: */
28+/* Functionality name: http */
29+/* Detail name: connector */
30+
31+#include <basic.h>
32+#include <btron/taskcomm.h>
33+
34+#ifndef __HTTP_CONNECTOR_H__
35+#define __HTTP_CONNECTOR_H__
36+
37+/* Functionality name: http */
38+/* Detail name: requestsending */
39+typedef struct http_requestsending_t_ http_requestsending_t;
40+
41+IMPORT W http_requestsending_sendheader(http_requestsending_t *request, UB *p, W len);
42+IMPORT W http_requestsending_headerend(http_requestsending_t *request);
43+IMPORT W http_requestsending_sendmessagebody(http_requestsending_t *request, UB *p, W len);
44+IMPORT W http_requestsending_messageend(http_requestsending_t *request);
45+
46+/* Functionality name: http */
47+/* Detail name: responsereceiving */
48+/* Data structure identifier: result */
49+struct http_responsereceiving_result_ {
50+ enum {
51+ HTTP_RESPONSERECEIVING_RESULTTYPE_HEADER,
52+ HTTP_RESPONSERECEIVING_RESULTTYPE_HEADER_END,
53+ HTTP_RESPONSERECEIVING_RESULTTYPE_MESSAGEBODY,
54+ HTTP_RESPONSERECEIVING_RESULTTYPE_MESSAGEBODY_END,
55+ } type;
56+ UB *data;
57+ W len;
58+};
59+typedef struct http_responsereceiving_result_ http_responsereceiving_result;
60+
61+/* Functionality name: http */
62+/* Detail name: responsereceiving */
63+typedef struct http_responsereceiving_t_ http_responsereceiving_t;
64+
65+IMPORT W http_responsereceiving_getmessage(http_responsereceiving_t *response, http_responsereceiving_result *result);
66+IMPORT W http_responsereceiving_messageend(http_responsereceiving_t *response);
67+
68+/* Functionality name: http */
69+/* Detail name: connector */
70+/* Data structure identifier: event */
71+struct http_connector_event_ {
72+ enum {
73+ HTTP_CONNECTOR_EVENTTYPE_SEND,
74+ HTTP_CONNECTOR_EVENTTYPE_RECEIVE,
75+ } type;
76+ union {
77+ http_requestsending_t *request;
78+ http_responsereceiving_t *response;
79+ } ctx;
80+ VP arg;
81+};
82+typedef struct http_connector_event_ http_connector_event;
83+
84+/* Functionality name: http */
85+/* Detail name: connector */
86+typedef struct http_connector_t_ http_connector_t;
87+
88+IMPORT http_connector_t* http_connector_new();
89+IMPORT VOID http_connector_delete(http_connector_t *connector);
90+IMPORT W http_connector_request(http_connector_t *connector, UB *host, W host_len, UH port, UB *path, W path_len, VP arg);
91+IMPORT W http_connector_waitconnection(http_connector_t *connector, TMOUT tmout);
92+IMPORT W http_connector_getevent(http_connector_t *connector, http_connector_event *event);
93+
94+#endif
Show on old repository browser