Hello,
I found a bug in Icecast-2.3.2. SVN trunk is affected either. The problem lies
in src/net/sock.c: sock_connected() function.
This function is used to check status of socket after nonblocking connect(2)
and it has two implementations: select(2) and poll(2). The select branch does
the right job---it gets socket status by getsockopt(2) after selecting for
write. But the poll branch does not. To make things wrong, the poll
implementaion takes precedense.
The bug makes icecast thinking the connection succeded even it's not true. You
can reproduce the bug by requesting mount point pointing to
<
http://fm4.nobody.at:8080/fm4-mq.ogg>. Given domain name has both AAAA and
A records, but the AAAA is unreachable. Current code failes on writing request
to the server and it does not try another IP address to connect to.
I copied the code from select implementation into poll branch and it fixed the
problem. Patch follows.
-- Petr
Index: src/net/sock.c
===================================================================
--- src/net/sock.c (revision 16208)
+++ src/net/sock.c (working copy)
@@ -516,17 +516,27 @@
int sock_connected (sock_t sock, int timeout)
{
struct pollfd check;
+ int val = SOCK_ERROR;
+ socklen_t size = sizeof val;
check.fd = sock;
check.events = POLLOUT;
switch (poll (&check, 1, timeout*1000))
{
case 0: return SOCK_TIMEOUT;
+ default:
+ /* on windows getsockopt.val is defined as char* */
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*) &val, &size) == 0)
+ {
+ if (val == 0)
+ return 1;
+ sock_set_error (val);
+ }
+ /* fall through */
case -1:
if (sock_recoverable (sock_error()))
return 0;
return SOCK_ERROR;
- default: return 1;
}
}
_______________________________________________
Icecast-dev mailing list
Icecast-dev@...
http://lists.xiph.org/mailman/listinfo/icecast-dev