comparison libpurple/protocols/jabber/bosh.c @ 25994:a94b28023bf6

Clean up BOSH reading and disconnection handling. In particular, notice we've disconnected _before_ we process what we read, so that, if processing ends up trying to send a new packet, this connection will be marked as closed.
author Paul Aurich <paul@darkrain42.org>
date Mon, 16 Mar 2009 02:45:53 +0000
parents c3c2e8b64539
children e995540378f0
comparison
equal deleted inserted replaced
25993:6d7d360687bd 25994:a94b28023bf6
496 http_connection_send_request(chosen, packet); 496 http_connection_send_request(chosen, packet);
497 } 497 }
498 498
499 static void http_connection_connected(PurpleHTTPConnection *conn) 499 static void http_connection_connected(PurpleHTTPConnection *conn)
500 { 500 {
501 /* Indicate we're ready and reset some variables */
501 conn->ready = TRUE; 502 conn->ready = TRUE;
503 conn->requests = 0;
504 if (conn->buf) {
505 g_string_free(conn->buf, TRUE);
506 conn->buf = NULL;
507 }
508 conn->headers_done = FALSE;
509 conn->handled_len = conn->body_len = 0;
502 510
503 if (conn->bosh->ready) { 511 if (conn->bosh->ready) {
504 purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n"); 512 purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n");
505 if (conn->bosh->pending && conn->bosh->pending->len > 0) { 513 if (conn->bosh->pending && conn->bosh->pending->len > 0) {
506 /* Send the pending data */ 514 /* Send the pending data */
526 * Well, then. Fine! I never liked you anyway, server! I was cheating on you 534 * Well, then. Fine! I never liked you anyway, server! I was cheating on you
527 * with AIM! 535 * with AIM!
528 */ 536 */
529 conn->ready = FALSE; 537 conn->ready = FALSE;
530 conn->fd = -1; 538 conn->fd = -1;
539 purple_input_remove(conn->ie_handle);
540 conn->ie_handle = 0;
531 541
532 if (conn->bosh->pipelining) 542 if (conn->bosh->pipelining)
533 /* Hmmmm, fall back to multiple connections */ 543 /* Hmmmm, fall back to multiple connections */
534 conn->bosh->pipelining = FALSE; 544 conn->bosh->pipelining = FALSE;
535 545
603 jabber_bosh_http_connection_read(gpointer data, gint fd, 613 jabber_bosh_http_connection_read(gpointer data, gint fd,
604 PurpleInputCondition condition) 614 PurpleInputCondition condition)
605 { 615 {
606 PurpleHTTPConnection *conn = data; 616 PurpleHTTPConnection *conn = data;
607 char buffer[1025]; 617 char buffer[1025];
608 int perrno;
609 int cnt, count = 0; 618 int cnt, count = 0;
610
611 purple_debug_info("jabber", "jabber_bosh_http_connection_read\n");
612 619
613 if (!conn->buf) 620 if (!conn->buf)
614 conn->buf = g_string_new(""); 621 conn->buf = g_string_new("");
615 622
616 while ((cnt = read(fd, buffer, sizeof(buffer))) > 0) { 623 while ((cnt = read(fd, buffer, sizeof(buffer))) > 0) {
617 purple_debug_info("jabber", "bosh read %d bytes\n", cnt);
618 count += cnt; 624 count += cnt;
619 g_string_append_len(conn->buf, buffer, cnt); 625 g_string_append_len(conn->buf, buffer, cnt);
620 } 626 }
621 627
622 perrno = errno; 628 if (cnt == 0 || (cnt < 0 && errno != EAGAIN)) {
623 if (cnt == 0 && count) {
624 /* TODO: process should know this response ended with a closed socket
625 * and throw an error if it's not a complete response. */
626 jabber_bosh_http_connection_process(conn);
627 }
628
629 if (cnt == 0 || (cnt < 0 && perrno != EAGAIN)) {
630 if (cnt < 0) 629 if (cnt < 0)
631 purple_debug_info("jabber", "bosh read: %d\n", cnt); 630 purple_debug_info("jabber", "bosh read=%d, errno=%d\n", cnt, errno);
632 else 631 else
633 purple_debug_info("jabber", "bosh socket closed\n"); 632 purple_debug_info("jabber", "bosh server closed connection\n");
634 633
635 purple_input_remove(conn->ie_handle); 634 /*
636 conn->ie_handle = 0; 635 * If the socket is closed, the processing really needs to know about
637 636 * it. Handle that now (it will be handled again post-processing).
637 */
638 http_connection_disconnected(conn); 638 http_connection_disconnected(conn);
639 return; 639
640 /* Process what we do have */
640 } 641 }
641 642
642 jabber_bosh_http_connection_process(conn); 643 jabber_bosh_http_connection_process(conn);
643 } 644 }
644 645
692 conn->bosh->path, conn->bosh->host, bosh_useragent, 693 conn->bosh->path, conn->bosh->host, bosh_useragent,
693 req->len); 694 req->len);
694 695
695 packet = g_string_append(packet, req->str); 696 packet = g_string_append(packet, req->str);
696 697
697 purple_debug_misc("jabber", "BOSH out: %s\n", packet->str);
698 /* TODO: Better error handling, circbuffer or possible integration with 698 /* TODO: Better error handling, circbuffer or possible integration with
699 * low-level code in jabber.c */ 699 * low-level code in jabber.c */
700 ret = write(conn->fd, packet->str, packet->len); 700 ret = write(conn->fd, packet->str, packet->len);
701 701
702 ++conn->requests; 702 ++conn->requests;
703 ++conn->bosh->requests; 703 ++conn->bosh->requests;
704 g_string_free(packet, TRUE); 704 g_string_free(packet, TRUE);
705 705
706 if (ret < 0 && errno == EAGAIN) 706 if (ret < 0 && errno == EAGAIN)
707 purple_debug_warning("jabber", "BOSH write would have blocked\n"); 707 purple_debug_error("jabber", "BOSH write would have blocked\n");
708 708
709 if (ret <= 0) { 709 if (ret <= 0) {
710 purple_connection_error_reason(conn->bosh->js->gc, 710 purple_connection_error_reason(conn->bosh->js->gc,
711 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 711 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
712 _("Write error")); 712 _("Write error"));