Mercurial > pidgin
comparison src/protocols/oscar/flap_connection.c @ 13608:6c34fbb75bbd
[gaim-migrate @ 15994]
Disconnect the account with a decent error message when there are
problems with an oscar FLAP connection. This needed to be added
after I removed it when rewriting things for non-blocking I/O.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 10 Apr 2006 03:37:37 +0000 |
parents | 57e5d1455ad7 |
children | 5796551db930 |
comparison
equal
deleted
inserted
replaced
13607:a79d422bfe62 | 13608:6c34fbb75bbd |
---|---|
227 | 227 |
228 static gboolean | 228 static gboolean |
229 flap_connection_destroy_cb(gpointer data) | 229 flap_connection_destroy_cb(gpointer data) |
230 { | 230 { |
231 FlapConnection *conn; | 231 FlapConnection *conn; |
232 OscarData *od; | |
233 GaimAccount *account; | |
232 | 234 |
233 conn = data; | 235 conn = data; |
236 od = conn->od; | |
234 | 237 |
235 gaim_debug_info("oscar", "Destroying oscar connection of " | 238 gaim_debug_info("oscar", "Destroying oscar connection of " |
236 "type 0x%04hx\n", conn->type); | 239 "type 0x%04hx\n", conn->type); |
237 | 240 |
238 flap_connection_close(conn->od, conn); | 241 flap_connection_close(od, conn); |
239 | 242 |
240 if (conn->watcher_incoming != 0) | 243 if (conn->watcher_incoming != 0) |
241 gaim_input_remove(conn->watcher_incoming); | 244 gaim_input_remove(conn->watcher_incoming); |
242 if (conn->watcher_outgoing != 0) | 245 if (conn->watcher_outgoing != 0) |
243 gaim_input_remove(conn->watcher_outgoing); | 246 gaim_input_remove(conn->watcher_outgoing); |
246 | 249 |
247 /* | 250 /* |
248 * Free conn->internal, if necessary | 251 * Free conn->internal, if necessary |
249 */ | 252 */ |
250 if (conn->type == SNAC_FAMILY_CHAT) | 253 if (conn->type == SNAC_FAMILY_CHAT) |
251 flap_connection_destroy_chat(conn->od, conn); | 254 flap_connection_destroy_chat(od, conn); |
252 | 255 |
253 if (conn->inside != NULL) | 256 if (conn->inside != NULL) |
254 { | 257 { |
255 aim_conn_inside_t *inside = (aim_conn_inside_t *)conn->inside; | 258 aim_conn_inside_t *inside = (aim_conn_inside_t *)conn->inside; |
256 | 259 |
258 flap_connection_destroy_rates(inside->rates); | 261 flap_connection_destroy_rates(inside->rates); |
259 | 262 |
260 free(inside); | 263 free(inside); |
261 } | 264 } |
262 | 265 |
263 conn->od->oscar_connections = g_list_remove(conn->od->oscar_connections, conn); | 266 od->oscar_connections = g_list_remove(od->oscar_connections, conn); |
264 | |
265 g_free(conn); | 267 g_free(conn); |
266 | 268 |
269 account = gaim_connection_get_account(od->gc); | |
270 if ((od->oscar_connections == NULL) && (!account->disconnecting)) | |
271 { | |
272 /* No more FLAP connections! Sign off this GaimConnection! */ | |
273 const gchar *tmp; | |
274 if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED) | |
275 tmp = _("Server closed the connection."); | |
276 else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION) | |
277 tmp = _("Lost connection with server for an unknown reason."); | |
278 else if (conn->disconnect_reason == OSCAR_DISCONNECT_INVALID_DATA) | |
279 tmp = _("Received invalid data on connection with server."); | |
280 else if (conn->disconnect_reason == OSCAR_DISCONNECT_COULD_NOT_CONNECT) | |
281 tmp = _("Could not establish a connection with the server."); | |
282 else | |
283 tmp = NULL; | |
284 | |
285 if (tmp != NULL) | |
286 gaim_connection_error(od->gc, tmp); | |
287 } | |
288 | |
267 return FALSE; | 289 return FALSE; |
268 } | 290 } |
269 | 291 |
270 void | 292 void |
271 flap_connection_destroy(FlapConnection *conn) | 293 flap_connection_destroy(FlapConnection *conn, OscarDisconnectReason reason) |
272 { | 294 { |
273 if (conn->destroy_timeout != 0) | 295 if (conn->destroy_timeout != 0) |
274 gaim_timeout_remove(conn->destroy_timeout); | 296 gaim_timeout_remove(conn->destroy_timeout); |
297 conn->disconnect_reason = reason; | |
275 flap_connection_destroy_cb(conn); | 298 flap_connection_destroy_cb(conn); |
276 } | 299 } |
277 | 300 |
278 /** | 301 /** |
279 * Schedule Gaim to destroy the given FlapConnection as soon as we | 302 * Schedule Gaim to destroy the given FlapConnection as soon as we |
280 * return control back to the program's main loop. We must do this | 303 * return control back to the program's main loop. We must do this |
281 * if we want to destroy the connection but we are still using it | 304 * if we want to destroy the connection but we are still using it |
282 * for some reason. | 305 * for some reason. |
283 */ | 306 */ |
284 void | 307 void |
285 flap_connection_schedule_destroy(FlapConnection *conn) | 308 flap_connection_schedule_destroy(FlapConnection *conn, OscarDisconnectReason reason) |
286 { | 309 { |
287 if (conn->destroy_timeout != 0) | 310 if (conn->destroy_timeout != 0) |
288 /* Already taken care of */ | 311 /* Already taken care of */ |
289 return; | 312 return; |
290 | 313 |
291 gaim_debug_info("oscar", "Scheduling destruction of FLAP " | 314 gaim_debug_info("oscar", "Scheduling destruction of FLAP " |
292 "connection of type 0x%04hx\n", conn->type); | 315 "connection of type 0x%04hx\n", conn->type); |
316 conn->disconnect_reason = reason; | |
293 conn->destroy_timeout = gaim_timeout_add(0, flap_connection_destroy_cb, conn); | 317 conn->destroy_timeout = gaim_timeout_add(0, flap_connection_destroy_cb, conn); |
294 } | 318 } |
295 | 319 |
296 /** | 320 /** |
297 * In OSCAR, every connection has a set of SNAC groups associated | 321 * In OSCAR, every connection has a set of SNAC groups associated |
592 { | 616 { |
593 /* Error! */ | 617 /* Error! */ |
594 gaim_debug_warning("oscar", "Expecting FLAP version " | 618 gaim_debug_warning("oscar", "Expecting FLAP version " |
595 "0x00000001 but received FLAP version %08lx. Closing connection.\n", | 619 "0x00000001 but received FLAP version %08lx. Closing connection.\n", |
596 flap_version); | 620 flap_version); |
597 flap_connection_schedule_destroy(conn); | 621 flap_connection_schedule_destroy(conn, |
622 OSCAR_DISCONNECT_INVALID_DATA); | |
598 } | 623 } |
599 else | 624 else |
600 conn->connected = TRUE; | 625 conn->connected = TRUE; |
601 | 626 |
602 } else if (frame->channel == 0x02) { | 627 } else if (frame->channel == 0x02) { |
636 read = recv(conn->fd, &header, 6, MSG_PEEK); | 661 read = recv(conn->fd, &header, 6, MSG_PEEK); |
637 | 662 |
638 /* Check if the FLAP server closed the connection */ | 663 /* Check if the FLAP server closed the connection */ |
639 if (read == 0) | 664 if (read == 0) |
640 { | 665 { |
641 /* TODO: Print an error? Server closed connection. */ | 666 flap_connection_schedule_destroy(conn, |
642 flap_connection_schedule_destroy(conn); | 667 OSCAR_DISCONNECT_REMOTE_CLOSED); |
643 break; | 668 break; |
644 } | 669 } |
645 | 670 |
646 /* If there was an error then close the connection */ | 671 /* If there was an error then close the connection */ |
647 if (read == -1) | 672 if (read == -1) |
649 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) | 674 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) |
650 /* No worries */ | 675 /* No worries */ |
651 break; | 676 break; |
652 | 677 |
653 /* Error! */ | 678 /* Error! */ |
654 /* TODO: Print an error? Lost connection with server. */ | 679 flap_connection_schedule_destroy(conn, |
655 flap_connection_schedule_destroy(conn); | 680 OSCAR_DISCONNECT_LOST_CONNECTION); |
656 break; | 681 break; |
657 } | 682 } |
658 | 683 |
659 /* If we don't even have a complete FLAP header then do nothing */ | 684 /* If we don't even have a complete FLAP header then do nothing */ |
660 if (read < 6) | 685 if (read < 6) |
664 read = recv(conn->fd, &header, 6, 0); | 689 read = recv(conn->fd, &header, 6, 0); |
665 | 690 |
666 /* All FLAP frames must start with the byte 0x2a */ | 691 /* All FLAP frames must start with the byte 0x2a */ |
667 if (aimutil_get8(&header[0]) != 0x2a) | 692 if (aimutil_get8(&header[0]) != 0x2a) |
668 { | 693 { |
669 flap_connection_schedule_destroy(conn); | 694 flap_connection_schedule_destroy(conn, |
695 OSCAR_DISCONNECT_INVALID_DATA); | |
670 break; | 696 break; |
671 } | 697 } |
672 | 698 |
673 /* Initialize a new temporary FlapFrame for incoming data */ | 699 /* Initialize a new temporary FlapFrame for incoming data */ |
674 conn->buffer_incoming.channel = aimutil_get8(&header[1]); | 700 conn->buffer_incoming.channel = aimutil_get8(&header[1]); |
687 0); | 713 0); |
688 | 714 |
689 /* Check if the FLAP server closed the connection */ | 715 /* Check if the FLAP server closed the connection */ |
690 if (read == 0) | 716 if (read == 0) |
691 { | 717 { |
692 flap_connection_schedule_destroy(conn); | 718 flap_connection_schedule_destroy(conn, |
719 OSCAR_DISCONNECT_REMOTE_CLOSED); | |
693 break; | 720 break; |
694 } | 721 } |
695 | 722 |
696 if (read == -1) | 723 if (read == -1) |
697 { | 724 { |
698 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) | 725 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) |
699 /* No worries */ | 726 /* No worries */ |
700 break; | 727 break; |
701 | 728 |
702 /* Error! */ | 729 /* Error! */ |
703 /* TODO: Print an error? Lost connection with server. */ | 730 flap_connection_schedule_destroy(conn, |
704 flap_connection_schedule_destroy(conn); | 731 OSCAR_DISCONNECT_LOST_CONNECTION); |
705 break; | 732 break; |
706 } | 733 } |
707 | 734 |
708 conn->buffer_incoming.data.offset += read; | 735 conn->buffer_incoming.data.offset += read; |
709 if (conn->buffer_incoming.data.offset < conn->buffer_incoming.data.len) | 736 if (conn->buffer_incoming.data.offset < conn->buffer_incoming.data.len) |
743 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) | 770 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) |
744 /* No worries */ | 771 /* No worries */ |
745 return; | 772 return; |
746 | 773 |
747 /* Error! */ | 774 /* Error! */ |
748 flap_connection_schedule_destroy(conn); | 775 flap_connection_schedule_destroy(conn, OSCAR_DISCONNECT_LOST_CONNECTION); |
749 return; | 776 return; |
750 } | 777 } |
751 | 778 |
752 gaim_circ_buffer_mark_read(conn->buffer_outgoing, ret); | 779 gaim_circ_buffer_mark_read(conn->buffer_outgoing, ret); |
753 } | 780 } |