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 }