• R/O
  • SSH
  • HTTPS

pluto: Commit


Commit MetaInfo

Revision37 (tree)
Time2008-01-29 00:22:30
Authorhikarin

Log Message

Rewrote almost of pluto.c and pluto.h
Implemented changing client's uid and tag(subchannel).
Implemented publishing multicast
(This can publish to another server when the client requested with PUT).

Change Summary

Incremental Difference

--- trunk/pluto.c (revision 36)
+++ trunk/pluto.c (revision 37)
@@ -104,17 +104,20 @@
104104 }
105105
106106 apr_socket_t *listen;
107- apr_pollset_t *pollset;
108107 mei_server_t *server = apr_pcalloc(mp, sizeof(mei_server_t));
109108 server->pool = mp;
110109 server->config = config;
110+ server->clients = apr_hash_make(mp);
111111 server->executings = apr_hash_make(mp);
112112 server->uids = apr_hash_make(mp);
113113 server->tags = apr_hash_make(mp);
114+
115+ mei_server_create_listen_socket(server, &listen, mp);
116+ server->socket = listen;
114117 mei_server_initialize_acl(server);
115118 mei_server_initialize_channels(server);
116119
117- apr_pollset_create(&pollset,
120+ apr_pollset_create(&server->pollset,
118121 (apr_uint32_t) apr_atoi64(mei_config_get
119122 (server->config,
120123 "pluto.server.pollset.number",
@@ -122,24 +125,21 @@
122125 apr_pollfd_t pfd = { mp, APR_POLL_SOCKET, APR_POLLIN, 0, {NULL}
123126 , NULL
124127 };
125- mei_server_create_listen_socket(server, &listen, mp);
126128 pfd.desc.s = listen;
127- apr_pollset_add(pollset, &pfd);
129+ apr_pollset_add(server->pollset, &pfd);
128130 apr_time_t timeout = apr_atoi64(mei_config_get(server->config,
129131 "pluto.server.pollset.timeout",
130132 "30")) * APR_USEC_PER_SEC;
131133
132- apr_int32_t active;
133- const apr_pollfd_t *ret_pfd;
134-
135134 while (is_pluto_alive) {
136- apr_status_t rv;
137- rv = apr_pollset_poll(pollset, timeout, &active, &ret_pfd);
138- if (rv == APR_SUCCESS) {
135+ const apr_pollfd_t *ret_pfd;
136+ apr_int32_t active;
137+ if (apr_pollset_poll(server->pollset, timeout, &active, &ret_pfd) ==
138+ APR_SUCCESS) {
139139 int i;
140140 for (i = 0; i < active; i++) {
141141 if (ret_pfd[i].desc.s == listen) {
142- mei_server_accept_client(server, pollset, listen);
142+ mei_server_accept_client(server, listen);
143143 }
144144 else {
145145 mei_client_t *client = ret_pfd[i].client_data;
@@ -149,7 +149,7 @@
149149 }
150150 }
151151
152- apr_pollset_destroy(pollset);
152+ apr_pollset_destroy(server->pollset);
153153 apr_pool_destroy(mp);
154154 mei_server_finalize();
155155
@@ -221,11 +221,11 @@
221221 }
222222
223223 static const apr_array_header_t *mei_config_get_all(mei_config_t * config,
224- const char *key)
224+ const char *key,
225+ apr_pool_t * pool)
225226 {
226- apr_array_header_t *values =
227- apr_array_make(apr_table_elts(config)->pool, 32,
228- sizeof(const char *));
227+ apr_array_header_t *values = apr_array_make(pool, 32,
228+ sizeof(const char *));
229229 apr_table_do(mei_config_add_value_to_array, values, config, key, NULL);
230230 return values;
231231 }
@@ -255,7 +255,7 @@
255255 (apr_port_t) apr_atoi64(mei_config_get
256256 (server->config,
257257 "pluto.server.port", "8088")),
258- 0, mp));
258+ (apr_int32_t) 0, mp));
259259
260260 MEI_TRY_OR_THROW(apr_socket_create
261261 (sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, mp));
@@ -281,44 +281,52 @@
281281 }
282282
283283 static void mei_server_accept_client(mei_server_t * server,
284- apr_pollset_t * pollset,
285284 apr_socket_t * listen)
286285 {
287286 apr_socket_t *ns;
288- apr_status_t rv;
289- apr_pool_t *client_pool;
287+ apr_status_t rv = apr_socket_accept(&ns, listen, server->pool);
290288
291- MEI_TRY_OR_THROW(apr_pool_create(&client_pool, server->pool));
292- rv = apr_socket_accept(&ns, listen, client_pool);
293-
294289 if (rv == APR_SUCCESS) {
295- mei_client_t *client = apr_pcalloc(client_pool, sizeof(mei_client_t));
296- apr_pollfd_t pfd =
297- { server->pool, APR_POLL_SOCKET, APR_POLLIN, 0, {NULL}
298- , client
299- };
300- pfd.desc.s = ns;
290+ mei_client_t *client;
291+ apr_os_sock_t fd;
292+ apr_os_sock_get(&fd, ns);
293+ apr_socket_opt_set(ns, APR_SO_NONBLOCK, 1);
294+ apr_socket_timeout_set(ns, (apr_interval_time_t) 0);
295+ const char *sfd = apr_itoa(server->pool, fd);
301296
297+ if ((client =
298+ apr_hash_get(server->clients, sfd,
299+ APR_HASH_KEY_STRING)) == NULL) {
300+ apr_pool_t *client_pool;
301+ MEI_TRY_OR_THROW(apr_pool_create(&client_pool, server->pool));
302+
303+ client = apr_pcalloc(client_pool, sizeof(mei_client_t));
304+ client->pool = client_pool;
305+ client->connected_at = apr_time_now();
306+ client->event.committed_at = 0;
307+ client->event.is_waiting = FALSE;
308+ client->event.is_unbound = FALSE;
309+ client->request.method = MEI_REQUEST_IS_UNKNOWN;
310+ client->request.header = apr_table_make(client_pool, 32);
311+ client->request.param = apr_table_make(client_pool, 32);
312+ client->request.is_flash = 0;
313+ client->response.close_connection = TRUE;
314+ client->response.content_type = "text/html";
315+ client->response.status = 400;
316+ apr_hash_set(server->clients, sfd, APR_HASH_KEY_STRING, client);
317+ }
318+
302319 client->event_callback = mei_client_process_request;
303320 client->parent = server;
304- client->pool = client_pool;
305321 client->socket = ns;
306- client->pollset = pollset;
307- client->connected_at = apr_time_now();
308- client->event.committed_at = 0;
309- client->event.is_waiting = FALSE;
310- client->event.is_unbound = FALSE;
311- client->request.header = apr_hash_make(client_pool);
312- client->request.param = apr_hash_make(client_pool);
313- client->request.is_flash = 0;
314- client->response.close_connection = TRUE;
315- client->response.content_type = "text/html";
316- client->response.status = 400;
322+ client->fd = fd;
317323
318- apr_socket_opt_set(ns, APR_SO_NONBLOCK, 1);
319- apr_socket_timeout_set(ns, (apr_interval_time_t) 0);
320-
321- apr_pollset_add(pollset, &pfd);
324+ apr_pollfd_t pfd =
325+ { client->pool, APR_POLL_SOCKET, APR_POLLIN, 0, {NULL}
326+ , client
327+ };
328+ pfd.desc.s = client->socket;
329+ apr_pollset_add(client->parent->pollset, &pfd);
322330 }
323331 }
324332
@@ -325,10 +333,6 @@
325333 static const char *mei_server_status_code_to_string(int code)
326334 {
327335 switch (code) {
328- case 413:
329- return "HTTP/1.1 413 Request Entity Too Large";
330- case 411:
331- return "HTTP/1.1 411 Length Required";
332336 case 404:
333337 return "HTTP/1.1 404 Not Found";
334338 case 403:
@@ -335,8 +339,6 @@
335339 return "HTTP/1.1 403 Forbidden";
336340 case 400:
337341 return "HTTP/1.1 400 Bad Request";
338- case 201:
339- return "HTTP/1.1 201 Created";
340342 default:
341343 return "HTTP/1.1 200 OK";
342344 }
@@ -345,7 +347,8 @@
345347 static void mei_server_initialize_acl(mei_server_t * server)
346348 {
347349 const apr_array_header_t *values =
348- mei_config_get_all(server->config, "pluto.server.acl.put");
350+ mei_config_get_all(server->config, "pluto.server.acl.put",
351+ server->pool);
349352 int i;
350353
351354 server->acl = apr_pcalloc(server->pool, sizeof(mei_server_acl_t));
@@ -356,6 +359,7 @@
356359 char *mask, *ip =
357360 apr_pstrdup(server->pool, ((const char **) values->elts)[i]);
358361 ip = apr_strtok(ip, "/", &mask);
362+
359363 if (apr_ipsubnet_create(&subnet, ip, mask, server->pool) ==
360364 APR_SUCCESS) {
361365 mei_server_acl_entry_t *ent =
@@ -394,11 +398,13 @@
394398
395399 static void mei_server_initialize_channels(mei_server_t * server)
396400 {
401+ apr_hash_t *channels = apr_hash_make(server->pool);
397402 const apr_array_header_t *values =
398- mei_config_get_all(server->config, "pluto.server.channel");
403+ mei_config_get_all(server->config, "pluto.server.channel",
404+ apr_hash_pool_get(channels));
399405 int i;
400406
401- server->channels = apr_hash_make(server->pool);
407+ server->channels = channels;
402408 for (i = 0; i < values->nelts; i++) {
403409 const char *path = ((const char **) values->elts)[i];
404410 mei_channel_create(server, path);
@@ -405,6 +411,97 @@
405411 }
406412 }
407413
414+static void mei_server_multicast(mei_server_t * server, mei_client_t * client,
415+ const char *method, const char *body)
416+{
417+ MEI_START_ENTRY_POINT();
418+
419+ if (apr_table_get(client->request.header, "X-Pluto-Multicast") != NULL) {
420+ D("X-Pluto-Multicast was received, and doesn't multicast\n");
421+ return;
422+ }
423+
424+ apr_pool_t *pool;
425+ apr_sockaddr_t *self_sa;
426+ apr_pool_create(&pool, server->pool);
427+ apr_socket_addr_get(&self_sa, APR_LOCAL, server->socket);
428+
429+ const apr_array_header_t *values =
430+ mei_config_get_all(server->config, "pluto.server.multicast", pool);
431+ int i;
432+
433+ for (i = 0; i < values->nelts; i++) {
434+ char *sp, *ip = apr_pstrdup(pool, ((const char **) values->elts)[i]);
435+ ip = apr_strtok(ip, ":", &sp);
436+
437+ if (sp != NULL) {
438+ apr_sockaddr_t *sa;
439+ apr_socket_t *s;
440+ apr_port_t port = (apr_port_t) apr_atoi64(sp);
441+ apr_status_t rv;
442+
443+ if ((rv =
444+ apr_sockaddr_info_get(&sa, ip, APR_INET, port,
445+ (apr_int32_t) 0,
446+ pool)) != APR_SUCCESS) {
447+ MEI_RUNTIME_ERROR(rv);
448+ continue;
449+ }
450+ if (apr_sockaddr_equal(self_sa, sa) && self_sa->port == sa->port) {
451+ D("tried casting myself, skipping...\n");
452+ continue;
453+ }
454+ if ((rv = apr_socket_create
455+ (&s, sa->family, SOCK_STREAM, APR_PROTO_TCP,
456+ pool)) != APR_SUCCESS) {
457+ MEI_RUNTIME_ERROR(rv);
458+ continue;
459+ }
460+ apr_socket_opt_set(s, APR_SO_NONBLOCK, 1);
461+ apr_socket_timeout_set(s, (apr_interval_time_t) 3);
462+
463+ if ((rv = apr_socket_connect(s, sa)) != APR_SUCCESS) {
464+ MEI_RUNTIME_ERROR(rv);
465+ continue;
466+ }
467+ apr_socket_opt_set(s, APR_SO_NONBLOCK, 1);
468+ apr_socket_timeout_set(s, (apr_interval_time_t) 3);
469+
470+ if (body == NULL) {
471+ body = "";
472+ }
473+ const char *request = apr_psprintf(pool,
474+ "%s %s HTTP/1.1" MEI_CRLF
475+ "Content-Length: %"
476+ APR_SIZE_T_FMT MEI_CRLF
477+ "X-Pluto-Multicast: true"
478+ MEI_CRLF MEI_CRLF "%s",
479+ method, client->request.path,
480+ strlen(body), body);
481+ apr_size_t len = strlen(request);
482+
483+ if ((rv = apr_socket_send(s, request, &len)) != APR_SUCCESS) {
484+ MEI_RUNTIME_ERROR(rv);
485+ continue;
486+ }
487+
488+ char response[1];
489+ len = 1;
490+ rv = apr_socket_recv(s, response, &len);
491+ if (!APR_STATUS_IS_EAGAIN(rv) && (APR_STATUS_IS_TIMEUP(rv)
492+ || APR_STATUS_IS_EOF(rv)
493+ || len == 0)) {
494+ MEI_RUNTIME_ERROR(rv);
495+ continue;
496+ }
497+
498+ apr_socket_close(s);
499+ }
500+ }
501+
502+ apr_pool_destroy(pool);
503+}
504+
408505 static void mei_server_log(mei_server_t * server, const char *content)
409506 {
410507 if (mei_config_get(server->config, "pluto.server.log.enabled", NULL) !=
@@ -442,11 +539,12 @@
442539 {
443540 char *body = apr_pstrdup(client->pool, "");
444541 apr_size_t body_length = 0;
542+ apr_socket_t *socket = client->socket;
445543
446544 while (1) {
447545 char buf[BUFSIZE];
448546 apr_size_t len = sizeof(buf) - 1;
449- apr_status_t rv = apr_socket_recv(client->socket, buf, &len);
547+ apr_status_t rv = apr_socket_recv(socket, buf, &len);
450548
451549 if (APR_STATUS_IS_EAGAIN(rv)) {
452550
@@ -455,10 +553,11 @@
455553 break;
456554 }
457555 if (strncmp(body, "<policy-file-request/>", 22) == 0) {
458- const char *domain = mei_config_get(client->parent->config,
556+ mei_config_t *config = client->parent->config;
557+ const char *domain = mei_config_get(config,
459558 "pluto.client.flash.access.domain",
460559 "*");
461- const char *ports = mei_config_get(client->parent->config,
560+ const char *ports = mei_config_get(config,
462561 "pluto.client.flash.access.ports",
463562 "*");
464563 mei_client_send_content_for_flash(client,
@@ -474,7 +573,6 @@
474573 ports), TRUE);
475574 break;
476575 }
477- D("\n/*\n%s\n*/\n", body);
478576
479577 char *header = body;
480578 if ((body = strstr(header, MEI_CRLF MEI_CRLF)) != NULL) {
@@ -482,15 +580,39 @@
482580 /* strlen("\r\n\r\n") == 4 */
483581 body += 4;
484582 }
485- else {
486- body = apr_pstrdup(client->pool, "");
583+
584+ const char *path = client->request.path;
585+ if (client->request.method == MEI_REQUEST_IS_UNKNOWN) {
586+ char **tokens;
587+ char *request_first_line =
588+ apr_strtok(NULL, MEI_CRLF, &header);
589+ apr_tokenize_to_argv(request_first_line, &tokens,
590+ client->pool);
591+
592+ const char *method = tokens[0];
593+ const char *protocol = tokens[2];
594+ client->request.path = path = tokens[1];
595+ D("/*\n * %s\n */\n", request_first_line);
596+ if (sizeof(tokens) != 4 || method == NULL
597+ || path == NULL || protocol == NULL
598+ || strncmp(protocol, "HTTP/1.1", 8) != 0) {
599+ client->response.close_connection = TRUE;
600+ mei_client_send_content(client, 400, "");
601+ }
602+ else if (strncmp(method, "GET", 3) == 0) {
603+ client->request.method = MEI_REQUEST_IS_GET;
604+ }
605+ else if (strncmp(method, "POST", 4) == 0) {
606+ client->request.method = MEI_REQUEST_IS_POST;
607+ }
608+ else if (strncmp(method, "PUT", 3) == 0) {
609+ client->request.method = MEI_REQUEST_IS_PUT;
610+ }
611+ else if (strncmp(method, "DELETE", 6) == 0) {
612+ client->request.method = MEI_REQUEST_IS_DELETE;
613+ }
487614 }
488615
489- char **tokens;
490- char *request_first_line = apr_strtok(NULL, MEI_CRLF, &header);
491- D("/*\n * %s\n */\n", request_first_line);
492- apr_tokenize_to_argv(request_first_line, &tokens, client->pool);
493-
494616 char *header_key;
495617 while ((header_key = apr_strtok(NULL, MEI_CRLF, &header)) != NULL) {
496618 char *header_value;
@@ -502,86 +624,131 @@
502624 else {
503625 header_value = apr_pstrdup(client->pool, "");
504626 }
505- apr_hash_set(client->request.header, header_key,
506- APR_HASH_KEY_STRING, header_value);
627+ apr_table_setn(client->request.header, header_key,
628+ header_value);
507629 }
508630
509- const char *method = tokens[0];
510- const char *path = tokens[1];
511- const char *protocol = tokens[2];
512- if (sizeof(tokens) != 4 || method == NULL
513- || path == NULL || protocol == NULL
514- || strncmp(protocol, "HTTP/1.1", 8) != 0) {
515- client->response.close_connection = TRUE;
516- mei_client_send_content(client, 400, "");
517- }
518- else if (strncmp(method, "GET", 3) == 0) {
631+ if (client->request.method == MEI_REQUEST_IS_GET) {
519632 mei_request_parse_query_string(client, path);
520633 mei_client_bind_to_server(client);
521634 }
522- else if (strncmp(method, "POST", 4) == 0) {
635+ else if (client->request.method == MEI_REQUEST_IS_POST) {
523636 mei_request_parse_query_string(client, path);
524637 const char *ct =
525- apr_hash_get(client->request.header, "Content-Type",
526- APR_HASH_KEY_STRING);
638+ apr_table_get(client->request.header, "Content-Type");
527639
528640 if (ct != NULL
529641 /* strlen("application/x-www-form-urlencoded") == 33 */
530642 && strncmp(ct, "application/x-www-form-urlencoded",
531643 33) == 0) {
532- const char *cl = apr_hash_get
533- (client->request.header, "Content-Length",
534- APR_HASH_KEY_STRING);
535- if (cl == NULL) {
536- mei_client_send_content(client, 411, "");
644+ const char *cl = apr_table_get
645+ (client->request.header, "Content-Length");
646+ if (cl == NULL || body_length <= apr_atoi64(cl)) {
537647 break;
538648 }
539- else if (body_length <= apr_atoi64(cl)) {
540- mei_client_send_content(client, 413, "");
541- break;
542- }
543- else {
544- mei_request_set_parameters(client, body);
545- }
649+ mei_request_set_parameters(client, body);
650+ mei_client_bind_to_server(client);
546651 }
547652
548- mei_client_bind_to_server(client);
549653 }
550- else if (strncmp(method, "PUT", 3) == 0) {
654+ else if (client->request.method == MEI_REQUEST_IS_PUT) {
551655 apr_sockaddr_t *sa;
552656 apr_socket_addr_get(&sa, APR_REMOTE, client->socket);
657+ mei_server_t *server = client->parent;
553658
554- if (mei_server_check_acl(client->parent, sa)) {
659+ if (mei_server_check_acl(server, sa)) {
555660 mei_request_parse_query_string(client, path);
556661 mei_event_param_t *event =
557662 apr_pcalloc(client->pool, sizeof(mei_event_param_t));
558663 mei_request_set_tags(client, &event->tag, "tag");
559664 event->id = mei_request_get_parameter(client, "id");
560- event->uid = mei_request_get_parameter(client, "uid");
561665 event->status = MEI_EVENT_STATUS_UPDATE;
666+ const char *uid = event->uid =
667+ mei_request_get_parameter(client, "uid");
562668
669+ const char *sig =
670+ mei_request_get_parameter(client, "sig");
563671 const char *channel_path =
564672 apr_pstrdup(client->pool, client->request.path);
565- mei_channel_create(client->parent, channel_path);
673+
674+ client->signature = apr_pstrndup(client->pool, "", 1);
675+ mei_channel_create(server, channel_path);
566676 mei_channel_t *channel =
567- mei_channel_get(client->parent, channel_path);
677+ mei_channel_get(server, channel_path);
678+
568679 if (event->id != NULL) {
569- mei_channel_transmit(channel, event);
680+ mei_channel_transmit(server, channel, client, event);
570681 }
682+ else if (sig != NULL) {
683+ const char *new_sig = apr_pstrdup(server->pool, sig);
684+ int tag_count = event->tag->nelts;
685+ if (uid != NULL) {
686+ apr_hash_set(server->uids, new_sig,
687+ APR_HASH_KEY_STRING,
688+ apr_pstrdup(apr_hash_pool_get
689+ (server->uids), uid));
690+ }
691+ if (tag_count > 0) {
692+ int i = 0;
693+ apr_array_header_t *new_tag =
694+ apr_array_make(apr_hash_pool_get
695+ (server->tags), 32,
696+ sizeof(const char *));
697+ for (; i < tag_count; i++) {
698+ *(const char **) apr_array_push(new_tag)
699+ = apr_pstrdup(new_tag->pool,
700+ ((const char **) event->
701+ tag->elts)[i]);
702+ }
703+ apr_hash_set(server->tags, new_sig,
704+ APR_HASH_KEY_STRING, new_tag);
705+ }
571706
572- mei_client_send_content(client, 201, "");
707+ const apr_array_header_t *ta =
708+ apr_table_elts(channel);
709+ const apr_table_entry_t *te =
710+ (const apr_table_entry_t *) ta->elts;
711+ int i = 0;
712+
713+ for (; i < ta->nelts; i++) {
714+ const char *s = te[i].val;
715+ if (strcmp(s, sig) == 0) {
716+ mei_client_t *c =
717+ apr_hash_get(server->clients, te[i].key,
718+ APR_HASH_KEY_STRING);
719+ if (c != NULL) {
720+ if (uid != NULL) {
721+ c->request.uid =
722+ apr_pstrdup(client->pool, uid);
723+ }
724+ if (tag_count > 0) {
725+ c->request.tag =
726+ apr_array_copy(client->pool,
727+ event->tag);
728+ }
729+ }
730+ }
731+ }
732+
733+ }
734+
735+ mei_server_multicast(server, client, "PUT", body);
736+ mei_client_send_content(client, 200, "");
573737 }
574738 else {
575739 mei_client_send_content(client, 403, "");
576740 }
577741 }
578- else if (strncmp(method, "DELETE", 6) == 0) {
742+ else if (client->request.method == MEI_REQUEST_IS_DELETE) {
579743 apr_sockaddr_t *sa;
580744 apr_socket_addr_get(&sa, APR_REMOTE, client->socket);
745+ mei_server_t *server = client->parent;
581746
582- if (mei_server_check_acl(client->parent, sa)) {
747+ if (mei_server_check_acl(server, sa)) {
583748 mei_request_parse_query_string(client, path);
584- mei_channel_remove(client->parent, path);
749+ mei_channel_remove(server, path, client);
750+
751+ mei_server_multicast(server, client, "DELETE", body);
585752 mei_client_send_content(client, 200, "");
586753 }
587754 else {
@@ -594,8 +761,7 @@
594761 break;
595762 }
596763 else if (APR_STATUS_IS_EOF(rv) || len == 0) {
597- mei_client_remove_poll(client);
598- mei_client_close_connection(client);
764+ mei_client_unbind_from_server(client);
599765 break;
600766 }
601767 else {
@@ -613,11 +779,12 @@
613779 {
614780 MEI_START_ENTRY_POINT();
615781
782+ client->response.status = code;
616783 client->response.close_connection = TRUE;
617- client->response.status = code;
784+
618785 mei_client_set_response(client, content);
619- mei_client_remove_poll(client);
620786 mei_client_process_response(client, strlen(client->response.buffer));
787+ mei_client_close_connection(client);
621788 }
622789
623790 static void mei_client_send_content_for_flash(mei_client_t * client,
@@ -626,20 +793,15 @@
626793 {
627794 MEI_START_ENTRY_POINT();
628795
629- client->response.buffer = content;
630- client->response.close_connection = close_connection;
631- mei_client_remove_poll(client);
632- mei_client_process_response(client, strlen(content) + 1);
633-}
634-
635-static void mei_client_remove_poll(mei_client_t * client)
636-{
637796 apr_pollfd_t pfd = { client->pool, APR_POLL_SOCKET, APR_POLLIN, 0, {NULL}
638797 , client
639798 };
799+ pfd.desc.s = client->socket;
800+ apr_pollset_remove(client->parent->pollset, &pfd);
640801
641- pfd.desc.s = client->socket;
642- apr_pollset_remove(client->pollset, &pfd);
802+ client->response.buffer = content;
803+ client->response.close_connection = close_connection;
804+ mei_client_process_response(client, strlen(content) + 1);
643805 }
644806
645807 static void mei_client_bind_to_server(mei_client_t * client)
@@ -646,30 +808,27 @@
646808 {
647809 MEI_START_ENTRY_POINT();
648810
811+ mei_server_t *server = client->parent;
649812 const char *type = mei_request_get_parameter(client, "type");
650- apr_uint64_t maxlen = apr_atoi64(mei_config_get(client->parent->config,
813+ apr_uint64_t maxlen = apr_atoi64(mei_config_get(server->config,
651814 "pluto.client.signature.maxlen",
652815 "255"));
816+ const char *signature = client->signature =
817+ mei_request_get_parameter(client, "sig");
818+ const char *path = client->request.path;
819+ int is_flash = FALSE;
653820
654- if (client->signature == NULL) {
655- client->signature = mei_request_get_parameter(client, "sig");
821+ if (signature == NULL || strlen(signature) > maxlen) {
822+ return;
656823 }
657824 if (type != NULL) {
658- client->request.is_flash = strncmp(type, "flash", 5) == 0;
825+ is_flash = client->request.is_flash = strncmp(type, "flash", 5) == 0;
659826 }
660827
661- if (!mei_channel_exists(client->parent, client->request.path)) {
662- client->request.is_flash ? mei_client_send_content_for_flash(client,
663- "404\\0",
664- TRUE)
828+ if (!mei_channel_exists(server, path)) {
829+ is_flash ? mei_client_send_content_for_flash(client, "404\\0", TRUE)
665830 : mei_client_send_content(client, 404, "");
666831 }
667- else if (client->signature == NULL || strlen(client->signature) > maxlen) {
668- client->request.is_flash ? mei_client_send_content_for_flash(client,
669- "400\\0",
670- TRUE)
671- : mei_client_send_content(client, 400, "");
672- }
673832 else if (type == NULL) {
674833 mei_request_send_iframe_connection(client);
675834 }
@@ -676,20 +835,18 @@
676835 else {
677836 const char *phase = mei_request_get_parameter(client, "phase");
678837 client->event.executing =
679- apr_hash_get(client->parent->executings, client->signature,
680- APR_HASH_KEY_STRING);
838+ apr_hash_get(server->executings, signature, APR_HASH_KEY_STRING);
681839
682840 if (client->event.executing == NULL) {
683841 apr_pool_t *pool;
684- apr_pool_create(&pool, client->parent->pool);
842+ apr_pool_create(&pool, server->pool);
685843 client->event.executing = apr_table_make(pool, 8);
686- apr_hash_set(client->parent->executings, client->signature,
844+ apr_hash_set(server->executings, signature,
687845 APR_HASH_KEY_STRING, client->event.executing);
688846 }
689847
690848 client->request.uid =
691- apr_hash_get(client->parent->uids, client->signature,
692- APR_HASH_KEY_STRING);
849+ apr_hash_get(server->uids, signature, APR_HASH_KEY_STRING);
693850 if (client->request.uid == NULL) {
694851 client->request.uid =
695852 apr_pstrdup(client->pool,
@@ -696,8 +853,7 @@
696853 mei_request_get_parameter(client, "uid"));
697854 }
698855 client->request.tag =
699- apr_hash_get(client->parent->tags, client->signature,
700- APR_HASH_KEY_STRING);
856+ apr_hash_get(server->tags, signature, APR_HASH_KEY_STRING);
701857 if (client->request.tag == NULL) {
702858 mei_request_set_tags(client, &client->request.tag, "tag");
703859 }
@@ -712,26 +868,24 @@
712868 client->response.close_connection = FALSE;
713869
714870 if (phase == NULL || strncmp(phase, "reconnect", 9) != 0) {
715- if (client->request.is_flash) {
871+ if (is_flash) {
716872 mei_request_send_flash_connection(client, event);
717873 }
718- mei_channel_notify(client->parent, client->request.path, event);
719- mei_server_log(client->parent,
874+ mei_channel_notify(server, path, client, event);
875+ mei_server_log(server,
720876 apr_psprintf(client->pool, "Connected: %s\n",
721- client->signature));
877+ signature));
722878 }
723879
724- mei_channel_join(client->parent, client->request.path, client);
725- mei_client_remove_poll(client);
726- mei_server_log(client->parent,
880+ mei_channel_join(server, path, client);
881+ mei_server_log(server,
727882 apr_psprintf(client->pool, "Wait for %s:%s\n",
728- client->request.path, client->signature));
883+ path, signature));
729884
730885 if (mei_client_commit(client, event)) {
731- mei_server_log(client->parent,
886+ mei_server_log(server,
732887 apr_psprintf(client->pool, "Flushed %s:%s\n",
733- client->request.path,
734- client->signature));
888+ path, signature));
735889 }
736890 }
737891 }
@@ -754,7 +908,7 @@
754908 apr_pcalloc(client->pool, sizeof(mei_event_param_t));
755909 event->status = MEI_EVENT_STATUS_LEAVE;
756910
757- mei_channel_notify(server, path, event);
911+ mei_channel_notify(server, path, client, event);
758912 }
759913 }
760914
@@ -773,10 +927,27 @@
773927 }
774928
775929 mei_server_log(server,
776- apr_psprintf(client->pool, "Disconnected %s\n",
777- signature));
930+ apr_psprintf(client->pool, "Disconnected %s[%d]\n",
931+ signature, client->fd));
932+ mei_client_close_connection(client);
933+}
934+
935+static void mei_client_close_connection(mei_client_t * client)
936+{
937+ MEI_START_ENTRY_POINT();
938+
939+ mei_server_t *server = client->parent;
940+ apr_pollfd_t pfd = { client->pool, APR_POLL_SOCKET, APR_POLLIN, 0, {NULL}
941+ , client
942+ };
943+ pfd.desc.s = client->socket;
944+ apr_pollset_remove(server->pollset, &pfd);
945+
946+ apr_hash_set(server->clients, apr_itoa(client->parent->pool, client->fd),
947+ APR_HASH_KEY_STRING, NULL);
948+ apr_socket_close(client->socket);
778949 apr_pool_destroy(client->pool);
779- client = NULL;
950+ memset(client, 0, sizeof(mei_client_t));
780951 }
781952
782953 static int mei_client_can_respond(mei_client_t * client,
@@ -790,11 +961,15 @@
790961 return FALSE;
791962 }
792963
964+ mei_server_t *server = client->parent;
965+ const char *signature = client->signature;
966+
793967 int is_matched = FALSE;
794- apr_array_header_t *event_tag = event->tag;
795- apr_array_header_t *client_tag = client->request.tag;
968+ const apr_array_header_t *event_tag = event->tag;
969+ const apr_array_header_t *client_tag = client->request.tag;
796970 int event_tag_count = event_tag != NULL ? event_tag->nelts : 0;
797971 int client_tag_count = client_tag != NULL ? client_tag->nelts : 0;
972+
798973 if (event_tag_count > 0 && client_tag_count > 0) {
799974 apr_size_t search_nelts, search_elt_size;
800975 int i, iterate_nelts;
@@ -815,9 +990,11 @@
815990 search_elt_size = client_tag->elt_size;
816991 }
817992 for (i = 0; i < iterate_nelts; i++) {
993+/*
818994 D("iterate[%d](%d): %s / search(%d): %s\n", i,
819995 iterate_nelts, ((const char **) iterate_elts)[i], search_nelts,
820996 ((const char **) search_elts)[i]);
997+*/
821998 if (bsearch
822999 (((const char **) iterate_elts)[i], search_elts, search_nelts,
8231000 search_elt_size, mei_util_bsearch_compare_string) != NULL) {
@@ -835,13 +1012,12 @@
8351012 }
8361013 else {
8371014 client->event.executing =
838- apr_hash_get(client->parent->executings, client->signature,
839- APR_HASH_KEY_STRING);
1015+ apr_hash_get(server->executings, signature, APR_HASH_KEY_STRING);
8401016 if (client->event.executing == NULL) {
8411017 apr_pool_t *pool;
842- apr_pool_create(&pool, client->parent->pool);
1018+ apr_pool_create(&pool, server->pool);
8431019 client->event.executing = apr_table_make(pool, 8);
844- apr_hash_set(client->parent->executings, client->signature,
1020+ apr_hash_set(server->executings, signature,
8451021 APR_HASH_KEY_STRING, client->event.executing);
8461022 }
8471023
@@ -877,12 +1053,13 @@
8771053 client->event.executing = NULL;
8781054 client->event.committed_at = apr_time_now();
8791055
880- apr_size_t length = 0;
8811056 if (client->request.is_flash) {
882- client->response.buffer = apr_pstrcat(client->pool,
883- client->response.publish_buffer,
884- "\\0", NULL);
885- length = strlen(client->response.publish_buffer) + 1;
1057+ mei_client_send_content_for_flash(client, apr_pstrcat(client->pool,
1058+ client->
1059+ response.
1060+ publish_buffer,
1061+ "\\0", NULL),
1062+ FALSE);
8861063 }
8871064 else {
8881065 if (mei_client_check_connection(client) == FALSE) {
@@ -891,15 +1068,10 @@
8911068
8921069 client->event.is_waiting = FALSE;
8931070 client->response.status = 200;
894- client->response.close_connection = TRUE;
8951071 client->response.content_type = "text/javascript";
896- mei_client_set_response(client, client->response.publish_buffer);
897- length = strlen(client->response.buffer);
1072+ mei_client_send_content(client, 200, client->response.publish_buffer);
8981073 }
8991074
900- client->response.publish_buffer = NULL;
901- mei_client_process_response(client, length);
902-
9031075 return TRUE;
9041076 }
9051077
@@ -1029,13 +1201,12 @@
10291201 apr_size_t length)
10301202 {
10311203 const char *data = client->response.buffer;
1204+ apr_socket_t *socket = client->socket;
10321205 apr_size_t remain = length;
10331206 apr_size_t sent = remain;
10341207
1035- apr_socket_send(client->socket, data, &sent);
1036- if (client->response.close_connection == TRUE) {
1037- mei_client_close_connection(client);
1038- }
1208+ apr_socket_send(socket, data, &sent);
1209+ client->request.method = MEI_REQUEST_IS_UNKNOWN;
10391210
10401211 return TRUE;
10411212 }
@@ -1046,11 +1217,12 @@
10461217
10471218 char buf[1];
10481219 apr_size_t len = 1;
1049- apr_status_t rv = apr_socket_recv(client->socket, buf, &len);
1220+ apr_socket_t *socket = client->socket;
1221+ apr_status_t rv = apr_socket_recv(socket, buf, &len);
10501222
10511223 if (!APR_STATUS_IS_EAGAIN(rv) && (APR_STATUS_IS_TIMEUP(rv)
10521224 || APR_STATUS_IS_EOF(rv) || len == 0)) {
1053- mei_client_unbind_from_server(client);
1225+ apr_socket_close(socket);
10541226 return FALSE;
10551227 }
10561228
@@ -1057,27 +1229,21 @@
10571229 return TRUE;
10581230 }
10591231
1060-static int mei_client_close_connection(mei_client_t * client)
1061-{
1062- if (client->socket != NULL) {
1063- apr_socket_close(client->socket);
1064- }
1065- return TRUE;
1066-}
1067-
10681232 /*
10691233 * MEI channel class
10701234 */
10711235 static void mei_channel_create(mei_server_t * server, const char *path)
10721236 {
1073- if (apr_hash_get(server->channels, path, APR_HASH_KEY_STRING) == NULL) {
1074- const char *channel_path = apr_pstrdup(server->pool, path);
1075- mei_channel_t *channel = apr_table_make(server->pool, 32);
1076- apr_hash_set(server->channels, channel_path, APR_HASH_KEY_STRING,
1077- channel);
1237+ apr_hash_t *channels = server->channels;
1238+ apr_pool_t *pool;
1239+ apr_pool_create(&pool, apr_hash_pool_get(channels));
1240+
1241+ if (apr_hash_get(channels, path, APR_HASH_KEY_STRING) == NULL) {
1242+ mei_channel_t *channel = apr_table_make(pool, 32);
1243+ const char *channel_path = apr_pstrdup(pool, path);
1244+ apr_hash_set(channels, channel_path, APR_HASH_KEY_STRING, channel);
10781245 mei_server_log(server,
1079- apr_psprintf(server->pool, "Channel opened: %s\n",
1080- path));
1246+ apr_psprintf(pool, "Channel opened: %s\n", path));
10811247 }
10821248 }
10831249
@@ -1101,16 +1267,11 @@
11011267 apr_hash_get(server->channels, path, APR_HASH_KEY_STRING);
11021268
11031269 if (channel != NULL && client->signature != NULL) {
1104- const char *signature =
1105- apr_pstrdup(apr_table_elts(channel)->pool, client->signature);
1270+ apr_pool_t *pool = apr_table_elts(channel)->pool;
1271+ const char *signature = apr_pstrdup(pool, client->signature);
1272+ const char *sfd = apr_itoa(pool, client->fd);
1273+ apr_table_setn(channel, sfd, signature);
11061274
1107- mei_client_t *used;
1108- if ((used =
1109- (mei_client_t *) apr_table_get(channel, signature)) != NULL) {
1110- apr_pool_destroy(used->pool);
1111- }
1112- apr_table_setn(channel, signature, (const char *) client);
1113-
11141275 return TRUE;
11151276 }
11161277 else {
@@ -1119,6 +1280,7 @@
11191280 }
11201281
11211282 static int mei_channel_notify(mei_server_t * server, const char *path,
1283+ mei_client_t * client,
11221284 mei_event_param_t * event)
11231285 {
11241286 MEI_START_ENTRY_POINT();
@@ -1131,7 +1293,7 @@
11311293 apr_psprintf(server->pool,
11321294 "pluto-charon-xhr-event-id-%" APR_TIME_T_FMT,
11331295 apr_time_now());
1134- mei_channel_transmit(channel, event);
1296+ mei_channel_transmit(server, channel, client, event);
11351297 return TRUE;
11361298 }
11371299 else {
@@ -1139,7 +1301,9 @@
11391301 }
11401302 }
11411303
1142-static void mei_channel_transmit(mei_channel_t * channel,
1304+static void mei_channel_transmit(mei_server_t * server,
1305+ mei_channel_t * channel,
1306+ mei_client_t * client,
11431307 mei_event_param_t * event)
11441308 {
11451309 MEI_START_ENTRY_POINT();
@@ -1153,24 +1317,24 @@
11531317 apr_hash_t *committed = apr_hash_make(tmp_pool);
11541318
11551319 while (i < ta->nelts) {
1156- const char *signature = te[i].key;
1157- mei_client_t *client = (mei_client_t *) te[i].val;
1320+ const char *sfd = te[i].key;
1321+ const char *signature = te[i].val;
1322+ apr_os_sock_t fd = (apr_os_sock_t) apr_atoi64(sfd);
1323+ mei_client_t *c =
1324+ apr_hash_get(server->clients, sfd, APR_HASH_KEY_STRING);
11581325
1159- if (client == NULL || client->parent == NULL) {
1160- apr_table_unset(channel, signature);
1161- i = 0;
1162- continue;
1163- }
11641326 if (apr_hash_get(committed, signature, APR_HASH_KEY_STRING) != NULL) {
11651327 i++;
11661328 }
1167- else if (mei_client_can_respond(client, event)) {
1168- mei_client_commit(client, event);
1329+ else if (c != NULL && fd != client->fd
1330+ && strcmp(signature, client->signature) != 0
1331+ && mei_client_can_respond(c, event)) {
1332+ mei_client_commit(c, event);
11691333 apr_hash_set(committed, signature, APR_HASH_KEY_STRING, "");
11701334 i++;
11711335 }
11721336 else {
1173- apr_table_unset(channel, signature);
1337+ apr_table_unset(channel, sfd);
11741338 i = 0;
11751339 }
11761340 }
@@ -1187,7 +1351,8 @@
11871351 channel = apr_hash_get(server->channels, path, APR_HASH_KEY_STRING);
11881352
11891353 if (channel != NULL && client->signature != NULL) {
1190- apr_table_unset(channel, client->signature);
1354+ apr_pool_t *pool = apr_table_elts(channel)->pool;
1355+ apr_table_unset(channel, apr_itoa(pool, client->fd));
11911356 return TRUE;
11921357 }
11931358 else {
@@ -1195,7 +1360,8 @@
11951360 }
11961361 }
11971362
1198-static void mei_channel_remove(mei_server_t * server, const char *path)
1363+static void mei_channel_remove(mei_server_t * server, const char *path,
1364+ mei_client_t * client)
11991365 {
12001366 MEI_START_ENTRY_POINT();
12011367
@@ -1207,9 +1373,13 @@
12071373 int i = 0;
12081374
12091375 while (i < ta->nelts) {
1210- mei_client_t *client = (mei_client_t *) te[i].val;
1211- if (client != NULL && client->parent != NULL) {
1376+ const char *sfd = te[i].key;
1377+ apr_os_sock_t fd = (apr_os_sock_t) apr_atoi64(sfd);
1378+ mei_client_t *c =
1379+ apr_hash_get(server->clients, sfd, APR_HASH_KEY_STRING);
1380+ if (c != NULL && fd != client->fd) {
12121381 mei_client_unbind_from_server(client);
1382+ apr_table_unset(channel, te[i].val);
12131383 i = 0;
12141384 }
12151385 else {
@@ -1217,12 +1387,12 @@
12171387 }
12181388 }
12191389
1220- apr_table_clear(channel);
1390+ apr_hash_set(server->channels, path, APR_HASH_KEY_STRING, NULL);
1391+ mei_server_log(server,
1392+ apr_psprintf(apr_table_elts(channel)->pool,
1393+ "Channel closed: %s\n", path));
1394+ apr_pool_destroy(apr_table_elts(channel)->pool);
12211395 }
1222-
1223- apr_hash_set(server->channels, path, APR_HASH_KEY_STRING, NULL);
1224- mei_server_log(server,
1225- apr_psprintf(server->pool, "Channel closed: %s\n", path));
12261396 }
12271397
12281398 /*
@@ -1248,9 +1418,8 @@
12481418 const char *key)
12491419 {
12501420 return mei_request_decode_uri_string(client->pool,
1251- apr_hash_get(client->request.param,
1252- key,
1253- APR_HASH_KEY_STRING));
1421+ apr_table_get(client->request.param,
1422+ key));
12541423 }
12551424
12561425 static void mei_request_set_parameters(mei_client_t * client, char *body)
@@ -1266,8 +1435,7 @@
12661435 if ((key = apr_strtok(kv_unit, "=", &kv_state)) != NULL) {
12671436 const char *value = kv_state;
12681437 if (value != NULL) {
1269- apr_hash_set(client->request.param, key,
1270- APR_HASH_KEY_STRING, value);
1438+ apr_table_setn(client->request.param, key, value);
12711439 }
12721440 }
12731441 } while ((kv_unit = apr_strtok(NULL, "&", &qs_state)) != NULL);
@@ -1282,7 +1450,7 @@
12821450 key));
12831451
12841452 if (*tags == NULL) {
1285- *tags = apr_array_make(client->pool, 8, sizeof(char *));
1453+ *tags = apr_array_make(client->pool, 8, sizeof(const char *));
12861454 }
12871455 if (tag == NULL || strncmp(tag, "", 1) == 0) {
12881456 return;
@@ -1443,21 +1611,18 @@
14431611
14441612 static const char *mei_request_query_to_json(mei_client_t * client)
14451613 {
1614+ const apr_array_header_t *ta = apr_table_elts(client->request.param);
1615+ const apr_table_entry_t *te = (const apr_table_entry_t *) ta->elts;
14461616 const char *queries = apr_pstrdup(client->pool, "");
1617+ int i, ta_count = ta->nelts;
14471618
1448- apr_hash_index_t *hi;
1449- for (hi = apr_hash_first(NULL, client->request.param); hi;
1450- hi = apr_hash_next(hi)) {
1451- const void *key;
1452- void *value;
1453- apr_hash_this(hi, &key, NULL, &value);
1619+ for (i = 0; i < ta_count; i++) {
14541620 queries =
14551621 apr_pstrcat(client->pool, queries, "\"",
14561622 mei_request_escape_js(client->pool,
1457- (const char *) key), "\":\"",
1623+ te[i].key), "\":\"",
14581624 mei_request_escape_js(client->pool,
1459- (const char *) value), "\",",
1460- NULL);
1625+ te[i].val), "\",", NULL);
14611626 }
14621627
14631628 return queries;
--- trunk/pluto.h (revision 36)
+++ trunk/pluto.h (revision 37)
@@ -32,6 +32,7 @@
3232 #include <apr_md5.h>
3333 #include <apr_ring.h>
3434 #include <apr_thread_proc.h>
35+#include <apr_portable.h>
3536
3637 #ifdef __cplusplus
3738 extern "C"
@@ -81,7 +82,10 @@
8182 {
8283 mei_config_t *config;
8384 mei_server_acl_t *acl;
85+ apr_pollset_t *pollset;
86+ apr_socket_t *socket;
8487 apr_pool_t *pool;
88+ apr_hash_t *clients;
8589 apr_hash_t *channels;
8690 apr_hash_t *executings;
8791 apr_hash_t *uids;
@@ -93,12 +97,6 @@
9397 APR_RING_ENTRY(mei_server_acl_entry_t) link;
9498 apr_ipsubnet_t *subnet;
9599 };
96-
97-
98-
99-
100-
101-
102100
103101
104102
@@ -108,12 +106,20 @@
108106 {
109107 struct
110108 {
109+ enum mei_request_method
110+ {
111+ MEI_REQUEST_IS_GET,
112+ MEI_REQUEST_IS_POST,
113+ MEI_REQUEST_IS_PUT,
114+ MEI_REQUEST_IS_DELETE,
115+ MEI_REQUEST_IS_UNKNOWN
116+ } method;
111117 const char *path;
112118 const char *uid;
113119 apr_array_header_t *tag;
114120 int is_flash;
115- apr_hash_t *header;
116- apr_hash_t *param;
121+ apr_table_t *header;
122+ apr_table_t *param;
117123 } request;
118124 struct
119125 {
@@ -122,7 +128,6 @@
122128 const char *content_type;
123129 int status;
124130 int close_connection;
125- apr_hash_t *header;
126131 } response;
127132 struct
128133 {
@@ -135,7 +140,7 @@
135140 const char *signature;
136141 mei_server_t *parent;
137142 apr_pool_t *pool;
138- apr_pollset_t *pollset;
143+ apr_os_sock_t fd;
139144 apr_socket_t *socket;
140145 apr_time_t connected_at;
141146 };
@@ -159,25 +164,13 @@
159164 mei_event_param_t *event;
160165 };
161166
162-#define MEI_REQUEST_METHOD_IS_GET(client) \
163- (client)->request.method == MEI_REQUEST_METHOD_GET
164-#define MEI_REQUEST_METHOD_IS_POST(client) \
165- (client)->request.method == MEI_REQUEST_METHOD_POST
166-#define MEI_REQUEST_METHOD_IS_HEAD(client) \
167- (client)->request.method == MEI_REQUEST_METHOD_HEAD
168-#define MEI_REQUEST_METHOD_IS_PUT(client) \
169- (client)->request.method == MEI_REQUEST_METHOD_PUT
170-#define MEI_REQUEST_METHOD_IS_DELETE(client) \
171- (client)->request.method == MEI_REQUEST_METHOD_DELETE
172-#define MEI_REQUEST_METHOD_IS_UNKNOWN(client) \
173- (client)->request.method == MEI_REQUEST_METHOD_UNKNOWN
174-
175167 static void usage(const char *self);
176168 static mei_config_t *mei_config_load(apr_pool_t * mp, const char *path);
177169 static const char *mei_config_get(mei_config_t * config, const char *key,
178170 const char *def);
179171 static const apr_array_header_t *mei_config_get_all(mei_config_t * config,
180- const char *key);
172+ const char *key,
173+ apr_pool_t * pool);
181174 static int mei_config_add_value_to_array(void *data, const char *key,
182175 const char *value);
183176 static void mei_server_create_listen_socket(mei_server_t * server,
@@ -184,7 +177,6 @@
184177 apr_socket_t ** sock,
185178 apr_pool_t * mp);
186179 static void mei_server_accept_client(mei_server_t * server,
187- apr_pollset_t * pollset,
188180 apr_socket_t * listen);
189181 static const char *mei_server_status_code_to_string(int code);
190182 static void mei_server_initialize_acl(mei_server_t * server);
@@ -197,7 +189,6 @@
197189 apr_size_t length);
198190 static void mei_client_set_response(mei_client_t * client,
199191 const char *response_body);
200- static void mei_client_remove_poll(mei_client_t * client);
201192 static void mei_client_send_content(mei_client_t * client, int code,
202193 const char *content);
203194 static void mei_client_send_content_for_flash(mei_client_t * client,
@@ -205,6 +196,7 @@
205196 int close_connection);
206197 static void mei_client_bind_to_server(mei_client_t * client);
207198 static void mei_client_unbind_from_server(mei_client_t * client);
199+ static void mei_client_close_connection(mei_client_t * client);
208200 static int mei_client_can_respond(mei_client_t * client,
209201 mei_event_param_t * event);
210202 static int mei_client_commit(mei_client_t * client,
@@ -216,7 +208,6 @@
216208 mei_event_param_t *
217209 event);
218210 static int mei_client_check_connection(mei_client_t * client);
219- static int mei_client_close_connection(mei_client_t * client);
220211
221212 static void mei_channel_create(mei_server_t * server, const char *path);
222213 static int mei_channel_exists(mei_server_t * server, const char *path);
@@ -225,12 +216,16 @@
225216 static int mei_channel_join(mei_server_t * server, const char *path,
226217 mei_client_t * client);
227218 static int mei_channel_notify(mei_server_t * server, const char *path,
219+ mei_client_t * client,
228220 mei_event_param_t * event);
229- static void mei_channel_transmit(mei_channel_t * channel,
221+ static void mei_channel_transmit(mei_server_t * server,
222+ mei_channel_t * channel,
223+ mei_client_t * client,
230224 mei_event_param_t * event);
231225 static int mei_channel_leave(mei_server_t * server, const char *path,
232226 mei_client_t * client);
233- static void mei_channel_remove(mei_server_t * server, const char *path);
227+ static void mei_channel_remove(mei_server_t * server, const char *path,
228+ mei_client_t * client);
234229
235230 static void mei_request_parse_query_string(mei_client_t * client,
236231 const char *path);
@@ -268,6 +263,44 @@
268263 apr_file_printf(apr_stderr, \
269264 "[%s] %s at line %d\n", cbuf, __func__, __LINE__)
270265
266+#define MEI_INSPECT_ARRAY(array) do { \
267+ if (array == NULL) { break; } \
268+ int i = 0; \
269+ printf("ARRAY: count:[%d] %s at line %d\n", \
270+ array->nelts, __func__, __LINE__); \
271+ for (; i < array->nelts; i++) { \
272+ printf("%d: key=[%s]\n", i, ((const char **)(array->elts))[i]); \
273+ } \
274+} while(FALSE)
275+
276+#define MEI_INSPECT_TABLE(table) do { \
277+ if (table == NULL) { break; } \
278+ const apr_array_header_t *ta = apr_table_elts(table); \
279+ const apr_table_entry_t *te = (const apr_table_entry_t *) ta->elts; \
280+ int i = 0; \
281+ printf("TABLE: count:[%d] %s at line %d\n", \
282+ ta->nelts, __func__, __LINE__); \
283+ for (; i < ta->nelts; i++) { \
284+ printf("key=[%s] / value=[%s]\n", te[i].key, te[i].val); \
285+ } \
286+} while(FALSE)
287+
288+#define MEI_INSPECT_HASH(hash, pool) do {\
289+ if (hash == NULL || pool == NULL) { break; } \
290+ apr_ssize_t len = 0; \
291+ const void *key = NULL; \
292+ void *val = NULL; \
293+ apr_hash_index_t *hash_index = apr_hash_first(pool, hash); \
294+ printf(apr_stderr, "HASH: count:[%d] %s at line\n", \
295+ apr_hash_count(hash), __func__, __LINE__); \
296+ while (hash_index) { \
297+ apr_hash_this(hash_index, &key, &len, &val); \
298+ printf("key=[%s:%d] / value=[%p]\n", \
299+ (const char *)key, len, val); \
300+ hash_index = apr_hash_next(hash_index); \
301+ } \
302+} while(FALSE)
303+
271304 #else
272305
273306 #define MEI_JS_LINE_BREAK
@@ -276,6 +309,12 @@
276309
277310 #define MEI_START_ENTRY_POINT() (void)0
278311
312+#define MEI_INSPECT_ARRAY(array) (void)0
313+
314+#define MEI_INSPECT_TABLE(table) (void)0
315+
316+#define MEI_INSPECT_HASH(hash, pool) (void)0
317+
279318 #endif
280319
281320 #ifdef __cplusplus
Show on old repository browser