comparison libpurple/protocols/bonjour/jabber.c @ 25497:f38799160cfa

Better support running many Bonjour clients on the same machine by allowing a listening port to be specified and falling back to a system-assigned port if it can't be used. Fixes #8462.
author Daniel Atallah <daniel.atallah@gmail.com>
date Sat, 21 Feb 2009 22:10:27 +0000
parents 35d0ce5f319a
children 4b8c4870b13a
comparison
equal deleted inserted replaced
25496:7d58d7a3c5c3 25497:f38799160cfa
670 670
671 gint 671 gint
672 bonjour_jabber_start(BonjourJabber *jdata) 672 bonjour_jabber_start(BonjourJabber *jdata)
673 { 673 {
674 struct sockaddr_in my_addr; 674 struct sockaddr_in my_addr;
675 int i;
676 gboolean bind_successful;
677 675
678 /* Open a listening socket for incoming conversations */ 676 /* Open a listening socket for incoming conversations */
679 if ((jdata->socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) 677 if ((jdata->socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
680 {
681 purple_debug_error("bonjour", "Cannot open socket: %s\n", g_strerror(errno)); 678 purple_debug_error("bonjour", "Cannot open socket: %s\n", g_strerror(errno));
682 purple_connection_error_reason (jdata->account->gc, 679 purple_connection_error_reason(jdata->account->gc,
683 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 680 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
684 _("Cannot open socket")); 681 _("Cannot open socket"));
685 return -1; 682 return -1;
686 } 683 }
687 684
688 memset(&my_addr, 0, sizeof(struct sockaddr_in)); 685 memset(&my_addr, 0, sizeof(struct sockaddr_in));
689 my_addr.sin_family = AF_INET; 686 my_addr.sin_family = AF_INET;
690 687
691 /* Attempt to find a free port */ 688 /* Try to use the specified port - if it isn't available, use a random port */
692 bind_successful = FALSE; 689 my_addr.sin_port = htons(jdata->port);
693 for (i = 0; i < 10; i++) 690 if (bind(jdata->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0) {
694 { 691 purple_debug_info("bonjour", "Unable to bind to specified port %u (%s).\n", jdata->port, g_strerror(errno));
695 my_addr.sin_port = htons(jdata->port); 692 my_addr.sin_port = 0;
696 if (bind(jdata->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == 0) 693 if (bind(jdata->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0) {
697 { 694 purple_debug_error("bonjour", "Unable to bind to system assigned port (%s).\n", g_strerror(errno));
698 bind_successful = TRUE; 695 purple_connection_error_reason(jdata->account->gc,
699 break; 696 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
700 } 697 _("Could not bind socket to port"));
701 698 return -1;
702 purple_debug_info("bonjour", "Unable to bind to port %u.(%s)\n", jdata->port, g_strerror(errno)); 699 }
703 jdata->port++; 700 jdata->port = purple_network_get_port_from_fd(jdata->socket);
704 }
705
706 /* On no! We tried 10 ports and could not bind to ANY of them */
707 if (!bind_successful)
708 {
709 purple_debug_error("bonjour", "Cannot bind socket: %s\n", g_strerror(errno));
710 purple_connection_error_reason (jdata->account->gc,
711 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
712 _("Could not bind socket to port"));
713 return -1;
714 } 701 }
715 702
716 /* Attempt to listen on the bound socket */ 703 /* Attempt to listen on the bound socket */
717 if (listen(jdata->socket, 10) != 0) 704 if (listen(jdata->socket, 10) != 0) {
718 {
719 purple_debug_error("bonjour", "Cannot listen on socket: %s\n", g_strerror(errno)); 705 purple_debug_error("bonjour", "Cannot listen on socket: %s\n", g_strerror(errno));
720 purple_connection_error_reason (jdata->account->gc, 706 purple_connection_error_reason(jdata->account->gc,
721 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 707 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
722 _("Could not listen on socket")); 708 _("Could not listen on socket"));
723 return -1; 709 return -1;
724 } 710 }
725 711