samples: net: mdns_responder: Verify accept() result in echo server
The mdns_responder sample has a simple TCP echo server running, however
the accept() function errors were ignored, making the server defunct in
case server socket started to report errors (for example when network
went down).
Update the sample to restart the echo server in case of accept() errors
to make the sample more reliable.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
(cherry picked from commit 735f16f12f)
This commit is contained in:
committed by
github-actions[bot]
parent
c4ec030254
commit
031155b611
@@ -26,11 +26,7 @@ static int welcome(int fd)
|
||||
return send(fd, msg, sizeof(msg), 0);
|
||||
}
|
||||
|
||||
/* This is mainly here to bind to a port to get service advertisement
|
||||
* to work.. but since we're already here we might as well do something
|
||||
* useful.
|
||||
*/
|
||||
void service(void)
|
||||
static int echo_service(const struct sockaddr *server_addr)
|
||||
{
|
||||
int r;
|
||||
int server_fd;
|
||||
@@ -38,11 +34,116 @@ void service(void)
|
||||
socklen_t len;
|
||||
void *addrp;
|
||||
uint16_t *portp;
|
||||
struct sockaddr client_addr;
|
||||
struct sockaddr_storage client_addr;
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
uint8_t line[64];
|
||||
|
||||
static struct sockaddr server_addr;
|
||||
r = socket(server_addr->sa_family, SOCK_STREAM, 0);
|
||||
if (r == -1) {
|
||||
r = -errno;
|
||||
NET_DBG("socket() failed (%d)", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
server_fd = r;
|
||||
NET_DBG("server_fd is %d", server_fd);
|
||||
|
||||
r = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
|
||||
if (r == -1) {
|
||||
r = -errno;
|
||||
LOG_ERR("setsockopt() failed (%d)", r);
|
||||
close(server_fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = bind(server_fd, server_addr, sizeof(*server_addr));
|
||||
if (r == -1) {
|
||||
r = -errno;
|
||||
NET_DBG("bind() failed (%d)", r);
|
||||
close(server_fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (server_addr->sa_family == AF_INET6) {
|
||||
addrp = &net_sin6((server_addr))->sin6_addr;
|
||||
portp = &net_sin6(server_addr)->sin6_port;
|
||||
} else {
|
||||
addrp = &net_sin(server_addr)->sin_addr;
|
||||
portp = &net_sin(server_addr)->sin_port;
|
||||
}
|
||||
|
||||
inet_ntop(server_addr->sa_family, addrp, addrstr, sizeof(addrstr));
|
||||
NET_DBG("bound to [%s]:%u", addrstr, ntohs(*portp));
|
||||
|
||||
r = listen(server_fd, 1);
|
||||
if (r == -1) {
|
||||
r = -errno;
|
||||
NET_DBG("listen() failed (%d)", r);
|
||||
close(server_fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
len = sizeof(client_addr);
|
||||
r = accept(server_fd, (struct sockaddr *)&client_addr, &len);
|
||||
if (r == -1) {
|
||||
NET_DBG("accept() failed (%d)", errno);
|
||||
break;
|
||||
}
|
||||
|
||||
client_fd = r;
|
||||
|
||||
inet_ntop(server_addr->sa_family, addrp, addrstr, sizeof(addrstr));
|
||||
NET_DBG("accepted connection from [%s]:%u", addrstr, ntohs(*portp));
|
||||
|
||||
/* send a banner */
|
||||
r = welcome(client_fd);
|
||||
if (r == -1) {
|
||||
NET_DBG("send() failed (%d)", errno);
|
||||
close(client_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* echo 1 line at a time */
|
||||
r = recv(client_fd, line, sizeof(line), 0);
|
||||
if (r == -1) {
|
||||
NET_DBG("recv() failed (%d)", errno);
|
||||
close(client_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
NET_DBG("connection closed by peer");
|
||||
close(client_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
len = r;
|
||||
|
||||
r = send(client_fd, line, len, 0);
|
||||
if (r == -1) {
|
||||
NET_DBG("send() failed (%d)", errno);
|
||||
close(client_fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(server_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is mainly here to bind to a port to get service advertisement
|
||||
* to work.. but since we're already here we might as well do something
|
||||
* useful.
|
||||
*/
|
||||
void service(void)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
static struct sockaddr_storage server_addr;
|
||||
|
||||
#if DEFAULT_PORT == 0
|
||||
/* The advanced use case: ephemeral port */
|
||||
@@ -62,90 +163,21 @@ void service(void)
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
net_sin6(&server_addr)->sin6_family = AF_INET6;
|
||||
net_sin6(&server_addr)->sin6_addr = in6addr_any;
|
||||
net_sin6(&server_addr)->sin6_port = sys_cpu_to_be16(DEFAULT_PORT);
|
||||
net_sin6(net_sad(&server_addr))->sin6_family = AF_INET6;
|
||||
net_sin6(net_sad(&server_addr))->sin6_addr = in6addr_any;
|
||||
net_sin6(net_sad(&server_addr))->sin6_port = sys_cpu_to_be16(DEFAULT_PORT);
|
||||
} else if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
net_sin(&server_addr)->sin_family = AF_INET;
|
||||
net_sin(&server_addr)->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
net_sin(&server_addr)->sin_port = sys_cpu_to_be16(DEFAULT_PORT);
|
||||
net_sin(net_sad(&server_addr))->sin_family = AF_INET;
|
||||
net_sin(net_sad(&server_addr))->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
net_sin(net_sad(&server_addr))->sin_port = sys_cpu_to_be16(DEFAULT_PORT);
|
||||
} else {
|
||||
__ASSERT(false, "Neither IPv6 nor IPv4 are enabled");
|
||||
}
|
||||
|
||||
r = socket(server_addr.sa_family, SOCK_STREAM, 0);
|
||||
if (r == -1) {
|
||||
NET_DBG("socket() failed (%d)", errno);
|
||||
return;
|
||||
}
|
||||
|
||||
server_fd = r;
|
||||
NET_DBG("server_fd is %d", server_fd);
|
||||
|
||||
r = bind(server_fd, &server_addr, sizeof(server_addr));
|
||||
if (r == -1) {
|
||||
NET_DBG("bind() failed (%d)", errno);
|
||||
close(server_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (server_addr.sa_family == AF_INET6) {
|
||||
addrp = &net_sin6(&server_addr)->sin6_addr;
|
||||
portp = &net_sin6(&server_addr)->sin6_port;
|
||||
} else {
|
||||
addrp = &net_sin(&server_addr)->sin_addr;
|
||||
portp = &net_sin(&server_addr)->sin_port;
|
||||
}
|
||||
|
||||
inet_ntop(server_addr.sa_family, addrp, addrstr, sizeof(addrstr));
|
||||
NET_DBG("bound to [%s]:%u",
|
||||
addrstr, ntohs(*portp));
|
||||
|
||||
r = listen(server_fd, 1);
|
||||
if (r == -1) {
|
||||
NET_DBG("listen() failed (%d)", errno);
|
||||
close(server_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
len = sizeof(client_addr);
|
||||
r = accept(server_fd, (struct sockaddr *)&client_addr, &len);
|
||||
if (r == -1) {
|
||||
NET_DBG("accept() failed (%d)", errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
client_fd = r;
|
||||
|
||||
inet_ntop(server_addr.sa_family, addrp, addrstr, sizeof(addrstr));
|
||||
NET_DBG("accepted connection from [%s]:%u",
|
||||
addrstr, ntohs(*portp));
|
||||
|
||||
/* send a banner */
|
||||
r = welcome(client_fd);
|
||||
if (r == -1) {
|
||||
NET_DBG("send() failed (%d)", errno);
|
||||
close(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* echo 1 line at a time */
|
||||
r = recv(client_fd, line, sizeof(line), 0);
|
||||
if (r == -1) {
|
||||
NET_DBG("recv() failed (%d)", errno);
|
||||
close(client_fd);
|
||||
break;
|
||||
}
|
||||
len = r;
|
||||
|
||||
r = send(client_fd, line, len, 0);
|
||||
if (r == -1) {
|
||||
NET_DBG("send() failed (%d)", errno);
|
||||
close(client_fd);
|
||||
break;
|
||||
}
|
||||
while (r == 0) {
|
||||
r = echo_service((struct sockaddr *)&server_addr);
|
||||
if (r < 0) {
|
||||
NET_ERR("Fatal echo server error, %d", r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user