| 92 }; |
92 }; |
| 93 |
93 |
| 94 static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn); |
94 static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn); |
| 95 static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node); |
95 static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node); |
| 96 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node); |
96 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node); |
| 97 static void jabber_bosh_connection_send_native(PurpleBOSHConnection *conn, PurpleBOSHPacketType, xmlnode *node); |
97 static void jabber_bosh_connection_send(PurpleBOSHConnection *conn, PurpleBOSHPacketType type, const char *data); |
| 98 |
98 |
| 99 static void http_connection_connect(PurpleHTTPConnection *conn); |
99 static void http_connection_connect(PurpleHTTPConnection *conn); |
| 100 static void http_connection_send_request(PurpleHTTPConnection *conn, const GString *req); |
100 static void http_connection_send_request(PurpleHTTPConnection *conn, const GString *req); |
| 101 |
101 |
| 102 void jabber_bosh_init(void) |
102 void jabber_bosh_init(void) |
| 223 return conn->ssl; |
223 return conn->ssl; |
| 224 } |
224 } |
| 225 |
225 |
| 226 void jabber_bosh_connection_close(PurpleBOSHConnection *conn) |
226 void jabber_bosh_connection_close(PurpleBOSHConnection *conn) |
| 227 { |
227 { |
| 228 jabber_bosh_connection_send_native(conn, PACKET_TERMINATE, NULL); |
228 jabber_bosh_connection_send(conn, PACKET_TERMINATE, NULL); |
| 229 } |
229 } |
| 230 |
230 |
| 231 static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn) { |
231 static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn) { |
| 232 jabber_bosh_connection_send_native(conn, PACKET_STREAM_RESTART, NULL); |
232 jabber_bosh_connection_send(conn, PACKET_STREAM_RESTART, NULL); |
| 233 } |
233 } |
| 234 |
234 |
| 235 static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node) { |
235 static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node) { |
| 236 const char *type; |
236 const char *type; |
| 237 |
237 |
| 250 static gboolean |
250 static gboolean |
| 251 bosh_inactivity_cb(gpointer data) |
251 bosh_inactivity_cb(gpointer data) |
| 252 { |
252 { |
| 253 PurpleBOSHConnection *bosh = data; |
253 PurpleBOSHConnection *bosh = data; |
| 254 |
254 |
| 255 jabber_bosh_connection_send(bosh, NULL); |
255 jabber_bosh_connection_send(bosh, PACKET_NORMAL, NULL); |
| 256 return TRUE; |
256 return TRUE; |
| 257 } |
257 } |
| 258 |
258 |
| 259 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) { |
259 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) { |
| 260 xmlnode *child; |
260 xmlnode *child; |
| 450 } else { |
450 } else { |
| 451 g_return_if_reached(); |
451 g_return_if_reached(); |
| 452 } |
452 } |
| 453 } |
453 } |
| 454 |
454 |
| 455 void jabber_bosh_connection_send(PurpleBOSHConnection *conn, xmlnode *node) { |
|
| 456 jabber_bosh_connection_send_native(conn, PACKET_NORMAL, node); |
|
| 457 } |
|
| 458 |
|
| 459 void jabber_bosh_connection_send_raw(PurpleBOSHConnection *conn, |
455 void jabber_bosh_connection_send_raw(PurpleBOSHConnection *conn, |
| 460 const char *data, int len) |
456 const char *data) |
| 461 { |
457 { |
| 462 xmlnode *node = xmlnode_from_str(data, len); |
458 jabber_bosh_connection_send(conn, PACKET_NORMAL, data); |
| 463 if (node) { |
459 } |
| 464 jabber_bosh_connection_send_native(conn, PACKET_NORMAL, node); |
460 |
| 465 xmlnode_free(node); |
461 static void |
| 466 } else { |
462 jabber_bosh_connection_send(PurpleBOSHConnection *conn, PurpleBOSHPacketType type, |
| 467 /* |
463 const char *data) |
| 468 * This best emulates what a normal XMPP server would do |
|
| 469 * if you send bad XML. |
|
| 470 */ |
|
| 471 purple_connection_error_reason(conn->js->gc, |
|
| 472 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
|
| 473 _("Cannot send malformed XML")); |
|
| 474 } |
|
| 475 } |
|
| 476 |
|
| 477 static void |
|
| 478 jabber_bosh_connection_send_native(PurpleBOSHConnection *conn, PurpleBOSHPacketType type, |
|
| 479 xmlnode *node) |
|
| 480 { |
464 { |
| 481 PurpleHTTPConnection *chosen; |
465 PurpleHTTPConnection *chosen; |
| 482 GString *packet = NULL; |
466 GString *packet = NULL; |
| 483 char *buf = NULL; |
|
| 484 int len; |
|
| 485 |
467 |
| 486 chosen = find_available_http_connection(conn); |
468 chosen = find_available_http_connection(conn); |
| 487 |
469 |
| 488 if (type != PACKET_NORMAL && !chosen) { |
470 if (type != PACKET_NORMAL && !chosen) { |
| 489 /* |
471 /* |
| 495 if (!chosen->ready) |
477 if (!chosen->ready) |
| 496 purple_debug_warning("jabber", "First BOSH connection wasn't ready. Bad " |
478 purple_debug_warning("jabber", "First BOSH connection wasn't ready. Bad " |
| 497 "things may happen.\n"); |
479 "things may happen.\n"); |
| 498 } |
480 } |
| 499 |
481 |
| 500 if (node) |
|
| 501 buf = xmlnode_to_str(node, &len); |
|
| 502 |
|
| 503 if (type == PACKET_NORMAL && (!chosen || |
482 if (type == PACKET_NORMAL && (!chosen || |
| 504 (conn->max_requests > 0 && conn->requests == conn->max_requests))) { |
483 (conn->max_requests > 0 && conn->requests == conn->max_requests))) { |
| 505 /* |
484 /* |
| 506 * For normal data, send up to max_requests requests at a time or there is no |
485 * For normal data, send up to max_requests requests at a time or there is no |
| 507 * connection ready (likely, we're currently opening a second connection and |
486 * connection ready (likely, we're currently opening a second connection and |
| 508 * will send these packets when connected). |
487 * will send these packets when connected). |
| 509 */ |
488 */ |
| 510 if (buf) { |
489 if (data) { |
| 511 purple_circ_buffer_append(conn->pending, buf, len); |
490 int len = data ? strlen(data) : 0; |
| 512 g_free(buf); |
491 purple_circ_buffer_append(conn->pending, data, len); |
| 513 } |
492 } |
| 514 return; |
493 return; |
| 515 } |
494 } |
| 516 |
495 |
| 517 packet = g_string_new(""); |
496 packet = g_string_new(""); |
| 539 while ((read_amt = purple_circ_buffer_get_max_read(conn->pending)) > 0) { |
518 while ((read_amt = purple_circ_buffer_get_max_read(conn->pending)) > 0) { |
| 540 packet = g_string_append_len(packet, conn->pending->outptr, read_amt); |
519 packet = g_string_append_len(packet, conn->pending->outptr, read_amt); |
| 541 purple_circ_buffer_mark_read(conn->pending, read_amt); |
520 purple_circ_buffer_mark_read(conn->pending, read_amt); |
| 542 } |
521 } |
| 543 |
522 |
| 544 if (buf) |
523 if (data) |
| 545 packet = g_string_append_len(packet, buf, len); |
524 packet = g_string_append(packet, data); |
| 546 packet = g_string_append(packet, "</body>"); |
525 packet = g_string_append(packet, "</body>"); |
| 547 } |
526 } |
| 548 |
|
| 549 g_free(buf); |
|
| 550 |
527 |
| 551 http_connection_send_request(chosen, packet); |
528 http_connection_send_request(chosen, packet); |
| 552 } |
529 } |
| 553 |
530 |
| 554 static void |
531 static void |
| 566 |
543 |
| 567 if (conn->bosh->ready) { |
544 if (conn->bosh->ready) { |
| 568 purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n"); |
545 purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n"); |
| 569 if (conn->bosh->pending->bufused > 0) { |
546 if (conn->bosh->pending->bufused > 0) { |
| 570 /* Send the pending data */ |
547 /* Send the pending data */ |
| 571 jabber_bosh_connection_send_native(conn->bosh, PACKET_NORMAL, NULL); |
548 jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL); |
| 572 } |
549 } |
| 573 #if 0 |
550 #if 0 |
| 574 conn->bosh->receive_cb = jabber_bosh_connection_received; |
551 conn->bosh->receive_cb = jabber_bosh_connection_received; |
| 575 if (conn->bosh->connect_cb) |
552 if (conn->bosh->connect_cb) |
| 576 conn->bosh->connect_cb(conn->bosh); |
553 conn->bosh->connect_cb(conn->bosh); |
| 579 jabber_bosh_connection_boot(conn->bosh); |
556 jabber_bosh_connection_boot(conn->bosh); |
| 580 } |
557 } |
| 581 |
558 |
| 582 void jabber_bosh_connection_refresh(PurpleBOSHConnection *conn) |
559 void jabber_bosh_connection_refresh(PurpleBOSHConnection *conn) |
| 583 { |
560 { |
| 584 jabber_bosh_connection_send(conn, NULL); |
561 jabber_bosh_connection_send(conn, PACKET_NORMAL, NULL); |
| 585 } |
562 } |
| 586 |
563 |
| 587 static void http_connection_disconnected(PurpleHTTPConnection *conn) |
564 static void http_connection_disconnected(PurpleHTTPConnection *conn) |
| 588 { |
565 { |
| 589 /* |
566 /* |
| 668 http_received_cb(conn->buf->str + conn->handled_len, conn->body_len, |
645 http_received_cb(conn->buf->str + conn->handled_len, conn->body_len, |
| 669 conn->bosh); |
646 conn->bosh); |
| 670 |
647 |
| 671 if (conn->bosh->ready && |
648 if (conn->bosh->ready && |
| 672 (conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0)) { |
649 (conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0)) { |
| 673 jabber_bosh_connection_send(conn->bosh, NULL); |
650 jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL); |
| 674 purple_debug_misc("jabber", "BOSH: Sending an empty request\n"); |
651 purple_debug_misc("jabber", "BOSH: Sending an empty request\n"); |
| 675 } |
652 } |
| 676 |
653 |
| 677 g_string_free(conn->buf, TRUE); |
654 g_string_free(conn->buf, TRUE); |
| 678 conn->buf = NULL; |
655 conn->buf = NULL; |