]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/third_party/duktape-1.5.2/examples/eventloop/socket.c
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / third_party / prometheus-cpp / 3rdparty / civetweb / src / third_party / duktape-1.5.2 / examples / eventloop / socket.c
CommitLineData
1e59de90
TL
1/*
2 * TCP sockets binding example.
3 */
4
5#define _GNU_SOURCE
6#include <errno.h>
7#include <string.h>
8#include <stdio.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <netdb.h>
12#include <sys/types.h>
13#include <sys/socket.h>
14#include <netinet/in.h>
15#include <time.h>
16
17#include "duktape.h"
18
19#define ERROR_FROM_ERRNO(ctx) do { \
20 duk_error(ctx, DUK_ERR_ERROR, "%s (errno=%d)", strerror(errno), errno); \
21 } while (0)
22
23static void set_nonblocking(duk_context *ctx, int fd) {
24 int rc;
25 int flags;
26
27 rc = fcntl(fd, F_GETFL);
28 if (rc < 0) {
29 ERROR_FROM_ERRNO(ctx);
30 }
31 flags = rc;
32
33 flags |= O_NONBLOCK;
34
35 rc = fcntl(fd, F_SETFL, flags);
36 if (rc < 0) {
37 ERROR_FROM_ERRNO(ctx);
38 }
39}
40
41static void set_reuseaddr(duk_context *ctx, int fd) {
42 int val;
43 int rc;
44
45 val = 1;
46 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &val, sizeof(val));
47 if (rc != 0) {
48 ERROR_FROM_ERRNO(ctx);
49 }
50}
51
52#ifdef __APPLE__
53static void set_nosigpipe(duk_context *ctx, int fd) {
54 int val;
55 int rc;
56
57 val = 1;
58 rc = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const void *) &val, sizeof(val));
59 if (rc != 0) {
60 ERROR_FROM_ERRNO(ctx);
61 }
62}
63#endif
64
65static int socket_create_server_socket(duk_context *ctx) {
66 const char *addr = duk_to_string(ctx, 0);
67 int port = duk_to_int(ctx, 1);
68 int sock;
69 struct sockaddr_in sockaddr;
70 struct hostent *ent;
71 struct in_addr **addr_list;
72 struct in_addr *addr_inet;
73 int i;
74 int rc;
75
76 sock = socket(AF_INET, SOCK_STREAM, 0);
77 if (sock < 0) {
78 ERROR_FROM_ERRNO(ctx);
79 }
80
81 set_nonblocking(ctx, sock);
82 set_reuseaddr(ctx, sock);
83#ifdef __APPLE__
84 set_nosigpipe(ctx, sock);
85#endif
86
87 ent = gethostbyname(addr);
88 if (!ent) {
89 ERROR_FROM_ERRNO(ctx);
90 }
91
92 addr_list = (struct in_addr **) ent->h_addr_list;
93 addr_inet = NULL;
94 for (i = 0; addr_list[i]; i++) {
95 addr_inet = addr_list[i];
96 break;
97 }
98 if (!addr_inet) {
99 duk_error(ctx, DUK_ERR_ERROR, "cannot resolve %s", addr);
100 }
101
102 memset(&sockaddr, 0, sizeof(sockaddr));
103 sockaddr.sin_family = AF_INET;
104 sockaddr.sin_port = htons(port);
105 sockaddr.sin_addr = *addr_inet;
106
107 rc = bind(sock, (const struct sockaddr *) &sockaddr, sizeof(sockaddr));
108 if (rc < 0) {
109 ERROR_FROM_ERRNO(ctx);
110 }
111
112 rc = listen(sock, 10 /*backlog*/);
113 if (rc < 0) {
114 (void) close(sock);
115 ERROR_FROM_ERRNO(ctx);
116 }
117
118 duk_push_int(ctx, sock);
119 return 1;
120}
121
122static int socket_close(duk_context *ctx) {
123 int sock = duk_to_int(ctx, 0);
124 int rc;
125
126 rc = close(sock);
127 if (rc < 0) {
128 ERROR_FROM_ERRNO(ctx);
129 }
130 return 0;
131}
132
133static int socket_accept(duk_context *ctx) {
134 int sock = duk_to_int(ctx, 0);
135 int rc;
136 struct sockaddr_in addr;
137 socklen_t addrlen;
138
139 memset(&addr, 0, sizeof(addr));
140 addr.sin_family = AF_INET;
141 addrlen = sizeof(addr);
142
143 rc = accept(sock, (struct sockaddr *) &addr, &addrlen);
144 if (rc < 0) {
145 ERROR_FROM_ERRNO(ctx);
146 }
147
148 set_nonblocking(ctx, sock);
149#ifdef __APPLE__
150 set_nosigpipe(ctx, sock);
151#endif
152
153 if (addrlen == sizeof(addr)) {
154 uint32_t tmp = ntohl(addr.sin_addr.s_addr);
155
156 duk_push_object(ctx);
157
158 duk_push_string(ctx, "fd");
159 duk_push_int(ctx, rc);
160 duk_put_prop(ctx, -3);
161 duk_push_string(ctx, "addr");
162 duk_push_sprintf(ctx, "%d.%d.%d.%d", ((tmp >> 24) & 0xff), ((tmp >> 16) & 0xff), ((tmp >> 8) & 0xff), (tmp & 0xff));
163 duk_put_prop(ctx, -3);
164 duk_push_string(ctx, "port");
165 duk_push_int(ctx, ntohs(addr.sin_port));
166 duk_put_prop(ctx, -3);
167
168 return 1;
169 }
170
171 return 0;
172}
173
174static int socket_connect(duk_context *ctx) {
175 const char *addr = duk_to_string(ctx, 0);
176 int port = duk_to_int(ctx, 1);
177 int sock;
178 struct sockaddr_in sockaddr;
179 struct hostent *ent;
180 struct in_addr **addr_list;
181 struct in_addr *addr_inet;
182 int i;
183 int rc;
184
185 sock = socket(AF_INET, SOCK_STREAM, 0);
186 if (sock < 0) {
187 ERROR_FROM_ERRNO(ctx);
188 }
189
190 set_nonblocking(ctx, sock);
191#ifdef __APPLE__
192 set_nosigpipe(ctx, sock);
193#endif
194
195 ent = gethostbyname(addr);
196 if (!ent) {
197 ERROR_FROM_ERRNO(ctx);
198 }
199
200 addr_list = (struct in_addr **) ent->h_addr_list;
201 addr_inet = NULL;
202 for (i = 0; addr_list[i]; i++) {
203 addr_inet = addr_list[i];
204 break;
205 }
206 if (!addr_inet) {
207 duk_error(ctx, DUK_ERR_ERROR, "cannot resolve %s", addr);
208 }
209
210 memset(&sockaddr, 0, sizeof(sockaddr));
211 sockaddr.sin_family = AF_INET;
212 sockaddr.sin_port = htons(port);
213 sockaddr.sin_addr = *addr_inet;
214
215 rc = connect(sock, (const struct sockaddr *) &sockaddr, (socklen_t) sizeof(sockaddr));
216 if (rc < 0) {
217 if (errno == EINPROGRESS) {
218#if 0
219 fprintf(stderr, "connect() returned EINPROGRESS as expected, need to poll writability\n");
220 fflush(stderr);
221#endif
222 } else {
223 ERROR_FROM_ERRNO(ctx);
224 }
225 }
226
227 duk_push_int(ctx, sock);
228 return 1;
229}
230
231static int socket_read(duk_context *ctx) {
232 int sock = duk_to_int(ctx, 0);
233 char readbuf[1024];
234 int rc;
235 void *data;
236
237 rc = recvfrom(sock, (void *) readbuf, sizeof(readbuf), 0, NULL, NULL);
238 if (rc < 0) {
239 ERROR_FROM_ERRNO(ctx);
240 }
241
242 data = duk_push_fixed_buffer(ctx, rc);
243 memcpy(data, readbuf, rc);
244 return 1;
245}
246
247static int socket_write(duk_context *ctx) {
248 int sock = duk_to_int(ctx, 0);
249 const char *data;
250 size_t len;
251 ssize_t rc;
252
253 data = duk_to_buffer(ctx, 1, &len);
254
255 /* MSG_NOSIGNAL: avoid SIGPIPE */
256#ifdef __APPLE__
257 rc = sendto(sock, (void *) data, len, 0, NULL, 0);
258#else
259 rc = sendto(sock, (void *) data, len, MSG_NOSIGNAL, NULL, 0);
260#endif
261 if (rc < 0) {
262 ERROR_FROM_ERRNO(ctx);
263 }
264
265 duk_push_int(ctx, rc);
266 return 1;
267}
268
269static duk_function_list_entry socket_funcs[] = {
270 { "createServerSocket", socket_create_server_socket, 2 },
271 { "close", socket_close, 1 },
272 { "accept", socket_accept, 1 },
273 { "connect", socket_connect, 2 },
274 { "read", socket_read, 1 },
275 { "write", socket_write, 2 },
276 { NULL, NULL, 0 }
277};
278
279void socket_register(duk_context *ctx) {
280 /* Set global 'Socket'. */
281 duk_push_global_object(ctx);
282 duk_push_object(ctx);
283 duk_put_function_list(ctx, -1, socket_funcs);
284 duk_put_prop_string(ctx, -2, "Socket");
285 duk_pop(ctx);
286}