@cryptotaxi247 / netdata-1 / commits / 72c91ac89

generic sockets listening functions supporting multiple sets of both TCP and UDP sockets (for later use)

Costa Tsaousis (ktsaou) committed Apr 23, 2017 at 03:32 UTC 72c91ac89a6af39a2f866fee185cfe9b9c94329b
4 files changed +251 -191
src/main.c
+1 -1
@@ -920,7 +920,7 @@ int main(int argc, char **argv) {
920 web_server_threading_selection();
921
922 if(web_server_mode != WEB_SERVER_MODE_NONE)
923 - create_listen_sockets();
923 + create_api_listen_sockets();
924 }
925
926 // initialize the log files
src/socket.c
+117 -102
@@ -1,5 +1,121 @@
1 #include "common.h"
2
3 +// _connect_to()
4 +// protocol IPPROTO_TCP, IPPROTO_UDP
5 +// socktype SOCK_STREAM, SOCK_DGRAM
6 +// host the destination hostname or IP address (IPv4 or IPv6) to connect to
7 +// if it resolves to many IPs, all are tried (IPv4 and IPv6)
8 +// scope_id the if_index id of the interface to use for connecting (0 = any)
9 +// (used only under IPv6)
10 +// service the service name or port to connect to
11 +// timeout the timeout for establishing a connection
12 +
13 +static inline int _connect_to(int protocol, int socktype, const char *host, uint32_t scope_id, const char *service, struct timeval *timeout) {
14 + struct addrinfo hints;
15 + struct addrinfo *ai_head = NULL, *ai = NULL;
16 +
17 + memset(&hints, 0, sizeof(hints));
18 + hints.ai_family = PF_UNSPEC; /* Allow IPv4 or IPv6 */
19 + hints.ai_socktype = socktype;
20 + hints.ai_protocol = protocol;
21 +
22 + int ai_err = getaddrinfo(host, service, &hints, &ai_head);
23 + if (ai_err != 0) {
24 + error("Cannot resolve host '%s', port '%s': %s", host, service, gai_strerror(ai_err));
25 + return -1;
26 + }
27 +
28 + int fd = -1;
29 + for (ai = ai_head; ai != NULL && fd == -1; ai = ai->ai_next) {
30 +
31 + if (ai->ai_family == PF_INET6) {
32 + struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr;
33 + if(pSadrIn6->sin6_scope_id == 0) {
34 + pSadrIn6->sin6_scope_id = scope_id;
35 + }
36 + }
37 +
38 + char hostBfr[NI_MAXHOST + 1];
39 + char servBfr[NI_MAXSERV + 1];
40 +
41 + getnameinfo(ai->ai_addr,
42 + ai->ai_addrlen,
43 + hostBfr,
44 + sizeof(hostBfr),
45 + servBfr,
46 + sizeof(servBfr),
47 + NI_NUMERICHOST | NI_NUMERICSERV);
48 +
49 + debug(D_CONNECT_TO, "Address info: host = '%s', service = '%s', ai_flags = 0x%02X, ai_family = %d (PF_INET = %d, PF_INET6 = %d), ai_socktype = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d), ai_protocol = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d), ai_addrlen = %lu (sockaddr_in = %lu, sockaddr_in6 = %lu)",
50 + hostBfr,
51 + servBfr,
52 + (unsigned int)ai->ai_flags,
53 + ai->ai_family,
54 + PF_INET,
55 + PF_INET6,
56 + ai->ai_socktype,
57 + SOCK_STREAM,
58 + SOCK_DGRAM,
59 + ai->ai_protocol,
60 + IPPROTO_TCP,
61 + IPPROTO_UDP,
62 + (unsigned long)ai->ai_addrlen,
63 + (unsigned long)sizeof(struct sockaddr_in),
64 + (unsigned long)sizeof(struct sockaddr_in6));
65 +
66 + switch (ai->ai_addr->sa_family) {
67 + case PF_INET: {
68 + struct sockaddr_in *pSadrIn = (struct sockaddr_in *)ai->ai_addr;
69 + debug(D_CONNECT_TO, "ai_addr = sin_family: %d (AF_INET = %d, AF_INET6 = %d), sin_addr: '%s', sin_port: '%s'",
70 + pSadrIn->sin_family,
71 + AF_INET,
72 + AF_INET6,
73 + hostBfr,
74 + servBfr);
75 + break;
76 + }
77 +
78 + case PF_INET6: {
79 + struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr;
80 + debug(D_CONNECT_TO,"ai_addr = sin6_family: %d (AF_INET = %d, AF_INET6 = %d), sin6_addr: '%s', sin6_port: '%s', sin6_flowinfo: %u, sin6_scope_id: %u",
81 + pSadrIn6->sin6_family,
82 + AF_INET,
83 + AF_INET6,
84 + hostBfr,
85 + servBfr,
86 + pSadrIn6->sin6_flowinfo,
87 + pSadrIn6->sin6_scope_id);
88 + break;
89 + }
90 +
91 + default: {
92 + debug(D_CONNECT_TO, "Unknown protocol family %d.", ai->ai_family);
93 + continue;
94 + }
95 + }
96 +
97 + fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
98 + if(fd != -1) {
99 + if(timeout) {
100 + if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) timeout, sizeof(struct timeval)) < 0)
101 + error("Failed to set timeout on the socket to ip '%s' port '%s'", hostBfr, servBfr);
102 + }
103 +
104 + if(connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
105 + error("Failed to connect to '%s', port '%s'", hostBfr, servBfr);
106 + close(fd);
107 + fd = -1;
108 + }
109 +
110 + debug(D_CONNECT_TO, "Connected to '%s' on port '%s'.", hostBfr, servBfr);
111 + }
112 + }
113 +
114 + freeaddrinfo(ai_head);
115 +
116 + return fd;
117 +}
118 +
119 // connect_to()
120 //
121 // definition format:
@@ -12,9 +128,6 @@
128 // PORT = port number or service name
129
130 int connect_to(const char *definition, int default_port, struct timeval *timeout) {
15 - struct addrinfo hints;
16 - struct addrinfo *ai_head = NULL, *ai = NULL;
17 -
131 char buffer[strlen(definition) + 1];
132 strcpy(buffer, definition);
133
@@ -78,106 +191,8 @@ int connect_to(const char *definition, int default_port, struct timeval *timeout
191 if(!*service)
192 service = default_service;
193
81 - memset(&hints, 0, sizeof(hints));
82 - hints.ai_family = PF_UNSPEC; /* Allow IPv4 or IPv6 */
83 - hints.ai_socktype = socktype;
84 - hints.ai_protocol = protocol;
85 -
86 - int ai_err = getaddrinfo(host, service, &hints, &ai_head);
87 - if (ai_err != 0) {
88 - error("Cannot resolve host '%s', port '%s': %s", host, service, gai_strerror(ai_err));
89 - return -1;
90 - }
91 -
92 - int fd = -1;
93 - for (ai = ai_head; ai != NULL && fd == -1; ai = ai->ai_next) {
94 -
95 - if (ai->ai_family == PF_INET6) {
96 - struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr;
97 - if(pSadrIn6->sin6_scope_id == 0) {
98 - pSadrIn6->sin6_scope_id = scope_id;
99 - }
100 - }
101 -
102 - char hostBfr[NI_MAXHOST + 1];
103 - char servBfr[NI_MAXSERV + 1];
104 -
105 - getnameinfo(ai->ai_addr,
106 - ai->ai_addrlen,
107 - hostBfr,
108 - sizeof(hostBfr),
109 - servBfr,
110 - sizeof(servBfr),
111 - NI_NUMERICHOST | NI_NUMERICSERV);
112 -
113 - debug(D_CONNECT_TO, "Address info: host = '%s', service = '%s', ai_flags = 0x%02X, ai_family = %d (PF_INET = %d, PF_INET6 = %d), ai_socktype = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d), ai_protocol = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d), ai_addrlen = %lu (sockaddr_in = %lu, sockaddr_in6 = %lu)",
114 - hostBfr,
115 - servBfr,
116 - (unsigned int)ai->ai_flags,
117 - ai->ai_family,
118 - PF_INET,
119 - PF_INET6,
120 - ai->ai_socktype,
121 - SOCK_STREAM,
122 - SOCK_DGRAM,
123 - ai->ai_protocol,
124 - IPPROTO_TCP,
125 - IPPROTO_UDP,
126 - (unsigned long)ai->ai_addrlen,
127 - (unsigned long)sizeof(struct sockaddr_in),
128 - (unsigned long)sizeof(struct sockaddr_in6));
129 -
130 - switch (ai->ai_addr->sa_family) {
131 - case PF_INET: {
132 - struct sockaddr_in *pSadrIn = (struct sockaddr_in *)ai->ai_addr;
133 - debug(D_CONNECT_TO, "ai_addr = sin_family: %d (AF_INET = %d, AF_INET6 = %d), sin_addr: '%s', sin_port: '%s'",
134 - pSadrIn->sin_family,
135 - AF_INET,
136 - AF_INET6,
137 - hostBfr,
138 - servBfr);
139 - break;
140 - }
141 -
142 - case PF_INET6: {
143 - struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6 *) ai->ai_addr;
144 - debug(D_CONNECT_TO,"ai_addr = sin6_family: %d (AF_INET = %d, AF_INET6 = %d), sin6_addr: '%s', sin6_port: '%s', sin6_flowinfo: %u, sin6_scope_id: %u",
145 - pSadrIn6->sin6_family,
146 - AF_INET,
147 - AF_INET6,
148 - hostBfr,
149 - servBfr,
150 - pSadrIn6->sin6_flowinfo,
151 - pSadrIn6->sin6_scope_id);
152 - break;
153 - }
154 -
155 - default: {
156 - debug(D_CONNECT_TO, "Unknown protocol family %d.", ai->ai_family);
157 - continue;
158 - }
159 - }
194
161 - fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
162 - if(fd != -1) {
163 - if(timeout) {
164 - if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) timeout, sizeof(struct timeval)) < 0)
165 - error("Failed to set timeout on the socket to ip '%s' port '%s'", hostBfr, servBfr);
166 - }
167 -
168 - if(connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
169 - error("Failed to connect to '%s', port '%s'", hostBfr, servBfr);
170 - close(fd);
171 - fd = -1;
172 - }
173 -
174 - debug(D_CONNECT_TO, "Connected to '%s' on port '%s'.", hostBfr, servBfr);
175 - }
176 - }
177 -
178 - freeaddrinfo(ai_head);
179 -
180 - return fd;
195 + return _connect_to(protocol, socktype, host, scope_id, service, timeout);
196 }
197
198 int connect_to_one_of(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size) {
src/web_server.c
+132 -86
@@ -1,15 +1,29 @@
1 #include "common.h"
2
3 -int listen_backlog = LISTEN_BACKLOG;
4 -size_t listen_fds_count = 0;
5 -int listen_fds[MAX_LISTEN_FDS] = { [0 ... 99] = -1 };
6 -char *listen_fds_names[MAX_LISTEN_FDS] = { [0 ... 99] = NULL };
7 -int listen_port = LISTEN_PORT;
3 +typedef struct listen_sockets {
4 + const char *config_section;
5 + size_t opened;
6 + size_t failed;
7 + int fds[MAX_LISTEN_FDS];
8 + char *fds_names[MAX_LISTEN_FDS];
9 + int default_port;
10 + int backlog;
11 + uint32_t flags;
12 +} LISTEN_SOCKETS;
13 +
14 +static LISTEN_SOCKETS api_sockets = {
15 + .config_section = CONFIG_SECTION_WEB,
16 + .opened = 0,
17 + .failed = 0,
18 + .fds = { [0 ... 99] = -1 },
19 + .fds_names = { [0 ... 99] = NULL },
20 + .default_port = LISTEN_PORT,
21 + .backlog = LISTEN_BACKLOG,
22 + .flags = 0
23 +};
24
25 WEB_SERVER_MODE web_server_mode = WEB_SERVER_MODE_MULTI_THREADED;
26
11 -static int shown_server_socket_error = 0;
12 -
27 #ifdef NETDATA_INTERNAL_CHECKS
28 static void log_allocations(void)
29 {
@@ -107,16 +121,15 @@ const char *web_server_mode_name(WEB_SERVER_MODE id) {
121 }
122 }
123
110 -int create_listen_socket4(const char *ip, int port, int listen_backlog) {
124 +int create_listen_socket4(int socktype, const char *ip, int port, int listen_backlog) {
125 int sock;
126 int sockopt = 1;
127
128 debug(D_LISTENER, "IPv4 creating new listening socket on ip '%s' port %d", ip, port);
129
116 - sock = socket(AF_INET, SOCK_STREAM, 0);
130 + sock = socket(AF_INET, socktype, 0);
131 if(sock < 0) {
132 error("IPv4 socket() on ip '%s' port %d failed.", ip, port);
119 - shown_server_socket_error = 1;
133 return -1;
134 }
135
@@ -132,7 +145,6 @@ int create_listen_socket4(const char *ip, int port, int listen_backlog) {
145 int ret = inet_pton(AF_INET, ip, (void *)&name.sin_addr.s_addr);
146 if(ret != 1) {
147 error("Failed to convert IP '%s' to a valid IPv4 address.", ip);
135 - shown_server_socket_error = 1;
148 close(sock);
149 return -1;
150 }
@@ -140,14 +152,12 @@ int create_listen_socket4(const char *ip, int port, int listen_backlog) {
152 if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
153 close(sock);
154 error("IPv4 bind() on ip '%s' port %d failed.", ip, port);
143 - shown_server_socket_error = 1;
155 return -1;
156 }
157
158 if(listen(sock, listen_backlog) < 0) {
159 close(sock);
160 error("IPv4 listen() on ip '%s' port %d failed.", ip, port);
150 - shown_server_socket_error = 1;
161 return -1;
162 }
163
@@ -155,17 +165,16 @@ int create_listen_socket4(const char *ip, int port, int listen_backlog) {
165 return sock;
166 }
167
158 -int create_listen_socket6(const char *ip, int port, int listen_backlog) {
168 +int create_listen_socket6(int socktype, uint32_t scope_id, const char *ip, int port, int listen_backlog) {
169 int sock = -1;
170 int sockopt = 1;
171 int ipv6only = 1;
172
173 debug(D_LISTENER, "IPv6 creating new listening socket on ip '%s' port %d", ip, port);
174
165 - sock = socket(AF_INET6, SOCK_STREAM, 0);
175 + sock = socket(AF_INET6, socktype, 0);
176 if (sock < 0) {
177 error("IPv6 socket() on ip '%s' port %d failed.", ip, port);
168 - shown_server_socket_error = 1;
178 return -1;
179 }
180
@@ -181,28 +190,26 @@ int create_listen_socket6(const char *ip, int port, int listen_backlog) {
190 memset(&name, 0, sizeof(struct sockaddr_in6));
191 name.sin6_family = AF_INET6;
192 name.sin6_port = htons ((uint16_t) port);
193 + name.sin6_scope_id = scope_id;
194
195 int ret = inet_pton(AF_INET6, ip, (void *)&name.sin6_addr.s6_addr);
196 if(ret != 1) {
197 error("Failed to convert IP '%s' to a valid IPv6 address.", ip);
188 - shown_server_socket_error = 1;
198 close(sock);
199 return -1;
200 }
201
193 - name.sin6_scope_id = 0;
202 + name.sin6_scope_id = scope_id;
203
204 if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
205 close(sock);
206 error("IPv6 bind() on ip '%s' port %d failed.", ip, port);
198 - shown_server_socket_error = 1;
207 return -1;
208 }
209
210 if (listen(sock, listen_backlog) < 0) {
211 close(sock);
212 error("IPv6 listen() on ip '%s' port %d failed.", ip, port);
205 - shown_server_socket_error = 1;
213 return -1;
214 }
215
@@ -210,46 +217,45 @@ int create_listen_socket6(const char *ip, int port, int listen_backlog) {
217 return sock;
218 }
219
213 -static inline int add_listen_socket(int fd, const char *ip, int port) {
214 - if(listen_fds_count >= MAX_LISTEN_FDS) {
215 - error("Too many listening sockets. Failed to add listening socket at ip '%s' port %d", ip, port);
216 - shown_server_socket_error = 1;
220 +static inline int add_listen_socket(LISTEN_SOCKETS *sockets, int fd, const char *protocol, const char *ip, int port) {
221 + if(sockets->opened >= MAX_LISTEN_FDS) {
222 + error("Too many listening sockets. Failed to add listening %s socket at ip '%s' port %d", protocol, ip, port);
223 close(fd);
224 return -1;
225 }
226
221 - listen_fds[listen_fds_count] = fd;
227 + sockets->fds[sockets->opened] = fd;
228
229 char buffer[100 + 1];
224 - snprintfz(buffer, 100, "[%s]:%d", ip, port);
225 - listen_fds_names[listen_fds_count] = strdupz(buffer);
230 + snprintfz(buffer, 100, "%s:[%s]:%d", protocol, ip, port);
231 + sockets->fds_names[sockets->opened] = strdupz(buffer);
232
227 - listen_fds_count++;
233 + sockets->opened++;
234 return 0;
235 }
236
231 -int is_listen_socket(int fd) {
237 +int is_listen_socket(LISTEN_SOCKETS *sockets, int fd) {
238 size_t i;
233 - for(i = 0; i < listen_fds_count ;i++)
234 - if(listen_fds[i] == fd) return 1;
239 + for(i = 0; i < sockets->opened ;i++)
240 + if(sockets->fds[i] == fd) return 1;
241
242 return 0;
243 }
244
239 -static inline void close_listen_sockets(void) {
245 +static inline void close_listen_sockets(LISTEN_SOCKETS *sockets) {
246 size_t i;
241 - for(i = 0; i < listen_fds_count ;i++) {
242 - close(listen_fds[i]);
243 - listen_fds[i] = -1;
247 + for(i = 0; i < sockets->opened ;i++) {
248 + close(sockets->fds[i]);
249 + sockets->fds[i] = -1;
250
245 - freez(listen_fds_names[i]);
246 - listen_fds_names[i] = NULL;
251 + freez(sockets->fds_names[i]);
252 + sockets->fds_names[i] = NULL;
253 }
254
249 - listen_fds_count = 0;
255 + sockets->opened = 0;
256 }
257
252 -static inline int bind_to_one(const char *definition, int default_port, int listen_backlog) {
258 +static inline int bind_to_one(LISTEN_SOCKETS *sockets, const char *definition, int default_port, int listen_backlog) {
259 int added = 0;
260 struct addrinfo hints;
261 struct addrinfo *result = NULL, *rp = NULL;
@@ -260,7 +266,23 @@ static inline int bind_to_one(const char *definition, int default_port, int list
266 char buffer2[10 + 1];
267 snprintfz(buffer2, 10, "%d", default_port);
268
263 - char *ip = buffer, *port = buffer2;
269 + char *ip = buffer, *port = buffer2, *interface = "";;
270 +
271 + int protocol = IPPROTO_TCP, socktype = SOCK_STREAM;
272 + const char *protocol_str = "tcp";
273 +
274 + if(strncmp(ip, "tcp:", 4) == 0) {
275 + ip += 4;
276 + protocol = IPPROTO_TCP;
277 + socktype = SOCK_STREAM;
278 + protocol_str = "tcp";
279 + }
280 + else if(strncmp(ip, "udp:", 4) == 0) {
281 + ip += 4;
282 + protocol = IPPROTO_UDP;
283 + socktype = SOCK_DGRAM;
284 + protocol_str = "udp";
285 + }
286
287 char *e = ip;
288 if(*e == '[') {
@@ -272,6 +294,13 @@ static inline int bind_to_one(const char *definition, int default_port, int list
294 }
295 }
296 else {
297 + while(*e && *e != ':' && *e != '%') e++;
298 + }
299 +
300 + if(*e == '%') {
301 + *e = '\0';
302 + e++;
303 + interface = e;
304 while(*e && *e != ':') e++;
305 }
306
@@ -280,16 +309,24 @@ static inline int bind_to_one(const char *definition, int default_port, int list
309 *e = '\0';
310 }
311
312 + uint32_t scope_id = 0;
313 + if(*interface) {
314 + scope_id = if_nametoindex(interface);
315 + if(!scope_id)
316 + error("Cannot find a network interface named '%s'. Continuing with limiting the network interface", interface);
317 + }
318 +
319 if(!*ip || *ip == '*' || !strcmp(ip, "any") || !strcmp(ip, "all"))
320 ip = NULL;
321 +
322 if(!*port)
323 port = buffer2;
324
288 - memset(&hints, 0, sizeof(struct addrinfo));
289 - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
290 - hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
291 - hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
292 - hints.ai_protocol = 0; /* Any protocol */
325 + memset(&hints, 0, sizeof(hints));
326 + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
327 + hints.ai_socktype = socktype;
328 + hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
329 + hints.ai_protocol = protocol;
330 hints.ai_canonname = NULL;
331 hints.ai_addr = NULL;
332 hints.ai_next = NULL;
@@ -311,7 +348,7 @@ static inline int bind_to_one(const char *definition, int default_port, int list
348 struct sockaddr_in *sin = (struct sockaddr_in *) rp->ai_addr;
349 inet_ntop(AF_INET, &sin->sin_addr, rip, INET_ADDRSTRLEN);
350 rport = ntohs(sin->sin_port);
314 - fd = create_listen_socket4(rip, rport, listen_backlog);
351 + fd = create_listen_socket4(socktype, rip, rport, listen_backlog);
352 break;
353 }
354
@@ -319,15 +356,21 @@ static inline int bind_to_one(const char *definition, int default_port, int list
356 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) rp->ai_addr;
357 inet_ntop(AF_INET6, &sin6->sin6_addr, rip, INET6_ADDRSTRLEN);
358 rport = ntohs(sin6->sin6_port);
322 - fd = create_listen_socket6(rip, rport, listen_backlog);
359 + fd = create_listen_socket6(socktype, scope_id, rip, rport, listen_backlog);
360 break;
361 }
362 +
363 + default:
364 + debug(D_LISTENER, "Unknown socket family %d", rp->ai_addr->sa_family);
365 + break;
366 }
367
327 - if (fd == -1)
368 + if (fd == -1) {
369 error("Cannot bind to ip '%s', port %d", rip, rport);
370 + sockets->failed++;
371 + }
372 else {
330 - add_listen_socket(fd, rip, rport);
373 + add_listen_socket(sockets, fd, protocol_str, rip, rport);
374 added++;
375 }
376 }
@@ -337,19 +380,18 @@ static inline int bind_to_one(const char *definition, int default_port, int list
380 return added;
381 }
382
340 -int create_listen_sockets(void) {
341 - shown_server_socket_error = 0;
342 -
343 - listen_backlog = (int) config_get_number(CONFIG_SECTION_WEB, "listen backlog", LISTEN_BACKLOG);
383 +int create_listen_sockets(LISTEN_SOCKETS *sockets) {
384 + sockets->backlog = (int) config_get_number(sockets->config_section, "listen backlog", LISTEN_BACKLOG);
385
345 - listen_port = (int) config_get_number(CONFIG_SECTION_WEB, "default port", LISTEN_PORT);
346 - if(listen_port < 1 || listen_port > 65535) {
347 - error("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT);
348 - listen_port = (int) config_set_number(CONFIG_SECTION_WEB, "default port", LISTEN_PORT);
386 + int old_port = sockets->default_port;
387 + sockets->default_port = (int) config_get_number(sockets->config_section, "default port", sockets->default_port);
388 + if(sockets->default_port < 1 || sockets->default_port > 65535) {
389 + error("Invalid listen port %d given. Defaulting to %d.", sockets->default_port, old_port);
390 + sockets->default_port = (int) config_set_number(sockets->config_section, "default port", old_port);
391 }
350 - debug(D_OPTIONS, "Default listen port set to %d.", listen_port);
392 + debug(D_OPTIONS, "Default listen port set to %d.", sockets->default_port);
393
352 - char *s = config_get(CONFIG_SECTION_WEB, "bind to", "*");
394 + char *s = config_get(sockets->config_section, "bind to", "*");
395 while(*s) {
396 char *e = s;
397
@@ -364,20 +406,24 @@ int create_listen_sockets(void) {
406
407 char buf[e - s + 1];
408 strncpyz(buf, s, e - s);
367 - bind_to_one(buf, listen_port, listen_backlog);
409 + bind_to_one(sockets, buf, sockets->default_port, sockets->backlog);
410
411 s = e;
412 }
413
372 - if(!listen_fds_count)
414 + if(!sockets->opened)
415 fatal("Cannot listen on any socket. Exiting...");
374 - else if(shown_server_socket_error) {
416 + else if(sockets->failed) {
417 size_t i;
376 - for(i = 0; i < listen_fds_count ;i++)
377 - info("Listen socket %s opened.", listen_fds_names[i]);
418 + for(i = 0; i < sockets->opened ;i++)
419 + info("Listen socket %s opened successfully.", sockets->fds_names[i]);
420 }
421
380 - return (int)listen_fds_count;
422 + return (int)sockets->opened;
423 +}
424 +
425 +int create_api_listen_sockets(void) {
426 + return create_listen_sockets(&api_sockets);
427 }
428
429 // --------------------------------------------------------------------------------------
@@ -422,25 +468,25 @@ void *socket_listen_main_multi_threaded(void *ptr) {
468 if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
469 error("Cannot set pthread cancel state to ENABLE.");
470
425 - if(!listen_fds_count)
471 + if(!api_sockets.opened)
472 fatal("LISTENER: No sockets to listen to.");
473
428 - struct pollfd *fds = callocz(sizeof(struct pollfd), listen_fds_count);
474 + struct pollfd *fds = callocz(sizeof(struct pollfd), api_sockets.opened);
475
476 size_t i;
431 - for(i = 0; i < listen_fds_count ;i++) {
432 - fds[i].fd = listen_fds[i];
477 + for(i = 0; i < api_sockets.opened ;i++) {
478 + fds[i].fd = api_sockets.fds[i];
479 fds[i].events = POLLIN;
480 fds[i].revents = 0;
481
436 - info("Listening on '%s'", (listen_fds_names[i])?listen_fds_names[i]:"UNKNOWN");
482 + info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN");
483 }
484
485 int timeout = 10 * 1000;
486
487 for(;;) {
488 // debug(D_WEB_CLIENT, "LISTENER: Waiting...");
443 - retval = poll(fds, listen_fds_count, timeout);
489 + retval = poll(fds, api_sockets.opened, timeout);
490
491 if(unlikely(retval == -1)) {
492 error("LISTENER: poll() failed.");
@@ -453,7 +499,7 @@ void *socket_listen_main_multi_threaded(void *ptr) {
499 continue;
500 }
501
456 - for(i = 0 ; i < listen_fds_count ; i++) {
502 + for(i = 0 ; i < api_sockets.opened ; i++) {
503 short int revents = fds[i].revents;
504
505 // check for new incoming connections
@@ -486,7 +532,7 @@ void *socket_listen_main_multi_threaded(void *ptr) {
532 }
533
534 debug(D_WEB_CLIENT, "LISTENER: exit!");
489 - close_listen_sockets();
535 + close_listen_sockets(&api_sockets);
536
537 freez(fds);
538
@@ -555,7 +601,7 @@ void *socket_listen_main_single_threaded(void *ptr) {
601 if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
602 error("Cannot set pthread cancel state to ENABLE.");
603
558 - if(!listen_fds_count)
604 + if(!api_sockets.opened)
605 fatal("LISTENER: no listen sockets available.");
606
607 size_t i;
@@ -568,16 +614,16 @@ void *socket_listen_main_single_threaded(void *ptr) {
614 FD_ZERO (&efds);
615 int fdmax = 0;
616
571 - for(i = 0; i < listen_fds_count ; i++) {
572 - if (listen_fds[i] < 0 || listen_fds[i] >= FD_SETSIZE)
573 - fatal("LISTENER: Listen socket %d is not ready, or invalid.", listen_fds[i]);
617 + for(i = 0; i < api_sockets.opened ; i++) {
618 + if (api_sockets.fds[i] < 0 || api_sockets.fds[i] >= FD_SETSIZE)
619 + fatal("LISTENER: Listen socket %d is not ready, or invalid.", api_sockets.fds[i]);
620
575 - info("Listening on '%s'", (listen_fds_names[i])?listen_fds_names[i]:"UNKNOWN");
621 + info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN");
622
577 - FD_SET(listen_fds[i], &ifds);
578 - FD_SET(listen_fds[i], &efds);
579 - if(fdmax < listen_fds[i])
580 - fdmax = listen_fds[i];
623 + FD_SET(api_sockets.fds[i], &ifds);
624 + FD_SET(api_sockets.fds[i], &efds);
625 + if(fdmax < api_sockets.fds[i])
626 + fdmax = api_sockets.fds[i];
627 }
628
629 for(;;) {
@@ -596,10 +642,10 @@ void *socket_listen_main_single_threaded(void *ptr) {
642 else if(likely(retval)) {
643 debug(D_WEB_CLIENT_ACCESS, "LISTENER: got something.");
644
599 - for(i = 0; i < listen_fds_count ; i++) {
600 - if (FD_ISSET(listen_fds[i], &rifds)) {
645 + for(i = 0; i < api_sockets.opened ; i++) {
646 + if (FD_ISSET(api_sockets.fds[i], &rifds)) {
647 debug(D_WEB_CLIENT_ACCESS, "LISTENER: new connection.");
602 - w = web_client_create(listen_fds[i]);
648 + w = web_client_create(api_sockets.fds[i]);
649 if (single_threaded_link_client(w, &ifds, &ofds, &ifds, &fdmax) != 0) {
650 web_client_free(w);
651 }
@@ -658,7 +704,7 @@ void *socket_listen_main_single_threaded(void *ptr) {
704 }
705
706 debug(D_WEB_CLIENT, "LISTENER: exit!");
661 - close_listen_sockets();
707 + close_listen_sockets(&api_sockets);
708
709 static_thread->enabled = 0;
710 pthread_exit(NULL);
src/web_server.h
+1 -2
@@ -27,8 +27,7 @@ extern const char *web_server_mode_name(WEB_SERVER_MODE id);
27
28 extern void *socket_listen_main_multi_threaded(void *ptr);
29 extern void *socket_listen_main_single_threaded(void *ptr);
30 -extern int create_listen_sockets(void);
31 -extern int is_listen_socket(int fd);
30 +extern int create_api_listen_sockets(void);
31
32 #ifndef HAVE_ACCEPT4
33 extern int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags);