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