1 /*
2 * Copyright (C) 2016 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3 *
4 * This file is part of MooseFS.
5 *
6 * MooseFS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 (only).
9 *
10 * MooseFS is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with MooseFS; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18 * or visit http://www.gnu.org/licenses/gpl-2.0.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <sys/poll.h>
29 #include <sys/time.h>
30 #include <netinet/in.h>
31 #include <netinet/tcp.h>
32 #include <arpa/inet.h>
33 #include <netdb.h>
34 #include <unistd.h>
35 #include <inttypes.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <fcntl.h>
40 #include <errno.h>
41
42 #include "sockets.h"
43 #include "clocks.h"
44
45 /* Acid's simple socket library - ver 4.0 */
46
47 /* ---------------SOCK ADDR--------------- */
48
49 #define RRDNS_MAXADDR 256
50
51 typedef struct sockets_rrdns {
52 uint32_t iptab[RRDNS_MAXADDR];
53 uint16_t porttab[RRDNS_MAXADDR];
54 uint16_t datacnt,datapos;
55 } sockets_rrdns;
56
sockaddrnumfill(struct sockaddr_in * sa,uint32_t ip,uint16_t port)57 static inline int sockaddrnumfill(struct sockaddr_in *sa,uint32_t ip,uint16_t port) {
58 memset(sa,0,sizeof(struct sockaddr_in));
59 sa->sin_family = AF_INET;
60 sa->sin_port = htons(port);
61 sa->sin_addr.s_addr = htonl(ip);
62 #ifdef HAVE_SOCKADDR_SIN_LEN
63 sa->sin_len = sizeof(struct sockaddr_in);
64 #endif
65 return 0;
66 }
67
68
sockaddrfill(struct sockaddr_in * sa,const char * hostname,const char * service,int family,int socktype,int passive)69 static inline int sockaddrfill(struct sockaddr_in *sa,const char *hostname,const char *service,int family,int socktype,int passive) {
70 struct addrinfo hints, *res, *reshead;
71 uint32_t n,r;
72 memset(&hints, 0, sizeof(hints));
73 hints.ai_family = family;
74 hints.ai_socktype = socktype;
75 if (passive) {
76 hints.ai_flags = AI_PASSIVE;
77 }
78 if (hostname && hostname[0]=='*') {
79 hostname=NULL;
80 }
81 if (service && service[0]=='*') {
82 service=NULL;
83 }
84 if (getaddrinfo(hostname,service,&hints,&reshead)) {
85 return -1;
86 }
87
88 n = 0;
89 for (res = reshead ; res ; res=res->ai_next) {
90 if (res->ai_family==family && res->ai_socktype==socktype && res->ai_addrlen==sizeof(struct sockaddr_in)) {
91 n++;
92 }
93 }
94
95 r = random()%n;
96
97 for (res = reshead ; res ; res=res->ai_next) {
98 if (res->ai_family==family && res->ai_socktype==socktype && res->ai_addrlen==sizeof(struct sockaddr_in)) {
99 if (r==0) {
100 *sa = *((struct sockaddr_in*)(res->ai_addr));
101 freeaddrinfo(reshead);
102 return 0;
103 } else {
104 r--;
105 }
106 }
107 }
108 freeaddrinfo(reshead);
109 return -1;
110 }
111
112
sockresolve(const char * hostname,const char * service,uint32_t * ip,uint16_t * port,int family,int socktype,int passive)113 static inline int sockresolve(const char *hostname,const char *service,uint32_t *ip,uint16_t *port,int family,int socktype,int passive) {
114 struct sockaddr_in sa;
115 if (sockaddrfill(&sa,hostname,service,family,socktype,passive)<0) {
116 return -1;
117 }
118 if (ip!=(void *)0) {
119 *ip = ntohl(sa.sin_addr.s_addr);
120 }
121 if (port!=(void *)0) {
122 *port = ntohs(sa.sin_port);
123 }
124 return 0;
125 }
126
sockaddrpathfill(struct sockaddr_un * sa,const char * path)127 static inline int sockaddrpathfill(struct sockaddr_un *sa,const char *path) {
128 size_t pl;
129 pl = strlen(path);
130 if (pl >= sizeof(sa->sun_path)) { // overflow
131 return -1;
132 }
133 memset(sa,0,sizeof(struct sockaddr_un));
134 sa->sun_family = AF_LOCAL;
135 memcpy(sa->sun_path,path,pl);
136 sa->sun_path[pl]='\0';
137 return 0;
138 }
139
140 /* ---------- SOCKET UNIVERSAL ----------- */
141
socknonblock(int sock)142 static inline int socknonblock(int sock) {
143 #ifdef O_NONBLOCK
144 int flags = fcntl(sock, F_GETFL, 0);
145 if (flags == -1) {
146 return -1;
147 }
148 return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
149 #else
150 int yes = 1;
151 return ioctl(sock, FIONBIO, &yes);
152 #endif
153 }
154
sockgetstatus(int sock)155 static inline int sockgetstatus(int sock) {
156 socklen_t arglen = sizeof(int);
157 int rc = 0;
158 if (getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&rc,&arglen) < 0) {
159 rc=errno;
160 }
161 errno=rc;
162 return rc;
163 }
164
165 /* ----------- STRAM UNIVERSAL ----------- */
166
streamtoread(int sock,void * buff,uint32_t leng,uint32_t msecto)167 static inline int32_t streamtoread(int sock,void *buff,uint32_t leng,uint32_t msecto) {
168 uint32_t rcvd=0;
169 int i;
170 struct pollfd pfd;
171 double s,c;
172 uint32_t msecpassed;
173
174 s = 0.0;
175 pfd.fd = sock;
176 pfd.events = POLLIN;
177 pfd.revents = 0;
178 while (1) {
179 i = read(sock,((uint8_t*)buff)+rcvd,leng-rcvd);
180 if (i==0) {
181 return rcvd;
182 }
183 if (i>0) {
184 rcvd += i;
185 } else if (ERRNO_ERROR) {
186 return -1;
187 }
188 if (pfd.revents & POLLHUP) {
189 return rcvd;
190 }
191 if (rcvd>=leng) {
192 break;
193 }
194 if (s==0.0) {
195 s = monotonic_seconds();
196 msecpassed = 0;
197 } else {
198 c = monotonic_seconds();
199 msecpassed = (c-s)*1000.0;
200 if (msecpassed>=msecto) {
201 errno = ETIMEDOUT;
202 return -1;
203 }
204 }
205 pfd.revents = 0;
206 if (poll(&pfd,1,msecto-msecpassed)<0) {
207 if (errno!=EINTR) {
208 return -1;
209 } else {
210 continue;
211 }
212 }
213 if (pfd.revents & POLLERR) {
214 return -1;
215 }
216 if ((pfd.revents & POLLIN)==0) {
217 errno = ETIMEDOUT;
218 return -1;
219 }
220 }
221 return rcvd;
222 }
223
streamtowrite(int sock,const void * buff,uint32_t leng,uint32_t msecto)224 static inline int32_t streamtowrite(int sock,const void *buff,uint32_t leng,uint32_t msecto) {
225 uint32_t sent=0;
226 int32_t i;
227 struct pollfd pfd;
228 double s,c;
229 uint32_t msecpassed;
230
231 s = 0.0;
232 pfd.fd = sock;
233 pfd.events = POLLOUT;
234 pfd.revents = 0;
235 while (1) {
236 i = write(sock,((uint8_t*)buff)+sent,leng-sent);
237 if (i==0) {
238 return 0;
239 }
240 if (i>0) {
241 sent += i;
242 } else if (ERRNO_ERROR) {
243 return -1;
244 }
245 if (sent>=leng) {
246 break;
247 }
248 if (s==0.0) {
249 s = monotonic_seconds();
250 msecpassed = 0;
251 } else {
252 c = monotonic_seconds();
253 msecpassed = (c-s)*1000.0;
254 if (msecpassed>=msecto) {
255 errno = ETIMEDOUT;
256 return -1;
257 }
258 }
259 pfd.revents = 0;
260 if (poll(&pfd,1,msecto-msecpassed)<0) {
261 if (errno!=EINTR) {
262 return -1;
263 } else {
264 continue;
265 }
266 }
267 if (pfd.revents & (POLLHUP|POLLERR)) {
268 return -1;
269 }
270 if ((pfd.revents & POLLOUT)==0) {
271 errno = ETIMEDOUT;
272 return -1;
273 }
274 }
275 return sent;
276 }
277
streamtoforward(int srcsock,int dstsock,void * buff,uint32_t leng,uint32_t rcvd,uint32_t sent,uint32_t msecto)278 static inline int32_t streamtoforward(int srcsock,int dstsock,void *buff,uint32_t leng,uint32_t rcvd,uint32_t sent,uint32_t msecto) {
279 int32_t i;
280 struct pollfd pfd[2];
281 double s,c;
282 uint32_t msecpassed;
283 s = 0.0;
284 pfd[0].fd = srcsock;
285 pfd[0].events = POLLIN;
286 pfd[0].revents = 0;
287 pfd[1].fd = dstsock;
288 pfd[1].events = POLLOUT;
289 pfd[1].revents = 0;
290 while (1) {
291 if (rcvd<leng) {
292 i = read(srcsock,((uint8_t*)buff)+rcvd,leng-rcvd);
293 if (i==0) {
294 leng = rcvd;
295 }
296 if (i>0) {
297 rcvd += i;
298 } else if (ERRNO_ERROR) {
299 return -1;
300 }
301 }
302 if (pfd[0].revents & POLLHUP) {
303 leng = rcvd;
304 }
305 if (rcvd>sent) {
306 i = write(dstsock,((uint8_t*)buff)+sent,rcvd-sent);
307 if (i>0) {
308 sent += i;
309 } else if (ERRNO_ERROR) {
310 return -1;
311 }
312 }
313 if (rcvd>=leng && sent>=leng) {
314 break;
315 }
316 if (s==0.0) {
317 s = monotonic_seconds();
318 msecpassed = 0;
319 } else {
320 c = monotonic_seconds();
321 msecpassed = (c-s)*1000.0;
322 if (msecpassed>=msecto) {
323 errno = ETIMEDOUT;
324 return -1;
325 }
326 }
327 pfd[0].revents = 0;
328 pfd[1].revents = 0;
329 if (rcvd==leng) { // only wait for write
330 if (poll(pfd+1,1,msecto-msecpassed)<0) {
331 if (errno!=EINTR) {
332 return -1;
333 } else {
334 continue;
335 }
336 }
337 if (pfd[1].revents & (POLLERR|POLLHUP)) {
338 return -1;
339 }
340 pfd[0].revents = 0;
341 } else if (rcvd==sent) { // only wait for read
342 if (poll(pfd,1,msecto-msecpassed)<0) {
343 if (errno!=EINTR) {
344 return -1;
345 } else {
346 continue;
347 }
348 }
349 if (pfd[0].revents & POLLERR) {
350 return -1;
351 }
352 pfd[1].revents = 0;
353 } else {
354 if (poll(pfd,2,msecto-msecpassed)<0) {
355 if (errno!=EINTR) {
356 return -1;
357 } else {
358 continue;
359 }
360 }
361 if ((pfd[0].revents & POLLERR) || (pfd[1].revents & (POLLERR|POLLHUP))) {
362 return -1;
363 }
364 }
365 if ((pfd[0].revents & (POLLIN|POLLHUP))==0 && (pfd[1].revents & POLLOUT)==0) {
366 errno = ETIMEDOUT;
367 return -1;
368 }
369 }
370 return leng;
371 }
372
streamtoaccept(int lsock,uint32_t msecto)373 static inline int streamtoaccept(int lsock,uint32_t msecto) {
374 int i;
375 double s,c;
376 uint32_t msecpassed;
377 struct pollfd pfd;
378 i = accept(lsock,(struct sockaddr *)NULL,0);
379 if (i>=0) {
380 return i;
381 } else if (ERRNO_ERROR) {
382 return -1;
383 }
384 s = monotonic_seconds();
385 msecpassed = 0;
386 while (1) {
387 pfd.fd = lsock;
388 pfd.events = POLLIN;
389 pfd.revents = 0;
390 if (poll(&pfd,1,msecto-msecpassed)>=0) {
391 break;
392 }
393 if (errno==EINTR) {
394 c = monotonic_seconds();
395 msecpassed = (c-s)*1000.0;
396 if (msecpassed>=msecto) {
397 errno = ETIMEDOUT;
398 return -1;
399 }
400 continue;
401 } else {
402 return -1;
403 }
404 }
405 if (pfd.revents & (POLLHUP|POLLERR)) {
406 return -1;
407 }
408 if (pfd.revents & POLLIN) {
409 return accept(lsock,(struct sockaddr *)NULL,0);
410 }
411 errno = ETIMEDOUT;
412 return -1;
413 }
414
streamaccept(int lsock)415 static inline int streamaccept(int lsock) {
416 int sock;
417 sock=accept(lsock,(struct sockaddr *)NULL,0);
418 if (sock<0) {
419 return -1;
420 }
421 return sock;
422 }
423
424 /* ----------------- TCP ----------------- */
425
tcpsetacceptfilter(int sock)426 int tcpsetacceptfilter(int sock) {
427 #ifdef SO_ACCEPTFILTER
428 struct accept_filter_arg afa;
429
430 bzero(&afa, sizeof(afa));
431 strcpy(afa.af_name, "dataready");
432 return setsockopt(sock, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
433 #elif TCP_DEFER_ACCEPT
434 int v = 1;
435
436 return setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &v, sizeof(v));
437 #else
438 (void)sock;
439 errno=ENOTSUP;
440 return -1;
441 #endif
442 }
443
tcpsocket(void)444 int tcpsocket(void) {
445 return socket(AF_INET,SOCK_STREAM,0);
446 }
447
tcpnonblock(int sock)448 int tcpnonblock(int sock) {
449 return socknonblock(sock);
450 }
451
tcpgetstatus(int sock)452 int tcpgetstatus(int sock) {
453 return sockgetstatus(sock);
454 }
455
456
tcpresolve(const char * hostname,const char * service,uint32_t * ip,uint16_t * port,int passive)457 int tcpresolve(const char *hostname,const char *service,uint32_t *ip,uint16_t *port,int passive) {
458 return sockresolve(hostname,service,ip,port,AF_INET,SOCK_STREAM,passive);
459 }
460
tcpreuseaddr(int sock)461 int tcpreuseaddr(int sock) {
462 int yes=1;
463 return setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(int));
464 }
465
tcpnodelay(int sock)466 int tcpnodelay(int sock) {
467 int yes=1;
468 return setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char*)&yes,sizeof(int));
469 }
470
tcpaccfhttp(int sock)471 int tcpaccfhttp(int sock) {
472 #ifdef SO_ACCEPTFILTER
473 struct accept_filter_arg afa;
474
475 bzero(&afa, sizeof(afa));
476 strcpy(afa.af_name, "httpready");
477 return setsockopt(sock, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
478 #else
479 (void)sock;
480 errno=EINVAL;
481 return -1;
482 #endif
483 }
484
tcpaccfdata(int sock)485 int tcpaccfdata(int sock) {
486 #ifdef SO_ACCEPTFILTER
487 struct accept_filter_arg afa;
488
489 bzero(&afa, sizeof(afa));
490 strcpy(afa.af_name, "dataready");
491 return setsockopt(sock, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
492 #else
493 (void)sock;
494 errno=EINVAL;
495 return -1;
496 #endif
497 }
498
tcpstrbind(int sock,const char * hostname,const char * service)499 int tcpstrbind(int sock,const char *hostname,const char *service) {
500 struct sockaddr_in sa;
501 if (sockaddrfill(&sa,hostname,service,AF_INET,SOCK_STREAM,1)<0) {
502 return -1;
503 }
504 if (bind(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) {
505 return -1;
506 }
507 return 0;
508 }
509
tcpnumbind(int sock,uint32_t ip,uint16_t port)510 int tcpnumbind(int sock,uint32_t ip,uint16_t port) {
511 struct sockaddr_in sa;
512 sockaddrnumfill(&sa,ip,port);
513 if (bind(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) {
514 return -1;
515 }
516 return 0;
517 }
518
tcpstrconnect(int sock,const char * hostname,const char * service)519 int tcpstrconnect(int sock,const char *hostname,const char *service) {
520 struct sockaddr_in sa;
521 if (sockaddrfill(&sa,hostname,service,AF_INET,SOCK_STREAM,0)<0) {
522 return -1;
523 }
524 if (connect(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) >= 0) {
525 return 0;
526 }
527 if (errno == EINPROGRESS) {
528 return 1;
529 }
530 return -1;
531 }
532
tcpnumconnect(int sock,uint32_t ip,uint16_t port)533 int tcpnumconnect(int sock,uint32_t ip,uint16_t port) {
534 struct sockaddr_in sa;
535 sockaddrnumfill(&sa,ip,port);
536 if (connect(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) >= 0) {
537 return 0;
538 }
539 if (errno == EINPROGRESS) {
540 return 1;
541 }
542 return -1;
543 }
544
tcpstrtoconnect(int sock,const char * hostname,const char * service,uint32_t msecto)545 int tcpstrtoconnect(int sock,const char *hostname,const char *service,uint32_t msecto) {
546 struct sockaddr_in sa;
547 if (socknonblock(sock)<0) {
548 return -1;
549 }
550 if (sockaddrfill(&sa,hostname,service,AF_INET,SOCK_STREAM,0)<0) {
551 return -1;
552 }
553 if (connect(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) >= 0) {
554 return 0;
555 }
556 if (errno == EINPROGRESS) {
557 double s,c;
558 uint32_t msecpassed;
559 struct pollfd pfd;
560 s = monotonic_seconds();
561 msecpassed = 0;
562 while (1) {
563 pfd.fd = sock;
564 pfd.events = POLLOUT;
565 pfd.revents = 0;
566 if (poll(&pfd,1,msecto-msecpassed)>=0) {
567 break;
568 }
569 if (errno==EINTR) {
570 c = monotonic_seconds();
571 msecpassed = (c-s)*1000.0;
572 if (msecpassed>=msecto) {
573 errno = ETIMEDOUT;
574 return -1;
575 }
576 continue;
577 } else {
578 return -1;
579 }
580 }
581 if (pfd.revents & (POLLHUP|POLLERR)) {
582 return -1;
583 }
584 if (pfd.revents & POLLOUT) {
585 return sockgetstatus(sock);
586 }
587 errno=ETIMEDOUT;
588 }
589 return -1;
590 }
591
tcpnumtoconnect(int sock,uint32_t ip,uint16_t port,uint32_t msecto)592 int tcpnumtoconnect(int sock,uint32_t ip,uint16_t port,uint32_t msecto) {
593 struct sockaddr_in sa;
594 if (socknonblock(sock)<0) {
595 return -1;
596 }
597 sockaddrnumfill(&sa,ip,port);
598 if (connect(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) >= 0) {
599 return 0;
600 }
601 if (errno == EINPROGRESS) {
602 double s,c;
603 uint32_t msecpassed;
604 struct pollfd pfd;
605 s = monotonic_seconds();
606 msecpassed = 0;
607 while (1) {
608 pfd.fd = sock;
609 pfd.events = POLLOUT;
610 pfd.revents = 0;
611 if (poll(&pfd,1,msecto-msecpassed)>=0) {
612 break;
613 }
614 if (errno==EINTR) {
615 c = monotonic_seconds();
616 msecpassed = (c-s)*1000.0;
617 if (msecpassed>=msecto) {
618 errno = ETIMEDOUT;
619 return -1;
620 }
621 continue;
622 } else {
623 return -1;
624 }
625 }
626 if (pfd.revents & (POLLHUP|POLLERR)) {
627 return -1;
628 }
629 if (pfd.revents & POLLOUT) {
630 return sockgetstatus(sock);
631 }
632 errno=ETIMEDOUT;
633 }
634 return -1;
635 }
636
tcpstrlisten(int sock,const char * hostname,const char * service,uint16_t queue)637 int tcpstrlisten(int sock,const char *hostname,const char *service,uint16_t queue) {
638 struct sockaddr_in sa;
639 if (sockaddrfill(&sa,hostname,service,AF_INET,SOCK_STREAM,1)<0) {
640 return -1;
641 }
642 if (bind(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) {
643 return -1;
644 }
645 if (listen(sock,queue)<0) {
646 return -1;
647 }
648 return 0;
649 }
650
tcpnumlisten(int sock,uint32_t ip,uint16_t port,uint16_t queue)651 int tcpnumlisten(int sock,uint32_t ip,uint16_t port,uint16_t queue) {
652 struct sockaddr_in sa;
653 sockaddrnumfill(&sa,ip,port);
654 if (bind(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) {
655 return -1;
656 }
657 if (listen(sock,queue)<0) {
658 return -1;
659 }
660 return 0;
661 }
662
tcpgetpeer(int sock,uint32_t * ip,uint16_t * port)663 int tcpgetpeer(int sock,uint32_t *ip,uint16_t *port) {
664 struct sockaddr_in sa;
665 socklen_t leng;
666 leng=sizeof(sa);
667 if (getpeername(sock,(struct sockaddr *)&sa,&leng)<0) {
668 return -1;
669 }
670 if (ip!=(void *)0) {
671 *ip = ntohl(sa.sin_addr.s_addr);
672 }
673 if (port!=(void *)0) {
674 *port = ntohs(sa.sin_port);
675 }
676 return 0;
677 }
678
tcpgetmyaddr(int sock,uint32_t * ip,uint16_t * port)679 int tcpgetmyaddr(int sock,uint32_t *ip,uint16_t *port) {
680 struct sockaddr_in sa;
681 socklen_t leng;
682 leng=sizeof(sa);
683 if (getsockname(sock,(struct sockaddr *)&sa,&leng)<0) {
684 return -1;
685 }
686 if (ip!=(void *)0) {
687 *ip = ntohl(sa.sin_addr.s_addr);
688 }
689 if (port!=(void *)0) {
690 *port = ntohs(sa.sin_port);
691 }
692 return 0;
693 }
694
tcpclose(int sock)695 int tcpclose(int sock) {
696 // make sure that all pending data in the output buffer will be sent
697 shutdown(sock,SHUT_WR);
698 return close(sock);
699 }
700
tcptoread(int sock,void * buff,uint32_t leng,uint32_t msecto)701 int32_t tcptoread(int sock,void *buff,uint32_t leng,uint32_t msecto) {
702 return streamtoread(sock,buff,leng,msecto);
703 }
704
tcptowrite(int sock,const void * buff,uint32_t leng,uint32_t msecto)705 int32_t tcptowrite(int sock,const void *buff,uint32_t leng,uint32_t msecto) {
706 return streamtowrite(sock,buff,leng,msecto);
707 }
708
tcptoforward(int srcsock,int dstsock,void * buff,uint32_t leng,uint32_t rcvd,uint32_t sent,uint32_t msecto)709 int32_t tcptoforward(int srcsock,int dstsock,void *buff,uint32_t leng,uint32_t rcvd,uint32_t sent,uint32_t msecto) {
710 return streamtoforward(srcsock,dstsock,buff,leng,rcvd,sent,msecto);
711 }
712
tcptoaccept(int lsock,uint32_t msecto)713 int tcptoaccept(int lsock,uint32_t msecto) {
714 return streamtoaccept(lsock,msecto);
715 }
716
tcpaccept(int lsock)717 int tcpaccept(int lsock) {
718 return streamaccept(lsock);
719 }
720
721 /*
722 int32_t tcpread(int sock,void *buff,uint32_t leng) {
723 uint32_t rcvd=0;
724 int i;
725 while (rcvd<leng) {
726 i = read(sock,((uint8_t*)buff)+rcvd,leng-rcvd);
727 if (i<=0) {
728 return i;
729 }
730 rcvd+=i;
731 }
732 return rcvd;
733 }
734
735 int32_t tcpwrite(int sock,const void *buff,uint32_t leng) {
736 uint32_t sent=0;
737 int i;
738 while (sent<leng) {
739 i = write(sock,((const uint8_t*)buff)+sent,leng-sent);
740 if (i<=0) {
741 return i;
742 }
743 sent+=i;
744 }
745 return sent;
746 }
747 */
748
749 /* ----------------- UDP ----------------- */
750
udpsocket(void)751 int udpsocket(void) {
752 return socket(AF_INET,SOCK_DGRAM,0);
753 }
754
udpnonblock(int sock)755 int udpnonblock(int sock) {
756 return socknonblock(sock);
757 }
758
udpgetstatus(int sock)759 int udpgetstatus(int sock) {
760 return sockgetstatus(sock);
761 }
762
763
udpresolve(const char * hostname,const char * service,uint32_t * ip,uint16_t * port,int passive)764 int udpresolve(const char *hostname,const char *service,uint32_t *ip,uint16_t *port,int passive) {
765 return sockresolve(hostname,service,ip,port,AF_INET,SOCK_DGRAM,passive);
766 }
767
udpnumlisten(int sock,uint32_t ip,uint16_t port)768 int udpnumlisten(int sock,uint32_t ip,uint16_t port) {
769 struct sockaddr_in sa;
770 sockaddrnumfill(&sa,ip,port);
771 return bind(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in));
772 }
773
udpstrlisten(int sock,const char * hostname,const char * service)774 int udpstrlisten(int sock,const char *hostname,const char *service) {
775 struct sockaddr_in sa;
776 if (sockaddrfill(&sa,hostname,service,AF_INET,SOCK_DGRAM,1)<0) {
777 return -1;
778 }
779 return bind(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_in));
780 }
781
udpwrite(int sock,uint32_t ip,uint16_t port,const void * buff,uint16_t leng)782 int udpwrite(int sock,uint32_t ip,uint16_t port,const void *buff,uint16_t leng) {
783 struct sockaddr_in sa;
784 if (leng>512) {
785 return -1;
786 }
787 sockaddrnumfill(&sa,ip,port);
788 return sendto(sock,buff,leng,0,(struct sockaddr *)&sa,sizeof(struct sockaddr_in));
789 }
790
udpread(int sock,uint32_t * ip,uint16_t * port,void * buff,uint16_t leng)791 int udpread(int sock,uint32_t *ip,uint16_t *port,void *buff,uint16_t leng) {
792 socklen_t templeng;
793 struct sockaddr tempaddr;
794 struct sockaddr_in *saptr;
795 int ret;
796 ret = recvfrom(sock,buff,leng,0,&tempaddr,&templeng);
797 if (templeng==sizeof(struct sockaddr_in)) {
798 saptr = ((struct sockaddr_in*)&tempaddr);
799 if (ip!=(void *)0) {
800 *ip = ntohl(saptr->sin_addr.s_addr);
801 }
802 if (port!=(void *)0) {
803 *port = ntohs(saptr->sin_port);
804 }
805 }
806 return ret;
807 }
808
udpclose(int sock)809 int udpclose(int sock) {
810 return close(sock);
811 }
812
813 /* ----------------- UNIX ---------------- */
814
unixsocket(void)815 int unixsocket(void) {
816 return socket(AF_UNIX,SOCK_STREAM,0);
817 }
818
unixnonblock(int sock)819 int unixnonblock(int sock) {
820 return socknonblock(sock);
821 }
822
unixgetstatus(int sock)823 int unixgetstatus(int sock) {
824 return sockgetstatus(sock);
825 }
826
unixconnect(int sock,const char * path)827 int unixconnect(int sock,const char *path) {
828 struct sockaddr_un sa;
829
830 if (sockaddrpathfill(&sa,path)<0) {
831 return -1;
832 }
833 if (connect(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_un)) >= 0) {
834 return 0;
835 }
836 if (errno == EINPROGRESS) {
837 return 1;
838 }
839 return -1;
840 }
841
unixtoconnect(int sock,const char * path,uint32_t msecto)842 int unixtoconnect(int sock,const char *path,uint32_t msecto) {
843 struct sockaddr_un sa;
844
845 if (socknonblock(sock)<0) {
846 return -1;
847 }
848 if (sockaddrpathfill(&sa,path)<0) {
849 return -1;
850 }
851 if (connect(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_un)) >= 0) {
852 return 0;
853 }
854 if (errno == EINPROGRESS) {
855 double s,c;
856 uint32_t msecpassed;
857 struct pollfd pfd;
858 s = monotonic_seconds();
859 msecpassed = 0;
860 while (1) {
861 pfd.fd = sock;
862 pfd.events = POLLOUT;
863 pfd.revents = 0;
864 if (poll(&pfd,1,msecto-msecpassed)>=0) {
865 break;
866 }
867 if (errno==EINTR) {
868 c = monotonic_seconds();
869 msecpassed = (c-s)*1000.0;
870 if (msecpassed>=msecto) {
871 errno = ETIMEDOUT;
872 return -1;
873 }
874 continue;
875 } else {
876 return -1;
877 }
878 }
879 if (pfd.revents & (POLLHUP|POLLERR)) {
880 return -1;
881 }
882 if (pfd.revents & POLLOUT) {
883 return sockgetstatus(sock);
884 }
885 errno=ETIMEDOUT;
886 }
887 return -1;
888 }
889
unixlisten(int sock,const char * path,int queue)890 int unixlisten(int sock,const char *path,int queue) {
891 struct sockaddr_un sa;
892
893 if (sockaddrpathfill(&sa,path)<0) {
894 return -1;
895 }
896 if (bind(sock,(struct sockaddr *)&sa,sizeof(struct sockaddr_un)) < 0) {
897 return -1;
898 }
899 if (listen(sock,queue)<0) {
900 return -1;
901 }
902 return 0;
903 }
904
unixtoread(int sock,void * buff,uint32_t leng,uint32_t msecto)905 int32_t unixtoread(int sock,void *buff,uint32_t leng,uint32_t msecto) {
906 return streamtoread(sock,buff,leng,msecto);
907 }
908
unixtowrite(int sock,const void * buff,uint32_t leng,uint32_t msecto)909 int32_t unixtowrite(int sock,const void *buff,uint32_t leng,uint32_t msecto) {
910 return streamtowrite(sock,buff,leng,msecto);
911 }
912
unixtoforward(int srcsock,int dstsock,void * buff,uint32_t leng,uint32_t rcvd,uint32_t sent,uint32_t msecto)913 int32_t unixtoforward(int srcsock,int dstsock,void *buff,uint32_t leng,uint32_t rcvd,uint32_t sent,uint32_t msecto) {
914 return streamtoforward(srcsock,dstsock,buff,leng,rcvd,sent,msecto);
915 }
916
unixtoaccept(int lsock,uint32_t msecto)917 int unixtoaccept(int lsock,uint32_t msecto) {
918 return streamtoaccept(lsock,msecto);
919 }
920
unixaccept(int lsock)921 int unixaccept(int lsock) {
922 return streamaccept(lsock);
923 }
924
925