1 /*
2 * Copyright (c) 2017 Linaro Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <errno.h>
10
11 #ifndef __ZEPHYR__
12
13 #include <netinet/in.h>
14 #include <sys/socket.h>
15 #include <arpa/inet.h>
16 #include <unistd.h>
17
18 #else
19
20 #include <zephyr/net/socket.h>
21 #include <zephyr/kernel.h>
22
23 #endif
24
25 #define BIND_PORT 4242
26
main(void)27 int main(void)
28 {
29 int opt;
30 socklen_t optlen = sizeof(int);
31 int serv, ret;
32 struct sockaddr_in6 bind_addr = {
33 .sin6_family = AF_INET6,
34 .sin6_addr = IN6ADDR_ANY_INIT,
35 .sin6_port = htons(BIND_PORT),
36 };
37 static int counter;
38
39 serv = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
40 if (serv < 0) {
41 printf("error: socket: %d\n", errno);
42 exit(1);
43 }
44
45 ret = getsockopt(serv, IPPROTO_IPV6, IPV6_V6ONLY, &opt, &optlen);
46 if (ret == 0) {
47 if (opt) {
48 printf("IPV6_V6ONLY option is on, turning it off.\n");
49
50 opt = 0;
51 ret = setsockopt(serv, IPPROTO_IPV6, IPV6_V6ONLY,
52 &opt, optlen);
53 if (ret < 0) {
54 printf("Cannot turn off IPV6_V6ONLY option\n");
55 } else {
56 printf("Sharing same socket between IPv6 and IPv4\n");
57 }
58 }
59 }
60
61 if (bind(serv, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) < 0) {
62 printf("error: bind: %d\n", errno);
63 exit(1);
64 }
65
66 if (listen(serv, 5) < 0) {
67 printf("error: listen: %d\n", errno);
68 exit(1);
69 }
70
71 printf("Single-threaded TCP echo server waits for a connection on "
72 "port %d...\n", BIND_PORT);
73
74 while (1) {
75 struct sockaddr_in6 client_addr;
76 socklen_t client_addr_len = sizeof(client_addr);
77 char addr_str[32];
78 int client = accept(serv, (struct sockaddr *)&client_addr,
79 &client_addr_len);
80
81 if (client < 0) {
82 printf("error: accept: %d\n", errno);
83 continue;
84 }
85
86 inet_ntop(client_addr.sin6_family, &client_addr.sin6_addr,
87 addr_str, sizeof(addr_str));
88 printf("Connection #%d from %s\n", counter++, addr_str);
89
90 while (1) {
91 char buf[128], *p;
92 int len = recv(client, buf, sizeof(buf), 0);
93 int out_len;
94
95 if (len <= 0) {
96 if (len < 0) {
97 printf("error: recv: %d\n", errno);
98 }
99 break;
100 }
101
102 p = buf;
103 do {
104 out_len = send(client, p, len, 0);
105 if (out_len < 0) {
106 printf("error: send: %d\n", errno);
107 goto error;
108 }
109 p += out_len;
110 len -= out_len;
111 } while (len);
112 }
113
114 error:
115 close(client);
116 printf("Connection from %s closed\n", addr_str);
117 }
118 return 0;
119 }
120