serversocket-remove-unused-variable-res-in-eServerSo
[openblackhole/openblackhole-enigma2.git] / lib / network / serversocket.cpp
1 #include <errno.h>
2 #include <string.h>
3 #include <lib/network/serversocket.h>
4 #include <arpa/inet.h>
5
6 bool eServerSocket::ok()
7 {
8         return okflag;
9 }
10
11 void eServerSocket::notifier(int)
12 {
13         int clientfd;
14         socklen_t clientlen;
15         struct sockaddr client_addr;
16         char straddr[INET6_ADDRSTRLEN];
17
18 #ifdef DEBUG_SERVERSOCKET
19         eDebug("[eServerSocket] incoming connection!");
20 #endif
21
22         clientlen = sizeof(client_addr);
23         clientfd = accept(getDescriptor(), &client_addr, &clientlen);
24         if (clientfd < 0)
25         {
26                 eDebug("[eServerSocket] error on accept: %m");
27                 return;
28         }
29
30         if (client_addr.sa_family == AF_LOCAL)
31         {
32                 strRemoteHost = "(local)";
33         }
34         else
35         {
36                 strRemoteHost = inet_ntop(client_addr.sa_family, client_addr.sa_data, straddr, sizeof(straddr));
37         }
38         newConnection(clientfd);
39 }
40
41 eServerSocket::eServerSocket(int port, eMainloop *ml): eSocket(ml)
42 {
43         int res;
44         struct addrinfo *addr = NULL;
45         struct addrinfo hints;
46         char portnumber[16];
47
48         okflag = 0;
49         strRemoteHost = "";
50
51         memset(&hints, 0, sizeof(hints));
52         hints.ai_family = AF_UNSPEC; /* both ipv4 and ipv6 */
53         hints.ai_socktype = SOCK_STREAM;
54         hints.ai_protocol = 0; /* any */
55 #ifdef AI_ADDRCONFIG
56         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 */
57 #else
58         hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* AI_ADDRCONFIG is not available */
59 #endif
60         snprintf(portnumber, sizeof(portnumber), "%d", port);
61
62         if ((res = getaddrinfo(NULL, portnumber, &hints, &addr)) || !addr)
63         {
64                 eDebug("[eServerSocket] getaddrinfo: %s", gai_strerror(res));
65                 return;
66         }
67
68         if (startListening(addr) >= 0)
69         {
70                 okflag = 1;
71                 rsn->setRequested(eSocketNotifier::Read);
72         }
73         freeaddrinfo(addr);
74 }
75
76 eServerSocket::eServerSocket(std::string path, eMainloop *ml) : eSocket(ml)
77 {
78         struct sockaddr_un serv_addr_un;
79         struct addrinfo addr;
80
81         okflag = 0;
82         strRemoteHost = "";
83
84         memset(&serv_addr_un, 0, sizeof(serv_addr_un));
85         serv_addr_un.sun_family = AF_LOCAL;
86         strcpy(serv_addr_un.sun_path, path.c_str());
87
88         memset(&addr, 0, sizeof(addr));
89         addr.ai_family = AF_LOCAL;
90         addr.ai_socktype = SOCK_STREAM;
91         addr.ai_protocol = 0; /* any */
92         addr.ai_addr = (struct sockaddr *)&serv_addr_un;
93         addr.ai_addrlen = sizeof(serv_addr_un);
94
95         unlink(path.c_str());
96
97         if (startListening(&addr) >= 0)
98         {
99                 okflag = 1;
100                 rsn->setRequested(eSocketNotifier::Read);
101         }
102 }
103
104 eServerSocket::~eServerSocket()
105 {
106 #ifdef DEBUG_SERVERSOCKET
107         eDebug("[eServerSocket] destructed");
108 #endif
109 }
110
111 int eServerSocket::startListening(struct addrinfo *addr)
112 {
113         struct addrinfo *ptr = addr;
114         for (ptr = addr; ptr != NULL; ptr = ptr->ai_next)
115         {
116                 if (setSocket(socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol), 1) < 0)
117                 {
118                         continue;
119                 }
120
121                 int val = 1;
122                 setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
123
124                 if (bind(getDescriptor(), ptr->ai_addr, ptr->ai_addrlen) < 0)
125                 {
126                         eDebug("[eServerSocket] ERROR on bind: %m");
127                         close();
128                         continue;
129                 }
130         }
131
132         if (getDescriptor() < 0)
133         {
134                 return -1;
135         }
136
137         if (listen(getDescriptor(), 0) < 0)
138         {
139                 close();
140                 return -1;
141         }
142         return 0;
143 }
144
145 int eServerSocket::bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)
146 {
147         int result;
148         while (1)
149         {
150                 if ((result = ::bind(sockfd, addr, addrlen)) < 0 && errno == EINTR) continue;
151                 break;
152         }
153         return result;
154 }
155
156 int eServerSocket::listen(int sockfd, int backlog)
157 {
158         int result;
159         while (1)
160         {
161                 if ((result = ::listen(sockfd, backlog)) < 0 && errno == EINTR) continue;
162                 break;
163         }
164         return result;
165 }
166
167 int eServerSocket::accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
168 {
169         int result;
170         while (1)
171         {
172                 if ((result = ::accept(sockfd, addr, addrlen)) < 0 && errno == EINTR) continue;
173                 break;
174         }
175         return result;
176 }