Mercurial > pidgin
comparison libpurple/protocols/jabber/bosh.c @ 25669:828640306e31
Don't track a cb-per-POST and remove the PurpleHTTPResponse structure.
The only callback ever used is http_received_cb and the ordering of
responses from the server is not guaranteed to match the order of our requests,
so the metaphor of matching them doesn't make sense. Instead of that, just
track the number of requests (to ensure there is always a request outstanding).
Additionally, pass the data const-ified instead of copying it. It's just
fed to an XML parser anyway.
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Wed, 21 Jan 2009 00:19:33 +0000 |
parents | 8c58f31f41eb |
children | c11c14dde641 |
comparison
equal
deleted
inserted
replaced
25668:8c58f31f41eb | 25669:828640306e31 |
---|---|
27 #include "xmlnode.h" | 27 #include "xmlnode.h" |
28 | 28 |
29 #include "bosh.h" | 29 #include "bosh.h" |
30 | 30 |
31 typedef struct _PurpleHTTPRequest PurpleHTTPRequest; | 31 typedef struct _PurpleHTTPRequest PurpleHTTPRequest; |
32 typedef struct _PurpleHTTPResponse PurpleHTTPResponse; | |
33 typedef struct _PurpleHTTPConnection PurpleHTTPConnection; | 32 typedef struct _PurpleHTTPConnection PurpleHTTPConnection; |
34 | 33 |
35 typedef void (*PurpleHTTPConnectionConnectFunction)(PurpleHTTPConnection *conn); | 34 typedef void (*PurpleHTTPConnectionConnectFunction)(PurpleHTTPConnection *conn); |
36 typedef void (*PurpleHTTPConnectionDisconnectFunction)(PurpleHTTPConnection *conn); | 35 typedef void (*PurpleHTTPConnectionDisconnectFunction)(PurpleHTTPConnection *conn); |
37 typedef void (*PurpleHTTPRequestCallback)(PurpleHTTPResponse *res, void *userdata); | |
38 typedef void (*PurpleBOSHConnectionConnectFunction)(PurpleBOSHConnection *conn); | 36 typedef void (*PurpleBOSHConnectionConnectFunction)(PurpleBOSHConnection *conn); |
39 typedef void (*PurpleBOSHConnectionReceiveFunction)(PurpleBOSHConnection *conn, xmlnode *node); | 37 typedef void (*PurpleBOSHConnectionReceiveFunction)(PurpleBOSHConnection *conn, xmlnode *node); |
40 | 38 |
41 static char *bosh_useragent = NULL; | 39 static char *bosh_useragent = NULL; |
42 | 40 |
64 struct _PurpleHTTPConnection { | 62 struct _PurpleHTTPConnection { |
65 int fd; | 63 int fd; |
66 char *host; | 64 char *host; |
67 int port; | 65 int port; |
68 int ie_handle; | 66 int ie_handle; |
69 GQueue *requests; /* Queue of PurpleHTTPRequestCallbacks */ | 67 int requests; /* number of outstanding HTTP requests */ |
70 | 68 |
71 PurpleHTTPResponse *current_response; | |
72 GString *buf; | 69 GString *buf; |
73 gboolean headers_done; | 70 gboolean headers_done; |
74 gsize handled_len; | 71 gsize handled_len; |
75 gsize body_len; | 72 gsize body_len; |
76 | 73 |
79 PurpleHTTPConnectionConnectFunction disconnect_cb; | 76 PurpleHTTPConnectionConnectFunction disconnect_cb; |
80 void *userdata; | 77 void *userdata; |
81 }; | 78 }; |
82 | 79 |
83 struct _PurpleHTTPRequest { | 80 struct _PurpleHTTPRequest { |
84 PurpleHTTPRequestCallback cb; | |
85 const char *path; | 81 const char *path; |
86 char *data; | 82 char *data; |
87 int data_len; | 83 int data_len; |
88 void *userdata; | 84 void *userdata; |
89 }; | 85 }; |
90 | 86 |
91 struct _PurpleHTTPResponse { | |
92 char *data; | |
93 int data_len; | |
94 }; | |
95 | |
96 static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn); | 87 static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn); |
97 static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node); | 88 static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node); |
98 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node); | 89 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node); |
99 static void jabber_bosh_connection_http_received_cb(PurpleHTTPResponse *res, void *userdata); | |
100 static void jabber_bosh_connection_send_native(PurpleBOSHConnection *conn, xmlnode *node); | 90 static void jabber_bosh_connection_send_native(PurpleBOSHConnection *conn, xmlnode *node); |
101 | 91 |
102 static void jabber_bosh_http_connection_connect(PurpleHTTPConnection *conn); | 92 static void jabber_bosh_http_connection_connect(PurpleHTTPConnection *conn); |
103 static void jabber_bosh_http_connection_send_request(PurpleHTTPConnection *conn, PurpleHTTPRequest *req); | 93 static void jabber_bosh_http_connection_send_request(PurpleHTTPConnection *conn, PurpleHTTPRequest *req); |
104 | 94 |
132 { | 122 { |
133 g_free(req->data); | 123 g_free(req->data); |
134 g_free(req); | 124 g_free(req); |
135 } | 125 } |
136 | 126 |
137 static void | |
138 jabber_bosh_http_response_destroy(PurpleHTTPResponse *res) | |
139 { | |
140 g_free(res->data); | |
141 g_free(res); | |
142 } | |
143 | |
144 static PurpleHTTPConnection* | 127 static PurpleHTTPConnection* |
145 jabber_bosh_http_connection_init(const char *host, int port) | 128 jabber_bosh_http_connection_init(const char *host, int port) |
146 { | 129 { |
147 PurpleHTTPConnection *conn = g_new0(PurpleHTTPConnection, 1); | 130 PurpleHTTPConnection *conn = g_new0(PurpleHTTPConnection, 1); |
148 conn->host = g_strdup(host); | 131 conn->host = g_strdup(host); |
149 conn->port = port; | 132 conn->port = port; |
150 conn->fd = -1; | 133 conn->fd = -1; |
151 conn->requests = g_queue_new(); | |
152 | 134 |
153 return conn; | 135 return conn; |
154 } | 136 } |
155 | 137 |
156 static void | 138 static void |
159 g_free(conn->host); | 141 g_free(conn->host); |
160 | 142 |
161 if (conn->buf) | 143 if (conn->buf) |
162 g_string_free(conn->buf, TRUE); | 144 g_string_free(conn->buf, TRUE); |
163 | 145 |
164 if (conn->requests) | |
165 g_queue_free(conn->requests); | |
166 | |
167 if (conn->current_response) | |
168 jabber_bosh_http_response_destroy(conn->current_response); | |
169 | |
170 if (conn->ie_handle) | 146 if (conn->ie_handle) |
171 purple_input_remove(conn->ie_handle); | 147 purple_input_remove(conn->ie_handle); |
172 if (conn->fd > 0) | 148 if (conn->fd >= 0) |
173 close(conn->fd); | 149 close(conn->fd); |
174 | 150 |
175 g_free(conn); | 151 g_free(conn); |
176 } | 152 } |
177 | 153 |
394 conn->receive_cb = boot_response_cb; | 370 conn->receive_cb = boot_response_cb; |
395 jabber_bosh_connection_send_native(conn, init); | 371 jabber_bosh_connection_send_native(conn, init); |
396 xmlnode_free(init); | 372 xmlnode_free(init); |
397 } | 373 } |
398 | 374 |
399 static void jabber_bosh_connection_http_received_cb(PurpleHTTPResponse *res, void *userdata) { | 375 static void |
376 http_received_cb(const char *data, int len, void *userdata) | |
377 { | |
400 PurpleBOSHConnection *conn = userdata; | 378 PurpleBOSHConnection *conn = userdata; |
401 if (conn->receive_cb) { | 379 if (conn->receive_cb) { |
402 xmlnode *node = xmlnode_from_str(res->data, res->data_len); | 380 xmlnode *node = xmlnode_from_str(data, len); |
403 if (node) { | 381 if (node) { |
404 char *txt = xmlnode_to_formatted_str(node, NULL); | 382 char *txt = xmlnode_to_formatted_str(node, NULL); |
405 printf("\njabber_bosh_connection_http_received_cb\n%s\n", txt); | 383 printf("\nhttp_received_cb\n%s\n", txt); |
406 g_free(txt); | 384 g_free(txt); |
407 conn->receive_cb(conn, node); | 385 conn->receive_cb(conn, node); |
408 xmlnode_free(node); | 386 xmlnode_free(node); |
409 } else { | 387 } else { |
410 purple_debug_warning("jabber", "BOSH: Received invalid XML\n"); | 388 purple_debug_warning("jabber", "BOSH: Received invalid XML\n"); |
454 static void jabber_bosh_connection_send_native(PurpleBOSHConnection *conn, xmlnode *node) { | 432 static void jabber_bosh_connection_send_native(PurpleBOSHConnection *conn, xmlnode *node) { |
455 PurpleHTTPRequest *request; | 433 PurpleHTTPRequest *request; |
456 | 434 |
457 request = g_new0(PurpleHTTPRequest, 1); | 435 request = g_new0(PurpleHTTPRequest, 1); |
458 request->path = conn->path; | 436 request->path = conn->path; |
459 request->cb = jabber_bosh_connection_http_received_cb; | |
460 request->userdata = conn; | 437 request->userdata = conn; |
461 | 438 |
462 request->data = xmlnode_to_str(node, &(request->data_len)); | 439 request->data = xmlnode_to_str(node, &(request->data_len)); |
463 | 440 |
464 jabber_bosh_http_connection_send_request(conn->conn_a, request); | 441 jabber_bosh_http_connection_send_request(conn->conn_a, request); |
491 | 468 |
492 static void | 469 static void |
493 jabber_bosh_http_connection_process(PurpleHTTPConnection *conn) | 470 jabber_bosh_http_connection_process(PurpleHTTPConnection *conn) |
494 { | 471 { |
495 PurpleBOSHConnection *bosh_conn = conn->userdata; | 472 PurpleBOSHConnection *bosh_conn = conn->userdata; |
496 PurpleHTTPRequestCallback cb; | |
497 const char *cursor; | 473 const char *cursor; |
498 | |
499 if (!conn->current_response) | |
500 conn->current_response = g_new0(PurpleHTTPResponse, 1); | |
501 | 474 |
502 cursor = conn->buf->str + conn->handled_len; | 475 cursor = conn->buf->str + conn->handled_len; |
503 | 476 |
504 if (!conn->headers_done) { | 477 if (!conn->headers_done) { |
505 const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length"); | 478 const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length"); |
531 | 504 |
532 /* Have we read all that the Content-Length promised us? */ | 505 /* Have we read all that the Content-Length promised us? */ |
533 if (conn->buf->len - conn->handled_len < conn->body_len) | 506 if (conn->buf->len - conn->handled_len < conn->body_len) |
534 return; | 507 return; |
535 | 508 |
536 cb = g_queue_pop_head(conn->requests); | 509 --conn->requests; |
537 | 510 |
538 #warning For a pure HTTP 1.1 stack, this would need to be handled elsewhere. | 511 #warning For a pure HTTP 1.1 stack, this would need to be handled elsewhere. |
539 if (bosh_conn->ready && g_queue_is_empty(conn->requests)) { | 512 if (bosh_conn->ready && conn->requests == 0) { |
540 jabber_bosh_connection_send(bosh_conn, NULL); | 513 jabber_bosh_connection_send(bosh_conn, NULL); |
541 purple_debug_misc("jabber", "BOSH: Sending an empty request\n"); | 514 purple_debug_misc("jabber", "BOSH: Sending an empty request\n"); |
542 } | 515 } |
543 | 516 |
544 if (cb) { | 517 http_received_cb(conn->buf->str + conn->handled_len, conn->body_len, |
545 conn->current_response->data_len = conn->body_len; | 518 conn->userdata); |
546 conn->current_response->data = g_memdup(conn->buf->str + conn->handled_len, conn->body_len + 1); | |
547 | |
548 cb(conn->current_response, conn->userdata); | |
549 } else { | |
550 purple_debug_warning("jabber", "Received HTTP response before POST\n"); | |
551 } | |
552 | 519 |
553 g_string_free(conn->buf, TRUE); | 520 g_string_free(conn->buf, TRUE); |
554 conn->buf = NULL; | 521 conn->buf = NULL; |
555 jabber_bosh_http_response_destroy(conn->current_response); | 522 conn->headers_done = FALSE; |
556 conn->current_response = NULL; | 523 conn->handled_len = conn->body_len = 0; |
557 conn->headers_done = conn->handled_len = conn->body_len = 0; | |
558 } | 524 } |
559 | 525 |
560 static void | 526 static void |
561 jabber_bosh_http_connection_read(gpointer data, gint fd, | 527 jabber_bosh_http_connection_read(gpointer data, gint fd, |
562 PurpleInputCondition condition) | 528 PurpleInputCondition condition) |
660 purple_debug_misc("jabber", "BOSH out: %s\n", packet->str); | 626 purple_debug_misc("jabber", "BOSH out: %s\n", packet->str); |
661 /* TODO: Better error handling, circbuffer or possible integration with | 627 /* TODO: Better error handling, circbuffer or possible integration with |
662 * low-level code in jabber.c */ | 628 * low-level code in jabber.c */ |
663 ret = write(conn->fd, packet->str, packet->len); | 629 ret = write(conn->fd, packet->str, packet->len); |
664 | 630 |
631 ++conn->requests; | |
665 g_string_free(packet, TRUE); | 632 g_string_free(packet, TRUE); |
666 g_queue_push_tail(conn->requests, req->cb); | |
667 jabber_bosh_http_request_destroy(req); | 633 jabber_bosh_http_request_destroy(req); |
668 | 634 |
669 if (ret < 0 && errno == EAGAIN) | 635 if (ret < 0 && errno == EAGAIN) |
670 purple_debug_warning("jabber", "BOSH write would have blocked\n"); | 636 purple_debug_warning("jabber", "BOSH write would have blocked\n"); |
671 | 637 |