Merge pull request #121 from Dima73/timer
[openblackhole/openblackhole-enigma2.git] / lib / network / serversocket.cpp
index 093e7f9..14cfb2a 100644 (file)
@@ -1,4 +1,5 @@
 #include <errno.h>
 #include <errno.h>
+#include <string.h>
 #include <lib/network/serversocket.h>
 #include <arpa/inet.h>
 
 #include <lib/network/serversocket.h>
 #include <arpa/inet.h>
 
@@ -9,82 +10,138 @@ bool eServerSocket::ok()
 
 void eServerSocket::notifier(int)
 {
 
 void eServerSocket::notifier(int)
 {
-       int clientfd, clientlen;
-       struct sockaddr_in client_addr;
+       int clientfd;
+       socklen_t clientlen;
+       struct sockaddr client_addr;
+       char straddr[INET6_ADDRSTRLEN];
 
 #ifdef DEBUG_SERVERSOCKET
 
 #ifdef DEBUG_SERVERSOCKET
-       eDebug("[SERVERSOCKET] incoming connection!");
+       eDebug("[eServerSocket] incoming connection!");
 #endif
 
 #endif
 
-       clientlen=sizeof(client_addr);
-       clientfd=accept(getDescriptor(),
-                       (struct sockaddr *) &client_addr,
-                       (socklen_t*)&clientlen);
-       if(clientfd<0)
-               eDebug("[SERVERSOCKET] error on accept()");
+       clientlen = sizeof(client_addr);
+       clientfd = accept(getDescriptor(), &client_addr, &clientlen);
+       if (clientfd < 0)
+       {
+               eDebug("[eServerSocket] error on accept: %m");
+               return;
+       }
 
 
-       strRemoteHost = inet_ntoa(client_addr.sin_addr);
+       if (client_addr.sa_family == AF_LOCAL)
+       {
+               strRemoteHost = "(local)";
+       }
+       else
+       {
+               strRemoteHost = inet_ntop(client_addr.sa_family, client_addr.sa_data, straddr, sizeof(straddr));
+       }
        newConnection(clientfd);
 }
 
 eServerSocket::eServerSocket(int port, eMainloop *ml): eSocket(ml)
 {
        newConnection(clientfd);
 }
 
 eServerSocket::eServerSocket(int port, eMainloop *ml): eSocket(ml)
 {
-       struct sockaddr_in serv_addr;
-       strRemoteHost = "";
+       int res;
+       struct addrinfo *addr = NULL;
+       struct addrinfo hints;
+       char portnumber[16];
 
 
-       bzero(&serv_addr, sizeof(serv_addr));
-       serv_addr.sin_family=AF_INET;
-       serv_addr.sin_addr.s_addr=INADDR_ANY;
-       serv_addr.sin_port=htons(port);
-
-       okflag=1;
-       int val=1;
+       okflag = 0;
+       strRemoteHost = "";
 
 
-       setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = AF_UNSPEC; /* both ipv4 and ipv6 */
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_protocol = 0; /* any */
+#ifdef AI_ADDRCONFIG
+       hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_ADDRCONFIG; /* only return ipv6 if we have an ipv6 address ourselves, and ipv4 if we have an ipv4 address ourselves */
+#else
+       hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* AI_ADDRCONFIG is not available */
+#endif
+       snprintf(portnumber, sizeof(portnumber), "%d", port);
 
 
-       if(bind(getDescriptor(),
-               (struct sockaddr *) &serv_addr,
-               sizeof(serv_addr))<0)
+       if ((res = getaddrinfo(NULL, portnumber, &hints, &addr)) || !addr)
        {
        {
-               eDebug("[SERVERSOCKET] ERROR on bind() (%m)");
-               okflag=0;
+               eDebug("[eServerSocket] getaddrinfo: %s", gai_strerror(res));
+               return;
        }
        }
-       listen(getDescriptor(), 0);
 
 
-       rsn->setRequested(eSocketNotifier::Read);
+       if (startListening(addr) >= 0)
+       {
+               okflag = 1;
+               rsn->setRequested(eSocketNotifier::Read);
+       }
+       freeaddrinfo(addr);
 }
 
 }
 
-eServerSocket::eServerSocket(std::string path, eMainloop *ml) : eSocket(ml, AF_LOCAL)
+eServerSocket::eServerSocket(std::string path, eMainloop *ml) : eSocket(ml)
 {
 {
-       struct sockaddr_un serv_addr;
+       struct sockaddr_un serv_addr_un;
+       struct addrinfo addr;
+
+       okflag = 0;
        strRemoteHost = "";
 
        strRemoteHost = "";
 
-       memset(&serv_addr, 0, sizeof(serv_addr));
-       serv_addr.sun_family = AF_LOCAL;
-       strcpy(serv_addr.sun_path, path.c_str());
+       memset(&serv_addr_un, 0, sizeof(serv_addr_un));
+       serv_addr_un.sun_family = AF_LOCAL;
+       strcpy(serv_addr_un.sun_path, path.c_str());
 
 
-       okflag=1;
+       memset(&addr, 0, sizeof(addr));
+       addr.ai_family = AF_LOCAL;
+       addr.ai_socktype = SOCK_STREAM;
+       addr.ai_protocol = 0; /* any */
+       addr.ai_addr = (struct sockaddr *)&serv_addr_un;
+       addr.ai_addrlen = sizeof(serv_addr_un);
 
        unlink(path.c_str());
 
        unlink(path.c_str());
-       if(bind(getDescriptor(),
-               (struct sockaddr *) &serv_addr,
-               sizeof(serv_addr))<0)
+
+       if (startListening(&addr) >= 0)
        {
        {
-               eDebug("[SERVERSOCKET] ERROR on bind() (%m)");
-               okflag=0;
+               okflag = 1;
+               rsn->setRequested(eSocketNotifier::Read);
        }
        }
-       listen(getDescriptor(), 0);
-
-       rsn->setRequested(eSocketNotifier::Read);
 }
 
 eServerSocket::~eServerSocket()
 {
 }
 
 eServerSocket::~eServerSocket()
 {
-#if 0
-       eDebug("[SERVERSOCKET] destructed");
+#ifdef DEBUG_SERVERSOCKET
+       eDebug("[eServerSocket] destructed");
 #endif
 }
 
 #endif
 }
 
+int eServerSocket::startListening(struct addrinfo *addr)
+{
+       struct addrinfo *ptr = addr;
+       for (ptr = addr; ptr != NULL; ptr = ptr->ai_next)
+       {
+               if (setSocket(socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol), 1) < 0)
+               {
+                       continue;
+               }
+
+               int val = 1;
+               setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+
+               if (bind(getDescriptor(), ptr->ai_addr, ptr->ai_addrlen) < 0)
+               {
+                       eDebug("[eServerSocket] ERROR on bind: %m");
+                       close();
+                       continue;
+               }
+       }
+
+       if (getDescriptor() < 0)
+       {
+               return -1;
+       }
+
+       if (listen(getDescriptor(), 0) < 0)
+       {
+               close();
+               return -1;
+       }
+       return 0;
+}
+
 int eServerSocket::bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)
 {
        int result;
 int eServerSocket::bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)
 {
        int result;