diff options
Diffstat (limited to '')
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | src/directory.c | 2 | ||||
-rw-r--r-- | src/interface.c | 5 | ||||
-rw-r--r-- | src/listen.c | 107 | ||||
-rw-r--r-- | src/listen.h | 16 | ||||
-rw-r--r-- | src/main.c | 9 | ||||
-rw-r--r-- | src/player.c | 2 |
7 files changed, 97 insertions, 48 deletions
@@ -1,9 +1,5 @@ 0.12 ---- -*) network stuff - *) allow specifying multiple bind_to_address's - *) use getaddrinfo instead of gethostbyname - *) rewrite saved playlist code *) abstract out saved playlists from playlist.c *) command for displaying playlist contents diff --git a/src/directory.c b/src/directory.c index 5caeb311d..38043276f 100644 --- a/src/directory.c +++ b/src/directory.c @@ -193,7 +193,7 @@ int updateInit(FILE * fp, List * pathList) { unblockSignals(); finishSigHandlers(); - close(listenSocket); + closeAllListenSockets(); freeAllInterfaces(); finishPlaylist(); finishVolume(); diff --git a/src/interface.c b/src/interface.c index 72c71f911..d2ae43a8d 100644 --- a/src/interface.c +++ b/src/interface.c @@ -337,8 +337,7 @@ void addInterfacesReadyToReadAndListenSocketToFdSet(fd_set * fds, int * fdmax) { int i; FD_ZERO(fds); - FD_SET(listenSocket,fds); - if(*fdmax<listenSocket) *fdmax = listenSocket; + addListenSocketsToFdSet(fds, fdmax); for(i=0;i<interface_max_connections;i++) { if(interfaces[i].open && !interfaces[i].expired && !interfaces[i].bufferList) { @@ -396,7 +395,7 @@ int doIOForInterfaces() { addInterfacesForBufferFlushToFdSet(&wfds,&fdmax); while((selret = select(fdmax+1,&rfds,&wfds,NULL,&tv))) { - if(FD_ISSET(listenSocket,&rfds)) getConnections(listenSocket); + getConnections(&rfds); if(selret<0 && errno==EINTR) break; else if(selret<0) { closeNextErroredInterface(); diff --git a/src/listen.c b/src/listen.c index cb0bfa149..cac9492b8 100644 --- a/src/listen.c +++ b/src/listen.c @@ -41,10 +41,10 @@ #define ALLOW_REUSE 1 -int listenSocket; +int * listenSockets = NULL; +int numberOfListenSockets = 0; -int establish(unsigned short port) { - ConfigParam * param; +static int establishListen(unsigned int port, ConfigParam * param) { int allowReuse = ALLOW_REUSE; int sock; struct sockaddr * addrp; @@ -62,9 +62,8 @@ int establish(unsigned short port) { sin.sin_port = htons(port); sin.sin_family = AF_INET; - param = getConfigParam(CONF_BIND_TO_ADDRESS); - - if(!param || 0==strcmp(param->value, "any")==0) { + if(!param || 0==strcmp(param->value, "any")) { + DEBUG("binding to any address\n"); #ifdef HAVE_IPV6 if(ipv6Supported()) { sin6.sin6_addr = in6addr_any; @@ -81,6 +80,7 @@ int establish(unsigned short port) { } else { struct hostent * he; + DEBUG("binding to address for %s\n", param->value); if(!(he = gethostbyname(param->value))) { ERROR("can't lookup host \"%s\" at line %i\n", param->value, param->line); @@ -129,53 +129,102 @@ int establish(unsigned short port) { break; default: ERROR("unknown address family: %i\n",addrp->sa_family); - return -1; + exit(EXIT_FAILURE); } if((sock = socket(pf,SOCK_STREAM,0)) < 0) { ERROR("socket < 0\n"); - return -1; + exit(EXIT_FAILURE); + } + + if(fcntl(sock, F_SETFL ,fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) { + ERROR("problems setting nonblocking on listen socket: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); } if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&allowReuse, sizeof(allowReuse))<0) { - close(sock); ERROR("problems setsockopt'ing\n"); - return -1; + exit(EXIT_FAILURE); } if(bind(sock,addrp,addrlen)<0) { - ERROR("unable to bind port %i, maybe MPD is still running?\n", - port); - close(sock); - return -1; + ERROR("unable to bind port %i: %s\n", port, strerror(errno)); + ERROR("maybe MPD is still running?\n"); + exit(EXIT_FAILURE); } if(listen(sock,5)<0) { - close(sock); - ERROR("problems listen'ing\n"); - return -1; + ERROR("problems listen'ing: %s\n", strerror(errno)); + exit(EXIT_FAILURE); } return sock; } -void getConnections(int sock) { - fd_set fdsr; +void establish(unsigned int port) { + ConfigParam * param = getNextConfigParam(CONF_BIND_TO_ADDRESS, NULL); + + do { + numberOfListenSockets++; + listenSockets = realloc(listenSockets, + sizeof(int)*numberOfListenSockets); + + listenSockets[numberOfListenSockets-1] = + establishListen(port, param); + } while ((param = getNextConfigParam(CONF_BIND_TO_ADDRESS, param))); +} + +void addListenSocketsToFdSet(fd_set * fds, int * fdmax) { + int i; + + for(i=0; i<numberOfListenSockets; i++) { + FD_SET(listenSockets[i], fds); + if(listenSockets[i] > *fdmax) *fdmax = listenSockets[i]; + } +} + +void closeAllListenSockets() { + int i; + + DEBUG("closeAllListenSockets called\n"); + + for(i=0; i<numberOfListenSockets; i++) { + DEBUG("closing listen scoket %i\n", i); + while(close(listenSockets[i]) < 0 && errno==EINTR); + } + + numberOfListenSockets = 0; + free(listenSockets); + listenSockets = NULL; +} + +int isAListenSocket(int socket) { + int i; + + for(i=0; listenSockets[i] != socket && i<numberOfListenSockets; i++); + + return (i < numberOfListenSockets); +} + +void getConnections(fd_set * fds) { + int i; int fd = 0; - struct timeval tv; struct sockaddr sockAddr; socklen_t socklen = sizeof(sockAddr); - tv.tv_sec = tv.tv_usec = 0; - - fflush(NULL); - FD_ZERO(&fdsr); - FD_SET(sock,&fdsr); - if(select(sock+1,&fdsr,NULL,NULL,&tv)==1 && - ((fd = accept(sock,&sockAddr,&socklen)) >= 0)) { - openAInterface(fd,&sockAddr); + for(i=0; i<numberOfListenSockets; i++) { + if(FD_ISSET(listenSockets[i], fds)) { + if((fd = accept(listenSockets[i], &sockAddr, &socklen)) + >= 0) + { + openAInterface(fd,&sockAddr); + } + else if(fd<0 && (errno!=EAGAIN && errno!=EINTR)) { + ERROR("Problems accept()'ing\n"); + } + } } - else if(fd<0) ERROR("Problems accept()'ing\n"); } diff --git a/src/listen.h b/src/listen.h index dd5e32d8c..1030d9b19 100644 --- a/src/listen.h +++ b/src/listen.h @@ -21,10 +21,20 @@ #include "../config.h" -extern int listenSocket; +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> -int establish(unsigned short port); +void establish(unsigned int port); -void getConnections(int sock); +void getConnections(fd_set * fds); + +int isAListenSocket(int sock); + +void closeAllListenSockets(); + +/* fdmax should be initialized to something */ +void addListenSocketsToFdSet(fd_set * fds, int * fdmax); #endif diff --git a/src/main.c b/src/main.c index 2160a1ccd..bb1146cb0 100644 --- a/src/main.c +++ b/src/main.c @@ -226,12 +226,7 @@ void establishListen(Options * options) { exit(EXIT_FAILURE); } - if(options->createDB <= 0 && !options->updateDB && - (listenSocket = establish(port))<0) - { - ERROR("error binding port\n"); - exit(EXIT_FAILURE); - } + if(options->createDB <= 0 && !options->updateDB) establish(port); } void changeToUser(Options * options) { @@ -453,7 +448,7 @@ int main(int argc, char * argv[]) { playerKill(); freeAllInterfaces(); - close(listenSocket); + closeAllListenSockets(); closeMp3Directory(); closeTables(); finishPlaylist(); diff --git a/src/player.c b/src/player.c index cb9b5ed1c..c16cad22e 100644 --- a/src/player.c +++ b/src/player.c @@ -112,7 +112,7 @@ int playerInit() { setSigHandlersForDecoder(); - while(close(listenSocket)<0 && errno==EINTR); + closeAllListenSockets(); freeAllInterfaces(); closeMp3Directory(); finishPlaylist(); |