1 /**
2  * @file tcp.c  Transport Control Protocol
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #include <stdlib.h>
7 #ifdef HAVE_UNISTD_H
8 #include <unistd.h>
9 #endif
10 #ifdef HAVE_IO_H
11 #include <io.h>
12 #endif
13 #if !defined(WIN32)
14 #define __USE_POSIX 1  /**< Use POSIX flag */
15 #define __USE_XOPEN2K 1/**< Use POSIX.1:2001 code */
16 #define __USE_MISC 1
17 #include <netdb.h>
18 #endif
19 #ifdef __APPLE__
20 #include "TargetConditionals.h"
21 #endif
22 #include <string.h>
23 #include <re_types.h>
24 #include <re_fmt.h>
25 #include <re_mem.h>
26 #include <re_mbuf.h>
27 #include <re_list.h>
28 #include <re_main.h>
29 #include <re_sa.h>
30 #include <re_net.h>
31 #include <re_tcp.h>
32 
33 
34 #define DEBUG_MODULE "tcp"
sys_rel_get(uint32_t * rel,uint32_t * maj,uint32_t * min,uint32_t * patch)35 #define DEBUG_LEVEL 5
36 #include <re_dbg.h>
37 
38 
39 /** Platform independent buffer type cast */
40 #ifdef WIN32
41 #define BUF_CAST (char *)
42 #define SOK_CAST (int)
43 #define SIZ_CAST (int)
44 #define close closesocket
45 #else
46 #define BUF_CAST
47 #define SOK_CAST
48 #define SIZ_CAST
49 #endif
50 
51 
52 enum {
53 	TCP_TXQSZ_DEFAULT = 524288,
54 	TCP_RXSZ_DEFAULT  = 8192
55 };
56 
57 
58 /** Defines a listening TCP socket */
59 struct tcp_sock {
60 	int fd;               /**< Listening file descriptor         */
61 	int fdc;              /**< Cached connection file descriptor */
62 	tcp_conn_h *connh;    /**< TCP Connect handler               */
63 	void *arg;            /**< Handler argument                  */
64 };
65 
66 
67 /** Defines a TCP connection */
68 struct tcp_conn {
69 	struct list helpers;  /**< List of TCP-helpers               */
70 	struct list sendq;    /**< Sending queue                     */
71 	int fdc;              /**< Connection file descriptor        */
72 	tcp_estab_h *estabh;  /**< Connection established handler    */
73 	tcp_send_h *sendh;    /**< Data send handler                 */
74 	tcp_recv_h *recvh;    /**< Data receive handler              */
75 	tcp_close_h *closeh;  /**< Connection close handler          */
76 	void *arg;            /**< Handler argument                  */
77 	size_t rxsz;          /**< Maximum receive chunk size        */
78 	size_t txqsz;
79 	size_t txqsz_max;
80 	bool active;          /**< We are connecting flag            */
81 	bool connected;       /**< Connection is connected flag      */
82 };
83 
sys_kernel_get(struct re_printf * pf,void * unused)84 
85 /** Defines a TCP-Connection Helper */
86 struct tcp_helper {
87 	struct le le;
88 	int layer;
89 	tcp_helper_estab_h *estabh;
90 	tcp_helper_send_h *sendh;
91 	tcp_helper_recv_h *recvh;
92 	void *arg;
93 };
94 
95 
96 struct tcp_qent {
97 	struct le le;
98 	struct mbuf mb;
99 };
100 
101 
102 static void tcp_recv_handler(int flags, void *arg);
103 
104 
105 static bool helper_estab_handler(int *err, bool active, void *arg)
106 {
107 	(void)err;
108 	(void)active;
109 	(void)arg;
110 	return false;
111 }
112 
113 
114 static bool helper_send_handler(int *err, struct mbuf *mb, void *arg)
115 {
116 	(void)err;
117 	(void)mb;
118 	(void)arg;
119 	return false;
sys_build_get(struct re_printf * pf,void * unused)120 }
121 
122 
123 static bool helper_recv_handler(int *err, struct mbuf *mb, bool *estab,
124 				void *arg)
125 {
126 	(void)err;
127 	(void)mb;
128 	(void)estab;
129 	(void)arg;
130 	return false;
131 }
132 
133 
134 static void sock_destructor(void *data)
135 {
136 	struct tcp_sock *ts = data;
137 
138 	if (ts->fd >= 0) {
139 		fd_close(ts->fd);
140 		(void)close(ts->fd);
141 	}
142 	if (ts->fdc >= 0)
143 		(void)close(ts->fdc);
144 }
145 
146 
sys_arch_get(void)147 static void conn_destructor(void *data)
148 {
149 	struct tcp_conn *tc = data;
150 
151 	list_flush(&tc->helpers);
152 	list_flush(&tc->sendq);
153 
154 	if (tc->fdc >= 0) {
155 		fd_close(tc->fdc);
156 		(void)close(tc->fdc);
157 	}
158 }
159 
160 
161 static void helper_destructor(void *data)
sys_os_get(void)162 {
163 	struct tcp_helper *th = data;
164 
165 	list_unlink(&th->le);
166 }
167 
168 
169 static void qent_destructor(void *arg)
170 {
171 	struct tcp_qent *qe = arg;
172 
173 	list_unlink(&qe->le);
174 	mem_deref(qe->mb.buf);
175 }
176 
sys_libre_version_get(void)177 
178 static int enqueue(struct tcp_conn *tc, struct mbuf *mb)
179 {
180 	const size_t n = mbuf_get_left(mb);
181 	struct tcp_qent *qe;
182 	int err;
183 
184 	if (tc->txqsz + n > tc->txqsz_max)
185 		return ENOSPC;
186 
187 	if (!tc->sendq.head && !tc->sendh) {
188 
189 		err = fd_listen(tc->fdc, FD_READ | FD_WRITE,
190 				tcp_recv_handler, tc);
191 		if (err)
192 			return err;
193 	}
194 
195 	qe = mem_zalloc(sizeof(*qe), qent_destructor);
196 	if (!qe)
197 		return ENOMEM;
198 
199 	list_append(&tc->sendq, &qe->le, qe);
200 
201 	mbuf_init(&qe->mb);
202 
203 	err = mbuf_write_mem(&qe->mb, mbuf_buf(mb), n);
204 	qe->mb.pos = 0;
205 
206 	if (err)
207 		mem_deref(qe);
208 	else
209 		tc->txqsz += qe->mb.end;
210 
211 	return err;
212 }
213 
214 
215 static int dequeue(struct tcp_conn *tc)
216 {
217 	struct tcp_qent *qe = list_ledata(tc->sendq.head);
218 	ssize_t n;
219 #ifdef MSG_NOSIGNAL
sys_coredump_set(bool enable)220 	const int flags = MSG_NOSIGNAL; /* disable SIGPIPE signal */
221 #else
222 	const int flags = 0;
223 #endif
224 	if (!qe) {
225 		if (tc->sendh)
226 			tc->sendh(tc->arg);
227 
228 		return 0;
229 	}
230 
231 	n = send(tc->fdc, BUF_CAST mbuf_buf(&qe->mb),
232 		 qe->mb.end - qe->mb.pos, flags);
233 	if (n < 0) {
234 		if (EAGAIN == errno)
235 			return 0;
236 #ifdef WIN32
237 		if (WSAEWOULDBLOCK == WSAGetLastError())
238 			return 0;
239 #endif
240 		return errno;
241 	}
242 
243 	tc->txqsz  -= n;
244 	qe->mb.pos += n;
245 
246 	if (qe->mb.pos >= qe->mb.end)
247 		mem_deref(qe);
248 
249 	return 0;
250 }
251 
252 
253 static void conn_close(struct tcp_conn *tc, int err)
254 {
255 	list_flush(&tc->sendq);
256 	tc->txqsz = 0;
257 
258 	/* Stop polling */
259 	if (tc->fdc >= 0) {
260 		fd_close(tc->fdc);
261 		(void)close(tc->fdc);
262 		tc->fdc = -1;
263 	}
264 
265 	if (tc->closeh)
266 		tc->closeh(err, tc->arg);
267 }
268 
269 
270 static void tcp_recv_handler(int flags, void *arg)
271 {
272 	struct tcp_conn *tc = arg;
273 	struct mbuf *mb = NULL;
274 	bool hlp_estab = false;
275 	struct le *le;
276 	ssize_t n;
277 	int err;
278 	socklen_t err_len = sizeof(err);
279 
280 	if (flags & FD_EXCEPT) {
281 		DEBUG_INFO("recv handler: got FD_EXCEPT on fd=%d\n", tc->fdc);
282 	}
283 
284 	/* check for any errors */
285 	if (-1 == getsockopt(tc->fdc, SOL_SOCKET, SO_ERROR,
286 			     BUF_CAST &err, &err_len)) {
287 		DEBUG_WARNING("recv handler: getsockopt: (%m)\n", errno);
288 		return;
289 	}
290 
291 	if (err) {
292 		conn_close(tc, err);
293 		return;
294 	}
295 #if 0
296 	if (EINPROGRESS != err && EALREADY != err) {
297 		DEBUG_WARNING("recv handler: Socket error (%m)\n", err);
298 		return;
299 	}
300 #endif
301 
302 	if (flags & FD_WRITE) {
303 
304 		if (tc->connected) {
305 
306 			uint32_t nrefs;
307 
308 			mem_ref(tc);
309 
310 			err = dequeue(tc);
311 
312 			nrefs = mem_nrefs(tc);
313 			mem_deref(tc);
314 
315 			/* check if connection was deref'd from send handler */
316 			if (nrefs == 1)
317 				return;
318 
319 			if (err) {
320 				conn_close(tc, err);
321 				return;
322 			}
323 
324 			if (!tc->sendq.head && !tc->sendh) {
325 
326 				err = fd_listen(tc->fdc, FD_READ,
327 						tcp_recv_handler, tc);
328 				if (err) {
329 					conn_close(tc, err);
330 					return;
331 				}
332 			}
333 
334 			if (flags & FD_READ)
335 				goto read;
336 
337 			return;
338 		}
339 
340 		tc->connected = true;
341 
342 		err = fd_listen(tc->fdc, FD_READ, tcp_recv_handler, tc);
343 		if (err) {
344 			DEBUG_WARNING("recv handler: fd_listen(): %m\n", err);
345 			conn_close(tc, err);
346 			return;
347 		}
348 
349 		le = tc->helpers.head;
350 		while (le) {
351 			struct tcp_helper *th = le->data;
352 
353 			le = le->next;
354 
355 			if (th->estabh(&err, tc->active, th->arg) || err) {
356 				if (err)
357 					conn_close(tc, err);
358 				return;
359 			}
360 		}
361 
362 		if (tc->estabh)
363 			tc->estabh(tc->arg);
364 
365 		return;
366 	}
367 
368  read:
369 	mb = mbuf_alloc(tc->rxsz);
370 	if (!mb)
371 		return;
372 
373 	n = recv(tc->fdc, BUF_CAST mb->buf, mb->size, 0);
374 	if (0 == n) {
375 		mem_deref(mb);
376 		conn_close(tc, 0);
377 		return;
378 	}
379 	else if (n < 0) {
380 		DEBUG_WARNING("recv handler: recv(): %m\n", errno);
381 		goto out;
382 	}
383 
384 	mb->end = n;
385 
386 	le = tc->helpers.head;
387 	while (le) {
388 		struct tcp_helper *th = le->data;
389 		bool hdld = false;
390 
391 		le = le->next;
392 
393 		if (hlp_estab) {
394 
395 			hdld |= th->estabh(&err, tc->active, th->arg);
396 			if (err) {
397 				conn_close(tc, err);
398 				goto out;
399 			}
400 		}
401 
402 		if (mb->pos < mb->end) {
403 
404 		        hdld |= th->recvh(&err, mb, &hlp_estab, th->arg);
405 			if (err) {
406 				conn_close(tc, err);
407 				goto out;
408 			}
409 		}
410 
411 		if (hdld)
412 			goto out;
413 	}
414 
415 	mbuf_trim(mb);
416 
417 	if (hlp_estab && tc->estabh) {
418 
419 		uint32_t nrefs;
420 
421 		mem_ref(tc);
422 
423 		tc->estabh(tc->arg);
424 
425 		nrefs = mem_nrefs(tc);
426 		mem_deref(tc);
427 
428 		/* check if connection was deref'ed from establish handler */
429 		if (nrefs == 1)
430 			goto out;
431 	}
432 
433 	if (mb->pos < mb->end && tc->recvh) {
434 		tc->recvh(mb, tc->arg);
435 	}
436 
437  out:
438 	mem_deref(mb);
439 }
440 
441 
442 static struct tcp_conn *conn_alloc(tcp_estab_h *eh, tcp_recv_h *rh,
443 				   tcp_close_h *ch, void *arg)
444 {
445 	struct tcp_conn *tc;
446 
447 	tc = mem_zalloc(sizeof(*tc), conn_destructor);
448 	if (!tc)
449 		return NULL;
450 
451 	list_init(&tc->helpers);
452 
453 	tc->fdc    = -1;
454 	tc->rxsz   = TCP_RXSZ_DEFAULT;
455 	tc->txqsz_max = TCP_TXQSZ_DEFAULT;
456 	tc->estabh = eh;
457 	tc->recvh  = rh;
458 	tc->closeh = ch;
459 	tc->arg    = arg;
460 
461 	return tc;
462 }
463 
464 
465 static void tcp_sockopt_set(int fd)
466 {
467 #ifdef SO_LINGER
468 	const struct linger dl = {0, 0};
469 	int err;
470 
471 	err = setsockopt(fd, SOL_SOCKET, SO_LINGER, BUF_CAST &dl, sizeof(dl));
472 	if (err) {
473 		DEBUG_WARNING("sockopt: SO_LINGER (%m)\n", err);
474 	}
475 #else
476 	(void)fd;
477 #endif
478 }
479 
480 
481 /**
482  * Handler for incoming TCP connections.
483  *
484  * @param flags  Event flags.
485  * @param arg    Handler argument.
486  */
487 static void tcp_conn_handler(int flags, void *arg)
488 {
489 	struct sa peer;
490 	struct tcp_sock *ts = arg;
491 	int err;
492 
493 	(void)flags;
494 
495 	sa_init(&peer, AF_UNSPEC);
496 
497 	if (ts->fdc >= 0)
498 		(void)close(ts->fdc);
499 
500 	ts->fdc = SOK_CAST accept(ts->fd, &peer.u.sa, &peer.len);
501 	if (-1 == ts->fdc) {
502 
503 #if TARGET_OS_IPHONE
504 		if (EAGAIN == errno) {
505 
506 			struct tcp_sock *ts_new;
507 			struct sa laddr;
508 
509 			err = tcp_sock_local_get(ts, &laddr);
510 			if (err)
511 				return;
512 
513 			if (ts->fd >= 0) {
514 				fd_close(ts->fd);
515 				(void)close(ts->fd);
516 				ts->fd = -1;
517 			}
518 
519 			err = tcp_listen(&ts_new, &laddr, NULL, NULL);
520 			if (err)
521 				return;
522 
523 			ts->fd = ts_new->fd;
524 			ts_new->fd = -1;
525 
526 			mem_deref(ts_new);
527 
528 			fd_listen(ts->fd, FD_READ, tcp_conn_handler, ts);
529 		}
530 #endif
531 
532 		return;
533 	}
534 
535 	err = net_sockopt_blocking_set(ts->fdc, false);
536 	if (err) {
537 		DEBUG_WARNING("conn handler: nonblock set: %m\n", err);
538 		(void)close(ts->fdc);
539 		ts->fdc = -1;
540 		return;
541 	}
542 
543 	tcp_sockopt_set(ts->fdc);
544 
545 	if (ts->connh)
546 		ts->connh(&peer, ts->arg);
547 }
548 
549 
550 /**
551  * Create a TCP Socket
552  *
553  * @param tsp   Pointer to returned TCP Socket
554  * @param local Local listen address (NULL for any)
555  * @param ch    Incoming connection handler
556  * @param arg   Handler argument
557  *
558  * @return 0 if success, otherwise errorcode
559  */
560 int tcp_sock_alloc(struct tcp_sock **tsp, const struct sa *local,
561 		   tcp_conn_h *ch, void *arg)
562 {
563 	struct addrinfo hints, *res = NULL, *r;
564 	char addr[64] = "";
565 	char serv[6] = "0";
566 	struct tcp_sock *ts = NULL;
567 	int error, err;
568 
569 	if (!tsp)
570 		return EINVAL;
571 
572 	ts = mem_zalloc(sizeof(*ts), sock_destructor);
573 	if (!ts)
574 		return ENOMEM;
575 
576 	ts->fd  = -1;
577 	ts->fdc = -1;
578 
579 	if (local) {
580 		(void)re_snprintf(addr, sizeof(addr), "%H",
581 				  sa_print_addr, local);
582 		(void)re_snprintf(serv, sizeof(serv), "%u", sa_port(local));
583 	}
584 
585 	memset(&hints, 0, sizeof(hints));
586 	/* set-up hints structure */
587 	hints.ai_family   = PF_UNSPEC;
588 	hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
589 	hints.ai_socktype = SOCK_STREAM;
590 	hints.ai_protocol = IPPROTO_TCP;
591 
592 	error = getaddrinfo(addr[0] ? addr : NULL, serv, &hints, &res);
593 	if (error) {
594 #ifdef WIN32
595 		DEBUG_WARNING("listen: getaddrinfo: wsaerr=%d\n",
596 			      WSAGetLastError());
597 #endif
598 		DEBUG_WARNING("listen: getaddrinfo: %s:%s error=%d (%s)\n",
599 			      addr, serv, error, gai_strerror(error));
600 		err = EADDRNOTAVAIL;
601 		goto out;
602 	}
603 
604 	err = EINVAL;
605 	for (r = res; r; r = r->ai_next) {
606 		int fd = -1;
607 
608 		if (ts->fd >= 0)
609 			continue;
610 
611 		fd = SOK_CAST socket(r->ai_family, SOCK_STREAM, IPPROTO_TCP);
612 		if (fd < 0) {
613 			err = errno;
614 			continue;
615 		}
616 
617 		(void)net_sockopt_reuse_set(fd, true);
618 
619 		err = net_sockopt_blocking_set(fd, false);
620 		if (err) {
621 			DEBUG_WARNING("listen: nonblock set: %m\n", err);
622 			(void)close(fd);
623 			continue;
624 		}
625 
626 		tcp_sockopt_set(fd);
627 
628 		/* OK */
629 		ts->fd = fd;
630 		err = 0;
631 		break;
632 	}
633 
634 	freeaddrinfo(res);
635 
636 	if (-1 == ts->fd)
637 		goto out;
638 
639 	ts->connh = ch;
640 	ts->arg   = arg;
641 
642  out:
643 	if (err)
644 		mem_deref(ts);
645 	else
646 		*tsp = ts;
647 
648 	return err;
649 }
650 
651 
652 /**
653  * Bind to a TCP Socket
654  *
655  * @param ts    TCP Socket
656  * @param local Local bind address
657  *
658  * @return 0 if success, otherwise errorcode
659  */
660 int tcp_sock_bind(struct tcp_sock *ts, const struct sa *local)
661 {
662 	struct addrinfo hints, *res = NULL, *r;
663 	char addr[64] = "";
664 	char serv[NI_MAXSERV] = "0";
665 	int error, err;
666 
667 	if (!ts || ts->fd<0)
668 		return EINVAL;
669 
670 	if (local) {
671 		(void)re_snprintf(addr, sizeof(addr), "%H",
672 				  sa_print_addr, local);
673 		(void)re_snprintf(serv, sizeof(serv), "%u", sa_port(local));
674 	}
675 
676 	memset(&hints, 0, sizeof(hints));
677 	/* set-up hints structure */
678 	hints.ai_family   = PF_UNSPEC;
679 	hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
680 	hints.ai_socktype = SOCK_STREAM;
681 	hints.ai_protocol = IPPROTO_TCP;
682 
683 	error = getaddrinfo(addr[0] ? addr : NULL, serv, &hints, &res);
684 	if (error) {
685 #ifdef WIN32
686 		DEBUG_WARNING("sock_bind: getaddrinfo: wsaerr=%d\n",
687 			      WSAGetLastError());
688 #endif
689 		DEBUG_WARNING("sock_bind: getaddrinfo: %s:%s error=%d (%s)\n",
690 			      addr, serv, error, gai_strerror(error));
691 		return EADDRNOTAVAIL;
692 	}
693 
694 	err = EINVAL;
695 	for (r = res; r; r = r->ai_next) {
696 
697 		if (bind(ts->fd, r->ai_addr, SIZ_CAST r->ai_addrlen) < 0) {
698 			err = errno;
699 			DEBUG_WARNING("sock_bind: bind: %m (af=%d, %J)\n",
700 				      err, r->ai_family, local);
701 			continue;
702 		}
703 
704 		/* OK */
705 		err = 0;
706 		break;
707 	}
708 
709 	freeaddrinfo(res);
710 
711 	return err;
712 }
713 
714 
715 /**
716  * Listen on a TCP Socket
717  *
718  * @param ts       TCP Socket
719  * @param backlog  Maximum length the queue of pending connections
720  *
721  * @return 0 if success, otherwise errorcode
722  */
723 int tcp_sock_listen(struct tcp_sock *ts, int backlog)
724 {
725 	int err;
726 
727 	if (!ts)
728 		return EINVAL;
729 
730 	if (ts->fd < 0) {
731 		DEBUG_WARNING("sock_listen: invalid fd\n");
732 		return EBADF;
733 	}
734 
735 	if (listen(ts->fd, backlog) < 0) {
736 		err = errno;
737 		DEBUG_WARNING("sock_listen: listen(): %m\n", err);
738 		return err;
739 	}
740 
741 	return fd_listen(ts->fd, FD_READ, tcp_conn_handler, ts);
742 }
743 
744 
745 /**
746  * Accept an incoming TCP Connection
747  *
748  * @param tcp Returned TCP Connection object
749  * @param ts  Corresponding TCP Socket
750  * @param eh  TCP Connection Established handler
751  * @param rh  TCP Connection Receive data handler
752  * @param ch  TCP Connection close handler
753  * @param arg Handler argument
754  *
755  * @return 0 if success, otherwise errorcode
756  */
757 int tcp_accept(struct tcp_conn **tcp, struct tcp_sock *ts, tcp_estab_h *eh,
758 	       tcp_recv_h *rh, tcp_close_h *ch, void *arg)
759 {
760 	struct tcp_conn *tc;
761 	int err;
762 
763 	if (!tcp || !ts || ts->fdc < 0)
764 		return EINVAL;
765 
766 	tc = conn_alloc(eh, rh, ch, arg);
767 	if (!tc)
768 		return ENOMEM;
769 
770 	/* Transfer ownership to TCP connection */
771 	tc->fdc = ts->fdc;
772 	ts->fdc = -1;
773 
774 	err = fd_listen(tc->fdc, FD_READ | FD_WRITE | FD_EXCEPT,
775 			tcp_recv_handler, tc);
776 	if (err) {
777 		DEBUG_WARNING("accept: fd_listen(): %m\n", err);
778 	}
779 
780 	if (err)
781 		mem_deref(tc);
782 	else
783 		*tcp = tc;
784 
785 	return err;
786 }
787 
788 
789 /**
790  * Reject an incoming TCP Connection
791  *
792  * @param ts  Corresponding TCP Socket
793  */
794 void tcp_reject(struct tcp_sock *ts)
795 {
796 	if (!ts)
797 		return;
798 
799 	if (ts->fdc >= 0) {
800 		(void)close(ts->fdc);
801 		ts->fdc = -1;
802 	}
803 }
804 
805 
806 /**
807  * Allocate a TCP Connection
808  *
809  * @param tcp  Returned TCP Connection object
810  * @param peer Network address of peer
811  * @param eh   TCP Connection Established handler
812  * @param rh   TCP Connection Receive data handler
813  * @param ch   TCP Connection close handler
814  * @param arg  Handler argument
815  *
816  * @return 0 if success, otherwise errorcode
817  */
818 int tcp_conn_alloc(struct tcp_conn **tcp,
819 		   const struct sa *peer, tcp_estab_h *eh,
820 		   tcp_recv_h *rh, tcp_close_h *ch, void *arg)
821 {
822 	struct tcp_conn *tc;
823 	struct addrinfo hints, *res = NULL, *r;
824 	char addr[64];
825 	char serv[NI_MAXSERV] = "0";
826 	int error, err;
827 
828 	if (!tcp || !sa_isset(peer, SA_ALL))
829 		return EINVAL;
830 
831 	tc = conn_alloc(eh, rh, ch, arg);
832 	if (!tc)
833 		return ENOMEM;
834 
835 	memset(&hints, 0, sizeof(hints));
836 	/* set-up hints structure */
837 	hints.ai_family   = PF_UNSPEC;
838 	hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
839 	hints.ai_socktype = SOCK_STREAM;
840 	hints.ai_protocol = IPPROTO_TCP;
841 
842 	(void)re_snprintf(addr, sizeof(addr), "%H",
843 			  sa_print_addr, peer);
844 	(void)re_snprintf(serv, sizeof(serv), "%u", sa_port(peer));
845 
846 	error = getaddrinfo(addr, serv, &hints, &res);
847 	if (error) {
848 		DEBUG_WARNING("connect: getaddrinfo(): (%s)\n",
849 			      gai_strerror(error));
850 		err = EADDRNOTAVAIL;
851 		goto out;
852 	}
853 
854 	err = EINVAL;
855 	for (r = res; r; r = r->ai_next) {
856 
857 		tc->fdc = SOK_CAST socket(r->ai_family, SOCK_STREAM,
858 					  IPPROTO_TCP);
859 		if (tc->fdc < 0) {
860 			err = errno;
861 			continue;
862 		}
863 
864 		err = net_sockopt_blocking_set(tc->fdc, false);
865 		if (err) {
866 			DEBUG_WARNING("connect: nonblock set: %m\n", err);
867 			(void)close(tc->fdc);
868 			tc->fdc = -1;
869 			continue;
870 		}
871 
872 		tcp_sockopt_set(tc->fdc);
873 
874 		err = 0;
875 		break;
876 	}
877 
878 	freeaddrinfo(res);
879 
880  out:
881 	if (err)
882 		mem_deref(tc);
883 	else
884 		*tcp = tc;
885 
886 	return err;
887 }
888 
889 
890 /**
891  * Bind a TCP Connection to a local address
892  *
893  * @param tc    TCP Connection object
894  * @param local Local bind address
895  *
896  * @return 0 if success, otherwise errorcode
897  */
898 int tcp_conn_bind(struct tcp_conn *tc, const struct sa *local)
899 {
900 	struct addrinfo hints, *res = NULL, *r;
901 	char addr[64] = "";
902 	char serv[NI_MAXSERV] = "0";
903 	int error, err;
904 
905 	if (!tc)
906 		return EINVAL;
907 
908 	if (local) {
909 		(void)re_snprintf(addr, sizeof(addr), "%H",
910 				  sa_print_addr, local);
911 		(void)re_snprintf(serv, sizeof(serv), "%u", sa_port(local));
912 	}
913 
914 	memset(&hints, 0, sizeof(hints));
915 	/* set-up hints structure */
916 	hints.ai_family   = PF_UNSPEC;
917 	hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
918 	hints.ai_socktype = SOCK_STREAM;
919 	hints.ai_protocol = IPPROTO_TCP;
920 
921 	error = getaddrinfo(addr[0] ? addr : NULL, serv, &hints, &res);
922 	if (error) {
923 		DEBUG_WARNING("conn_bind: getaddrinfo(): (%s)\n",
924 			      gai_strerror(error));
925 		return EADDRNOTAVAIL;
926 	}
927 
928 	err = EINVAL;
929 	for (r = res; r; r = r->ai_next) {
930 
931 		(void)net_sockopt_reuse_set(tc->fdc, true);
932 
933 		/* bind to local address */
934 		if (bind(tc->fdc, r->ai_addr, SIZ_CAST r->ai_addrlen) < 0) {
935 
936 			/* Special case for mingw32/wine */
937 			if (0 == errno) {
938 				goto ok;
939 			}
940 
941 			err = errno;
942 			DEBUG_WARNING("conn_bind: bind(): %J: %m\n",
943 				      local, err);
944 			continue;
945 		}
946 
947 	ok:
948 		/* OK */
949 		err = 0;
950 		break;
951 	}
952 
953 	freeaddrinfo(res);
954 
955 	if (err) {
956 		DEBUG_WARNING("conn_bind failed: %J (%m)\n", local, err);
957 	}
958 
959 	return err;
960 }
961 
962 
963 /**
964  * Connect to a remote peer
965  *
966  * @param tc   TCP Connection object
967  * @param peer Network address of peer
968  *
969  * @return 0 if success, otherwise errorcode
970  */
971 int tcp_conn_connect(struct tcp_conn *tc, const struct sa *peer)
972 {
973 	struct addrinfo hints, *res = NULL, *r;
974 	char addr[64];
975 	char serv[NI_MAXSERV];
976 	int error, err = 0;
977 
978 	if (!tc || !sa_isset(peer, SA_ALL))
979 		return EINVAL;
980 
981 	tc->active = true;
982 
983 	if (tc->fdc < 0) {
984 		DEBUG_WARNING("invalid fd\n");
985 		return EBADF;
986 	}
987 
988 	memset(&hints, 0, sizeof(hints));
989 	/* set-up hints structure */
990 	hints.ai_family   = PF_UNSPEC;
991 	hints.ai_flags    = AI_PASSIVE | AI_NUMERICHOST;
992 	hints.ai_socktype = SOCK_STREAM;
993 	hints.ai_protocol = IPPROTO_TCP;
994 
995 	(void)re_snprintf(addr, sizeof(addr), "%H",
996 			  sa_print_addr, peer);
997 	(void)re_snprintf(serv, sizeof(serv), "%u", sa_port(peer));
998 
999 	error = getaddrinfo(addr, serv, &hints, &res);
1000 	if (error) {
1001 		DEBUG_WARNING("connect: getaddrinfo(): (%s)\n",
1002 			      gai_strerror(error));
1003 		return EADDRNOTAVAIL;
1004 	}
1005 
1006 	for (r = res; r; r = r->ai_next) {
1007 		struct sockaddr *sa = r->ai_addr;
1008 
1009 	again:
1010 		if (0 == connect(tc->fdc, sa, SIZ_CAST r->ai_addrlen)) {
1011 			err = 0;
1012 			goto out;
1013 		}
1014 		else {
1015 #ifdef WIN32
1016 			/* Special error handling for Windows */
1017 			if (WSAEWOULDBLOCK == WSAGetLastError()) {
1018 				err = 0;
1019 				goto out;
1020 			}
1021 #endif
1022 
1023 			/* Special case for mingw32/wine */
1024 			if (0 == errno) {
1025 				err = 0;
1026 				goto out;
1027 			}
1028 
1029 			if (EINTR == errno)
1030 				goto again;
1031 
1032 			if (EINPROGRESS != errno && EALREADY != errno) {
1033 				err = errno;
1034 				DEBUG_INFO("connect: connect() %J: %m\n",
1035 					   peer, err);
1036 			}
1037 		}
1038 	}
1039 
1040  out:
1041 	freeaddrinfo(res);
1042 
1043 	if (err)
1044 		return err;
1045 
1046 	return fd_listen(tc->fdc, FD_READ | FD_WRITE | FD_EXCEPT,
1047 			 tcp_recv_handler, tc);
1048 }
1049 
1050 
1051 static int tcp_send_internal(struct tcp_conn *tc, struct mbuf *mb,
1052 			     struct le *le)
1053 {
1054 	int err = 0;
1055 	ssize_t n;
1056 #ifdef MSG_NOSIGNAL
1057 	const int flags = MSG_NOSIGNAL; /* disable SIGPIPE signal */
1058 #else
1059 	const int flags = 0;
1060 #endif
1061 
1062 	if (tc->fdc < 0)
1063 		return ENOTCONN;
1064 
1065 	if (!mbuf_get_left(mb)) {
1066 		DEBUG_WARNING("send: empty mbuf (pos=%u end=%u)\n",
1067 			      mb->pos, mb->end);
1068 		return EINVAL;
1069 	}
1070 
1071 	/* call helpers in reverse order */
1072 	while (le) {
1073 		struct tcp_helper *th = le->data;
1074 
1075 		le = le->prev;
1076 
1077 		if (th->sendh(&err, mb, th->arg) || err)
1078 			return err;
1079 	}
1080 
1081 	if (tc->sendq.head)
1082 		return enqueue(tc, mb);
1083 
1084 	n = send(tc->fdc, BUF_CAST mbuf_buf(mb), mb->end - mb->pos, flags);
1085 	if (n < 0) {
1086 
1087 		if (EAGAIN == errno)
1088 			return enqueue(tc, mb);
1089 
1090 #ifdef WIN32
1091 		if (WSAEWOULDBLOCK == WSAGetLastError())
1092 			return enqueue(tc, mb);
1093 #endif
1094 		err = errno;
1095 
1096 		DEBUG_WARNING("send: write(): %m (fdc=%d)\n", err, tc->fdc);
1097 
1098 #ifdef WIN32
1099 		DEBUG_WARNING("WIN32 error: %d\n", WSAGetLastError());
1100 #endif
1101 
1102 		return err;
1103 	}
1104 
1105 	if ((size_t)n < mb->end - mb->pos) {
1106 
1107 		mb->pos += n;
1108 		err = enqueue(tc, mb);
1109 		mb->pos -= n;
1110 
1111 		return err;
1112 	}
1113 
1114 	return 0;
1115 }
1116 
1117 
1118 /**
1119  * Send data on a TCP Connection to a remote peer
1120  *
1121  * @param tc TCP Connection
1122  * @param mb Buffer to send
1123  *
1124  * @return 0 if success, otherwise errorcode
1125  */
1126 int tcp_send(struct tcp_conn *tc, struct mbuf *mb)
1127 {
1128 	if (!tc || !mb)
1129 		return EINVAL;
1130 
1131 	return tcp_send_internal(tc, mb, tc->helpers.tail);
1132 }
1133 
1134 
1135 /**
1136  * Send data on a TCP Connection to a remote peer bypassing this
1137  * helper and the helpers above it.
1138  *
1139  * @param tc TCP Connection
1140  * @param mb Buffer to send
1141  * @param th TCP Helper
1142  *
1143  * @return 0 if success, otherwise errorcode
1144  */
1145 int tcp_send_helper(struct tcp_conn *tc, struct mbuf *mb,
1146 		    struct tcp_helper *th)
1147 {
1148 	if (!tc || !mb || !th)
1149 		return EINVAL;
1150 
1151 	return tcp_send_internal(tc, mb, th->le.prev);
1152 }
1153 
1154 
1155 /**
1156  * Set the send handler on a TCP Connection, which will be called
1157  * every time it is ready to send data
1158  *
1159  * @param tc    TCP Connection
1160  * @param sendh TCP Send handler
1161  *
1162  * @return 0 if success, otherwise errorcode
1163  */
1164 int tcp_set_send(struct tcp_conn *tc, tcp_send_h *sendh)
1165 {
1166 	if (!tc)
1167 		return EINVAL;
1168 
1169 	tc->sendh = sendh;
1170 
1171 	if (tc->sendq.head || !sendh)
1172 		return 0;
1173 
1174 	return fd_listen(tc->fdc, FD_READ | FD_WRITE, tcp_recv_handler, tc);
1175 }
1176 
1177 
1178 /**
1179  * Set handlers on a TCP Connection
1180  *
1181  * @param tc  TCP Connection
1182  * @param eh  TCP Connection Established handler
1183  * @param rh  TCP Connection Receive data handler
1184  * @param ch  TCP Connection Close handler
1185  * @param arg Handler argument
1186  */
1187 void tcp_set_handlers(struct tcp_conn *tc, tcp_estab_h *eh, tcp_recv_h *rh,
1188 		      tcp_close_h *ch, void *arg)
1189 {
1190 	if (!tc)
1191 		return;
1192 
1193 	tc->estabh = eh;
1194 	tc->recvh  = rh;
1195 	tc->closeh = ch;
1196 	tc->arg    = arg;
1197 }
1198 
1199 
1200 /**
1201  * Get local network address of TCP Socket
1202  *
1203  * @param ts    TCP Socket
1204  * @param local Returned local network address
1205  *
1206  * @return 0 if success, otherwise errorcode
1207  */
1208 int tcp_sock_local_get(const struct tcp_sock *ts, struct sa *local)
1209 {
1210 	if (!ts || !local)
1211 		return EINVAL;
1212 
1213 	sa_init(local, AF_UNSPEC);
1214 
1215 	if (getsockname(ts->fd, &local->u.sa, &local->len) < 0) {
1216 		DEBUG_WARNING("local get: getsockname(): %m\n", errno);
1217 		return errno;
1218 	}
1219 
1220 	return 0;
1221 }
1222 
1223 
1224 /**
1225  * Get local network address of TCP Connection
1226  *
1227  * @param tc    TCP Connection
1228  * @param local Returned local network address
1229  *
1230  * @return 0 if success, otherwise errorcode
1231  */
1232 int tcp_conn_local_get(const struct tcp_conn *tc, struct sa *local)
1233 {
1234 	if (!tc || !local)
1235 		return EINVAL;
1236 
1237 	sa_init(local, AF_UNSPEC);
1238 
1239 	if (getsockname(tc->fdc, &local->u.sa, &local->len) < 0) {
1240 		DEBUG_WARNING("conn local get: getsockname(): %m\n", errno);
1241 		return errno;
1242 	}
1243 
1244 	return 0;
1245 }
1246 
1247 
1248 /**
1249  * Get remote peer network address of TCP Connection
1250  *
1251  * @param tc    TCP Connection
1252  * @param peer Returned remote peer network address
1253  *
1254  * @return 0 if success, otherwise errorcode
1255  */
1256 int tcp_conn_peer_get(const struct tcp_conn *tc, struct sa *peer)
1257 {
1258 	if (!tc || !peer)
1259 		return EINVAL;
1260 
1261 	sa_init(peer, AF_UNSPEC);
1262 
1263 	if (getpeername(tc->fdc, &peer->u.sa, &peer->len) < 0) {
1264 		DEBUG_WARNING("conn peer get: getpeername(): %m\n", errno);
1265 		return errno;
1266 	}
1267 
1268 	return 0;
1269 }
1270 
1271 
1272 /**
1273  * Set the maximum receive chunk size on a TCP Connection
1274  *
1275  * @param tc   TCP Connection
1276  * @param rxsz Maximum receive chunk size
1277  */
1278 void tcp_conn_rxsz_set(struct tcp_conn *tc, size_t rxsz)
1279 {
1280 	if (!tc)
1281 		return;
1282 
1283 	tc->rxsz = rxsz;
1284 }
1285 
1286 
1287 /**
1288  * Set the maximum send queue size on a TCP Connection
1289  *
1290  * @param tc    TCP Connection
1291  * @param txqsz Maximum send queue size
1292  */
1293 void tcp_conn_txqsz_set(struct tcp_conn *tc, size_t txqsz)
1294 {
1295 	if (!tc)
1296 		return;
1297 
1298 	tc->txqsz_max = txqsz;
1299 }
1300 
1301 
1302 /**
1303  * Get the file descriptor of a TCP Connection
1304  *
1305  * @param tc TCP-Connection
1306  *
1307  * @return File destriptor, or -1 if errors
1308  */
1309 int tcp_conn_fd(const struct tcp_conn *tc)
1310 {
1311 	return tc ? tc->fdc : -1;
1312 }
1313 
1314 
1315 /**
1316  * Get the current length of the transmit queue on a TCP Connection
1317  *
1318  * @param tc TCP-Connection
1319  *
1320  * @return Current transmit queue length, or 0 if errors
1321  */
1322 size_t tcp_conn_txqsz(const struct tcp_conn *tc)
1323 {
1324 	return tc ? tc->txqsz : 0;
1325 }
1326 
1327 
1328 static bool sort_handler(struct le *le1, struct le *le2, void *arg)
1329 {
1330 	struct tcp_helper *th1 = le1->data, *th2 = le2->data;
1331 	(void)arg;
1332 
1333 	return th1->layer <= th2->layer;
1334 }
1335 
1336 
1337 /**
1338  * Register a new TCP-helper on a TCP-Connection
1339  *
1340  * @param thp   Pointer to allocated TCP helper
1341  * @param tc    TCP Connection
1342  * @param layer Protocol layer; higher number means higher up in stack
1343  * @param eh    Established handler
1344  * @param sh    Send handler
1345  * @param rh    Receive handler
1346  * @param arg   Handler argument
1347  *
1348  * @return 0 if success, otherwise errorcode
1349  */
1350 int tcp_register_helper(struct tcp_helper **thp, struct tcp_conn *tc,
1351 			int layer,
1352 			tcp_helper_estab_h *eh, tcp_helper_send_h *sh,
1353 			tcp_helper_recv_h *rh, void *arg)
1354 {
1355 	struct tcp_helper *th;
1356 
1357 	if (!tc)
1358 		return EINVAL;
1359 
1360 	th = mem_zalloc(sizeof(*th), helper_destructor);
1361 	if (!th)
1362 		return ENOMEM;
1363 
1364 	list_append(&tc->helpers, &th->le, th);
1365 
1366 	th->layer  = layer;
1367 	th->estabh = eh ? eh : helper_estab_handler;
1368 	th->sendh  = sh ? sh : helper_send_handler;
1369 	th->recvh  = rh ? rh : helper_recv_handler;
1370 	th->arg = arg;
1371 
1372 	list_sort(&tc->helpers, sort_handler, NULL);
1373 
1374 	if (thp)
1375 		*thp = th;
1376 
1377 	return 0;
1378 }
1379