Patch re: the "IPv6" connection code
Adam M <[email protected]> Sun, 27 Mar 2005 17:48:36 -0600
| Newsgroups | gmane.comp.multimedia.xmms.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi all, It looks like I forgot to attach the patch last time. Anyway, this time it is attached. Please look at my other email for exact reason for the patch. You will also see a comment about the need for whitespace cleanup. It basically involves removing of the extra braces and deleting one tab all the way down. I haven't done that to make the patch easier to read. The changes in mpg123 and vorbis are essentially identical as both use the same connection code. This patch also fixes a race condition in the connection code. The `eof` global static flag should never be set in the connection code unless the connection fails. If you have questions, concerns, please ask. - Adam PS. *Some* IPv6/IPv4 specific code remains in the UDP listener, so the IPV6 compile flag remains. PPS. What is the point of the UDP listener in mpg123? Is it really needed? _______________________________________________ xmms-devel mailing list [email protected] http://lists.xmms.org/mailman/listinfo/xmms-devel
xmms.diff
(text/x-patch, 9.4 KB)
Index: Input/cdaudio/http.c
===================================================================
RCS file: /cvs/xmms/Input/cdaudio/http.c,v
retrieving revision 1.7
diff -u -r1.7 http.c
--- Input/cdaudio/http.c 1 Sep 2003 20:18:15 -0000 1.7
+++ Input/cdaudio/http.c 27 Mar 2005 23:37:13 -0000
@@ -25,18 +25,13 @@
gint http_open_connection(gchar * server, gint port)
{
gint sock;
-#ifdef USE_IPV6
struct addrinfo hints, *res, *res0;
char service[6];
-#else
- struct hostent *host;
- struct sockaddr_in address;
-#endif
-#ifdef USE_IPV6
g_snprintf(service, 6, "%d", port);
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
if (getaddrinfo(server, service, &hints, &res0))
return 0;
@@ -60,24 +55,13 @@
return 0;
}
}
+ /* Connection is established */
freeaddrinfo(res0);
return sock;
}
-#else
- sock = socket(AF_INET, SOCK_STREAM, 0);
- address.sin_family = AF_INET;
- if (!(host = gethostbyname(server)))
- return 0;
-
- memcpy(&address.sin_addr.s_addr, *(host->h_addr_list), sizeof(address.sin_addr.s_addr));
- address.sin_port = g_htons(port);
-
- if (connect(sock, (struct sockaddr *) &address, sizeof (struct sockaddr_in)) == -1)
- return 0;
-
-#endif
- return sock;
+ /* No connetion established, so we return 0 */
+ return 0;
}
void http_close_connection(gint sock)
Index: Input/mpg123/http.c
===================================================================
RCS file: /cvs/xmms/Input/mpg123/http.c,v
retrieving revision 1.32
diff -u -r1.32 http.c
--- Input/mpg123/http.c 7 Dec 2003 17:09:41 -0000 1.32
+++ Input/mpg123/http.c 27 Mar 2005 23:37:13 -0000
@@ -332,13 +332,8 @@
gboolean redirect;
int udp_sock = 0;
fd_set set;
-#ifdef USE_IPV6
struct addrinfo hints, *res, *res0;
char service[6];
-#else
- struct hostent *hp;
- struct sockaddr_in address;
-#endif
struct timeval tv;
url = (gchar *) arg;
@@ -360,12 +355,13 @@
chost = mpg123_cfg.use_proxy ? mpg123_cfg.proxy_host : host;
cport = mpg123_cfg.use_proxy ? mpg123_cfg.proxy_port : port;
-#ifdef USE_IPV6
g_snprintf(service, 6, "%d", cport);
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
if (! getaddrinfo(chost, service, &hints, &res0)) {
- eof = TRUE;
+ int connected = 0;
+
for (res = res0; res; res = res->ai_next) {
if ((sock = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
continue;
@@ -375,20 +371,42 @@
g_free(status);
((struct sockaddr_in6 *)res->ai_addr)->sin6_port = htons(cport);
if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
+
if (errno != EINPROGRESS) {
close(sock);
continue;
}
+ /* We are EINPROGRESS. We need to wait here until we are connected as otherwise we
+ * will never get to other addresses.
+ */
+ while (going) {
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(sock, &set);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ if (select(sock + 1, NULL, &set, NULL, &tv) > 0) {
+ err_len = sizeof (error);
+ getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &err_len);
+ if (error == 0)
+ connected = 1;
+ break;
+ }
+ else if( errno == EBADF || error == ENOMEM )
+ break; /* Select failures - break to avoid possible infinite loop */
+ }
}
- eof = FALSE;
- break;
+ if( connected )
+ break;
}
freeaddrinfo(res0);
- if (eof) {
+ if (!connected) {
status = g_strdup_printf(_("Couldn't connect to host %s:%d"), chost, cport);
show_error_message(status);
g_free(status);
mpg123_ip.set_info_text(NULL);
+ eof = TRUE;
}
} else {
status = g_strdup_printf(_("Couldn't look up host %s"), chost);
@@ -398,74 +416,10 @@
mpg123_ip.set_info_text(NULL);
eof = TRUE;
}
-#else
- sock = socket(AF_INET, SOCK_STREAM, 0);
- fcntl(sock, F_SETFL, O_NONBLOCK);
- address.sin_family = AF_INET;
-
- status = g_strdup_printf(_("LOOKING UP %s"), chost);
- mpg123_ip.set_info_text(status);
- g_free(status);
-
- if (!(hp = gethostbyname(chost)))
- {
- status = g_strdup_printf(_("Couldn't look up host %s"), chost);
- show_error_message(status);
- g_free(status);
-
- mpg123_ip.set_info_text(NULL);
- eof = TRUE;
- }
-#endif
if (!eof)
{
-#ifndef USE_IPV6
- memcpy(&address.sin_addr.s_addr, *(hp->h_addr_list), sizeof (address.sin_addr.s_addr));
- address.sin_port = g_htons(cport);
-
- status = g_strdup_printf(_("CONNECTING TO %s:%d"), chost, cport);
- mpg123_ip.set_info_text(status);
- g_free(status);
- if (connect(sock, (struct sockaddr *) &address, sizeof (struct sockaddr_in)) == -1)
- {
- if (errno != EINPROGRESS)
- {
- status = g_strdup_printf(_("Couldn't connect to host %s"), chost);
- show_error_message(status);
- g_free(status);
-
- mpg123_ip.set_info_text(NULL);
- eof = TRUE;
- }
- }
-#endif
- while (going)
- {
- tv.tv_sec = 0;
- tv.tv_usec = 10000;
- FD_ZERO(&set);
- FD_SET(sock, &set);
- if (select(sock + 1, NULL, &set, NULL, &tv) > 0)
- {
- err_len = sizeof (error);
- getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &err_len);
- if (error)
- {
- status = g_strdup_printf(_("Couldn't connect to host %s"),
- chost);
- show_error_message(status);
- g_free(status);
-
- mpg123_ip.set_info_text(NULL);
- eof = TRUE;
-
- }
- break;
- }
- }
- if (!eof)
- {
+ { /* TODO: cleanup whitespace */
gchar *auth = NULL, *proxy_auth = NULL;
gchar udpspace[30];
int udp_port;
Index: Input/vorbis/http.c
===================================================================
RCS file: /cvs/xmms/Input/vorbis/http.c,v
retrieving revision 1.6
diff -u -r1.6 http.c
--- Input/vorbis/http.c 1 Sep 2003 20:18:30 -0000 1.6
+++ Input/vorbis/http.c 27 Mar 2005 23:37:13 -0000
@@ -287,13 +287,8 @@
gint cnt, written, error, err_len, port, cport;
gboolean redirect;
fd_set set;
-#ifdef USE_IPV6
struct addrinfo hints, *res, *res0;
char service[6];
-#else
- struct hostent *hp;
- struct sockaddr_in address;
-#endif
struct timeval tv;
url = (gchar *) arg;
@@ -315,12 +310,12 @@
chost = vorbis_cfg.use_proxy ? vorbis_cfg.proxy_host : host;
cport = vorbis_cfg.use_proxy ? vorbis_cfg.proxy_port : port;
-#ifdef USE_IPV6
g_snprintf(service, 6, "%d", cport);
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = PF_UNSPEC;
if (! getaddrinfo(chost, service, &hints, &res0)) {
- eof = TRUE;
+ int connected = 0;
for (res = res0; res; res = res->ai_next) {
if ((sock = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
continue;
@@ -334,12 +329,32 @@
close(sock);
continue;
}
+ /* We are EINPROGRESS. We need to wait here until we are connected as otherwise we
+ * will never get to other addresses.
+ */
+ while (going) {
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(sock, &set);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ if (select(sock + 1, NULL, &set, NULL, &tv) > 0) {
+ err_len = sizeof (error);
+ getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &err_len);
+ if (error == 0)
+ connected = 1;
+ break;
+ }
+ else if( errno == EBADF || error == ENOMEM )
+ break; /* Select failures - break to avoid possible infinite loop */
+ }
}
- eof = FALSE;
- break;
+ if(connected)
+ break;
}
freeaddrinfo(res0);
- if (eof) {
+ if (!connected) {
status = g_strdup_printf(_("Couldn't connect to host %s:%d"), chost, cport);
vorbis_ip.set_info_text(status);
g_free(status);
@@ -352,74 +367,10 @@
g_free(status);
eof = TRUE;
}
-#else
- sock = socket(AF_INET, SOCK_STREAM, 0);
- fcntl(sock, F_SETFL, O_NONBLOCK);
- address.sin_family = AF_INET;
-
- status = g_strdup_printf(_("LOOKING UP %s"), chost);
- vorbis_ip.set_info_text(status);
- g_free(status);
-
- if (!(hp = gethostbyname(chost)))
- {
- status = g_strdup_printf(_("Couldn't look up host %s"), chost);
- show_error_message(status);
- g_free(status);
-
- vorbis_ip.set_info_text(NULL);
- eof = TRUE;
- }
-#endif
if (!eof)
{
-#ifndef USE_IPV6
- memcpy(&address.sin_addr.s_addr, *(hp->h_addr_list), sizeof (address.sin_addr.s_addr));
- address.sin_port = g_htons(cport);
-
- status = g_strdup_printf(_("CONNECTING TO %s:%d"), chost, cport);
- vorbis_ip.set_info_text(status);
- g_free(status);
- if (connect(sock, (struct sockaddr *) &address, sizeof (struct sockaddr_in)) == -1)
- {
- if (errno != EINPROGRESS)
- {
- status = g_strdup_printf(_("Couldn't connect to host %s"), chost);
- show_error_message(status);
- g_free(status);
-
- vorbis_ip.set_info_text(NULL);
- eof = TRUE;
- }
- }
-#endif
- while (going)
- {
- tv.tv_sec = 0;
- tv.tv_usec = 10000;
- FD_ZERO(&set);
- FD_SET(sock, &set);
- if (select(sock + 1, NULL, &set, NULL, &tv) > 0)
- {
- err_len = sizeof (error);
- getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &err_len);
- if (error)
- {
- status = g_strdup_printf(_("Couldn't connect to host %s"),
- chost);
- show_error_message(status);
- g_free(status);
-
- vorbis_ip.set_info_text(NULL);
- eof = TRUE;
-
- }
- break;
- }
- }
- if (!eof)
- {
+ { /* TODO: Cleanup whitespace */
gchar *auth = NULL, *proxy_auth = NULL;
if(user && pass)