aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO4
-rw-r--r--src/directory.c2
-rw-r--r--src/interface.c5
-rw-r--r--src/listen.c107
-rw-r--r--src/listen.h16
-rw-r--r--src/main.c9
-rw-r--r--src/player.c2
7 files changed, 97 insertions, 48 deletions
diff --git a/TODO b/TODO
index 7a32f20a5..42a456dfe 100644
--- a/TODO
+++ b/TODO
@@ -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();