comparison libpurple/protocols/jabber/bosh.c @ 25051:5f70e13db5cc

* data buffer for received data. Support for any HTTP resonse size now.
author Tobias Markmann <tfar@soc.pidgin.im>
date Sat, 16 Aug 2008 21:28:32 +0000
parents a03a953ba63d
children 0a8484372312
comparison
equal deleted inserted replaced
25050:a03a953ba63d 25051:5f70e13db5cc
80 80
81 jabber_bosh_connection_send_native(conn, restart); 81 jabber_bosh_connection_send_native(conn, restart);
82 } 82 }
83 83
84 void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) { 84 void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) {
85 85 xmlnode *child;
86 JabberStream *js = conn->js;
87
88 if (node == NULL) return;
89
90 child = node->child;
91 while (child != 0) {
92 if (child->type == XMLNODE_TYPE_TAG) {
93 jabber_process_packet(js, &child);
94 }
95 child = child->next;
96 }
86 xmlnode_free(node); 97 xmlnode_free(node);
87 } 98 }
88 99
89 void jabber_bosh_connection_auth_response(PurpleBOSHConnection *conn, xmlnode *node) { 100 void jabber_bosh_connection_auth_response(PurpleBOSHConnection *conn, xmlnode *node) {
90 xmlnode *child = node->child; 101 xmlnode *child = node->child;
96 if (child != NULL && child->type == XMLNODE_TYPE_TAG) { 107 if (child != NULL && child->type == XMLNODE_TYPE_TAG) {
97 JabberStream *js = conn->js; 108 JabberStream *js = conn->js;
98 if (!strcmp(child->name, "success")) { 109 if (!strcmp(child->name, "success")) {
99 jabber_bosh_connection_stream_restart(conn); 110 jabber_bosh_connection_stream_restart(conn);
100 jabber_process_packet(js, &child); 111 jabber_process_packet(js, &child);
112 conn->receive_cb = jabber_bosh_connection_received;
101 } else { 113 } else {
102 js->state = JABBER_STREAM_AUTHENTICATING; 114 js->state = JABBER_STREAM_AUTHENTICATING;
103 conn->receive_cb = jabber_bosh_connection_received;
104 jabber_process_packet(js, &child); 115 jabber_process_packet(js, &child);
105 } 116 }
106 } else printf("\n!! no child!!\n"); 117 } else printf("\n!! no child!!\n");
107 } 118 }
108 119
153 164
154 void jabber_bosh_connection_http_received_cb(PurpleHTTPRequest *req, PurpleHTTPResponse *res, void *userdata) { 165 void jabber_bosh_connection_http_received_cb(PurpleHTTPRequest *req, PurpleHTTPResponse *res, void *userdata) {
155 PurpleBOSHConnection *conn = userdata; 166 PurpleBOSHConnection *conn = userdata;
156 if (conn->receive_cb) { 167 if (conn->receive_cb) {
157 xmlnode *node = xmlnode_from_str(res->data, res->data_len); 168 xmlnode *node = xmlnode_from_str(res->data, res->data_len);
158 char *txt = xmlnode_to_formatted_str(node, NULL); 169 if (node) {
159 printf("\njabber_bosh_connection_http_received_cb\n%s\n", txt); 170 char *txt = xmlnode_to_formatted_str(node, NULL);
160 g_free(txt); 171 printf("\njabber_bosh_connection_http_received_cb\n%s\n", txt);
161 conn->receive_cb(conn, node); 172 g_free(txt);
173 conn->receive_cb(conn, node);
174 } else {
175 printf("\njabber_bosh_connection_http_received_cb: XML ERROR: %s\n", res->data);
176 }
162 } else purple_debug_info("jabber", "missing receive_cb of PurpleBOSHConnection.\n"); 177 } else purple_debug_info("jabber", "missing receive_cb of PurpleBOSHConnection.\n");
163 } 178 }
164 179
165 void jabber_bosh_connection_send(PurpleBOSHConnection *conn, xmlnode *node) { 180 void jabber_bosh_connection_send(PurpleBOSHConnection *conn, xmlnode *node) {
166 xmlnode *packet = xmlnode_new("body"); 181 xmlnode *packet = xmlnode_new("body");
201 void jabber_bosh_connection_connect(PurpleBOSHConnection *conn) { 216 void jabber_bosh_connection_connect(PurpleBOSHConnection *conn) {
202 conn->conn_a->connect_cb = jabber_bosh_connection_connected; 217 conn->conn_a->connect_cb = jabber_bosh_connection_connected;
203 jabber_bosh_http_connection_connect(conn->conn_a); 218 jabber_bosh_http_connection_connect(conn->conn_a);
204 } 219 }
205 220
221 void jabber_bosh_http_connection_receive_parse_header(PurpleHTTPResponse *response, char **data, int *len) {
222 GHashTable *header = response->header;
223 char *beginning = *data;
224 char *found = g_strstr_len(*data, len, "\r\n\r\n");
225 char *field = NULL;
226 char *value = NULL;
227 char *old_data = *data;
228
229 while (*beginning != 'H') ++beginning;
230 beginning[12] = 0;
231 response->status = atoi(&beginning[9]);
232 beginning = &beginning[13];
233 do {
234 ++beginning;
235 } while (*beginning != '\n');
236 ++beginning;
237 /* parse HTTP response header */
238 for (;beginning != found; ++beginning) {
239 if (!field) field = beginning;
240 if (*beginning == ':') {
241 *beginning = 0;
242 value = beginning + 1;
243 } else if (*beginning == '\r') {
244 *beginning = 0;
245 g_hash_table_replace(header, g_strdup(field), g_strdup(value));
246 value = field = 0;
247 ++beginning;
248 }
249 }
250 ++beginning; ++beginning; ++beginning; ++beginning;
251 /* remove the header from data buffer */
252 *data = g_strdup(beginning);
253 g_free(old_data);
254 }
255
206 static void jabber_bosh_http_connection_receive(gpointer data, gint source, PurpleInputCondition condition) { 256 static void jabber_bosh_http_connection_receive(gpointer data, gint source, PurpleInputCondition condition) {
207 char buffer[1024]; 257 char buffer[1025];
208 int len; 258 int len;
209 PurpleHTTPConnection *conn = data; 259 PurpleHTTPConnection *conn = data;
210 PurpleHTTPResponse *response = conn->current_response; 260 PurpleHTTPResponse *response = conn->current_response;
211 261
212 purple_debug_info("jabber", "jabber_bosh_http_connection_receive\n"); 262 purple_debug_info("jabber", "jabber_bosh_http_connection_receive\n");
213 if (!response) {
214 // new response
215 response = conn->current_response = g_new0(PurpleHTTPResponse, 1);
216 jabber_bosh_http_response_init(response);
217 }
218 263
219 len = read(source, buffer, 1024); 264 len = read(source, buffer, 1024);
220 if (len > 0) { 265 if (len > 0) {
221 char *found = NULL; 266 buffer[len] = 0;
222 if (found = g_strstr_len(buffer, len, "\r\n\r\n")) { 267 if (conn->current_data == NULL) {
223 char *beginning = buffer; 268 conn->current_len = len;
224 char *field = NULL; 269 conn->current_data = g_strdup_printf("%s", buffer);
225 char *value = NULL; 270 } else {
226 char *cl = NULL; 271 char *old_data = conn->current_data;
227 272 conn->current_len += len;
228 while (*beginning != 'H') ++beginning; 273 conn->current_data = g_strdup_printf("%s%s", conn->current_data, buffer);
229 beginning[12] = 0; 274 g_free(old_data);
230 response->status = atoi(&beginning[9]); 275 }
231 beginning = &beginning[13]; 276
232 do { 277 if (!response) {
233 ++beginning; 278 /* check for header footer */
234 } while (*beginning != '\n'); 279 char *found = NULL;
235 ++beginning; 280 if (found = g_strstr_len(conn->current_data, conn->current_len, "\r\n\r\n")) {
236 /* parse HTTP response header */ 281 // new response
237 for (;beginning != found; ++beginning) { 282 response = conn->current_response = g_new0(PurpleHTTPResponse, 1);
238 if (!field) field = beginning; 283 jabber_bosh_http_response_init(response);
239 if (*beginning == ':') { 284 jabber_bosh_http_connection_receive_parse_header(response, &(conn->current_data), &(conn->current_len));
240 *beginning = 0; 285 response->data_len = atoi(g_hash_table_lookup(response->header, "Content-Length"));
241 value = beginning + 1; 286 jabber_bosh_http_connection_receive(data, source, condition);
242 } else if (*beginning == '\r') { 287 } else {
243 *beginning = 0; 288 printf("\nDATA: %s \n", conn->current_data);
244 g_hash_table_replace(response->header, g_strdup(field), g_strdup(value)); 289 printf("\nDid not receive HTTP header\n");
245 value = field = 0;
246 ++beginning;
247 }
248 } 290 }
249 ++found; ++found; ++found; ++found; 291 }
250 292
251 cl = g_hash_table_lookup(response->header, "Content-Length"); 293 if (response) {
252 if (cl) { 294 if (conn->current_len >= response->data_len) {
253 PurpleHTTPRequest *request = NULL; 295 PurpleHTTPRequest *request = g_queue_pop_head(conn->requests);
254 response->data_len = atoi(cl);
255 if (response->data <= len - (found - buffer)) response->data = g_memdup(found, response->data_len);
256 else printf("\nDidn't receive complete content");
257
258 request = g_queue_pop_head(conn->requests);
259 if (request) { 296 if (request) {
297 response->data = g_memdup(conn->current_data, response->data_len);
260 request->cb(request, response, conn->userdata); 298 request->cb(request, response, conn->userdata);
261 jabber_bosh_http_request_clean(request); 299 jabber_bosh_http_request_clean(request);
262 jabber_bosh_http_response_clean(response); 300 jabber_bosh_http_response_clean(response);
263 conn->current_response = NULL; 301 conn->current_response = NULL;
264 } else { 302 } else {
265 purple_debug_info("jabber", "received HTTP response but haven't requested anything yet.\n"); 303 purple_debug_info("jabber", "received HTTP response but haven't requested anything yet.\n");
266 } 304 }
267 } else {
268 printf("\ndidn't receive length.\n");
269 } 305 }
270 } else {
271 printf("\nDid not receive complete HTTP header!\n");
272 } 306 }
273 } else { 307 } else {
274 purple_debug_info("jabber", "jabber_bosh_http_connection_receive: problem receiving data\n"); 308 purple_debug_info("jabber", "jabber_bosh_http_connection_receive: problem receiving data\n");
275 } 309 }
276 } 310 }