Bug Summary

File:libsofia-sip-ua/tport/tport.c
Warning:line 4827, column 55
Although the value stored to 's' is used in the enclosing expression, the value is never actually read from 's'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name tport.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-11/lib/clang/11.0.1 -D HAVE_CONFIG_H -I . -I ../.. -I ../../libsofia-sip-ua/su/sofia-sip -I ./../bnf -I ../bnf -I ./../stun -I ../stun -I ./../ipt -I ../ipt -I ./../msg -I ../msg -I ./../http -I ../http -I ./../url -I ../url -I ./../sip -I ../sip -I ./../su -I ../su -I ./include -D SU_DEBUG=0 -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /drone/src/libsofia-sip-ua/tport -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -o /drone/src/scan-build/2022-06-23-181620-12-1 -x c tport.c
1/*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2005 Nokia Corporation.
5 *
6 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25/**@CFILE tport.c Transport interface implementation.
26 *
27 * See tport.docs for more detailed description of tport interface.
28 *
29 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
30 * @author Ismo Puustinen <Ismo.H.Puustinen@nokia.com>
31 * @author Tat Chan <Tat.Chan@nokia.com>
32 * @author Kai Vehmanen <kai.vehmanen@nokia.com>
33 * @author Martti Mela <Martti.Mela@nokia.com>
34 *
35 * @date Created: Thu Jul 20 12:54:32 2000 ppessi
36 */
37
38#include "config.h"
39
40#include <sofia-sip/su_string.h>
41#include <sofia-sip/su.h>
42#include <sofia-sip/su_errno.h>
43#include <sofia-sip/su_alloc.h>
44#include <sofia-sip/su_tagarg.h>
45#include <sofia-sip/su_localinfo.h>
46
47typedef struct tport_nat_s tport_nat_t;
48
49#define SU_WAKEUP_ARG_Tstruct tport_s struct tport_s
50#define SU_TIMER_ARG_Tstruct tport_s struct tport_s
51#define SU_MSG_ARG_Tunion tport_su_msg_arg union tport_su_msg_arg
52
53#include <sofia-sip/su_wait.h>
54
55#include <sofia-sip/msg.h>
56#include <sofia-sip/msg_addr.h>
57#include <sofia-sip/hostdomain.h>
58
59#include <stdlib.h>
60#include <time.h>
61#include <assert.h>
62#include <errno(*__errno_location ()).h>
63#include <limits.h>
64
65#ifndef IPPROTO_SCTPIPPROTO_SCTP
66#define IPPROTO_SCTPIPPROTO_SCTP (132)
67#endif
68
69#include "sofia-sip/tport.h"
70#include "sofia-sip/su_uniqueid.h"
71#include <sofia-sip/rbtree.h>
72
73#include "tport_internal.h"
74
75#if HAVE_FUNC1
76#elif HAVE_FUNCTION1
77#define __func__ __FUNCTION__
78#else
79static char const __func__[] = "tport";
80#endif
81
82#define STACK_RECV(tp, msg, now)(tp)->tp_master->mr_tpac->tpac_recv((tp)->tp_master
->mr_stack, (tp), (msg), (tp)->tp_magic, (now))
\
83 (tp)->tp_master->mr_tpac->tpac_recv((tp)->tp_master->mr_stack, (tp), \
84 (msg), (tp)->tp_magic, (now))
85
86#define STACK_ERROR(tp, errcode, dstname)(tp)->tp_master->mr_tpac->tpac_error((tp)->tp_master
->mr_stack, (tp), (errcode), (dstname))
\
87 (tp)->tp_master->mr_tpac->tpac_error((tp)->tp_master->mr_stack, (tp), \
88 (errcode), (dstname))
89
90#define STACK_ADDRESS(tp)(tp)->tp_master->mr_tpac->tpac_address((tp)->tp_master
->mr_stack, (tp))
\
91 (tp)->tp_master->mr_tpac->tpac_address((tp)->tp_master->mr_stack, (tp))
92
93#define TP_STACKtp_master->mr_stack tp_master->mr_stack
94
95/* Define macros for rbtree implementation */
96#define TP_LEFT(tp)((tp)->tp_left) ((tp)->tp_left)
97#define TP_RIGHT(tp)((tp)->tp_right) ((tp)->tp_right)
98#define TP_PARENT(tp)((tp)->tp_dad) ((tp)->tp_dad)
99#define TP_SET_RED(tp)((tp)->tp_black = 0) ((tp)->tp_black = 0)
100#define TP_SET_BLACK(tp)((tp)->tp_black = 1) ((tp)->tp_black = 1)
101#define TP_IS_RED(tp)((tp) && (tp)->tp_black == 0) ((tp) && (tp)->tp_black == 0)
102#define TP_IS_BLACK(tp)(!(tp) || (tp)->tp_black == 1) (!(tp) || (tp)->tp_black == 1)
103#define TP_COPY_COLOR(dst, src)((dst)->tp_black = (src)->tp_black) ((dst)->tp_black = (src)->tp_black)
104#define TP_INSERT(tp)((void)0) ((void)0)
105#define TP_REMOVE(tp)((tp)->tp_left = (tp)->tp_right = (tp)->tp_dad = ((void
*)0))
((tp)->tp_left = (tp)->tp_right = (tp)->tp_dad = NULL((void*)0))
106
107su_inlinestatic inline int tp_cmp(tport_t const *a, tport_t const *b)
108{
109 if (a == b)
110 return 0;
111
112 if (a->tp_addrlentp_addrinfo->ai_addrlen != b->tp_addrlentp_addrinfo->ai_addrlen)
113 return (int)(a->tp_addrlentp_addrinfo->ai_addrlen - b->tp_addrlentp_addrinfo->ai_addrlen);
114
115 return memcmp(a->tp_addr, b->tp_addr, a->tp_addrlentp_addrinfo->ai_addrlen);
116}
117
118#ifdef __clang__1
119#pragma clang diagnostic push
120#pragma clang diagnostic ignored "-Wunused-function"
121#endif
122
123RBTREE_PROTOS(su_inline, tprb, tport_t)static inline int tprb_insert(tport_t **, tport_t *, tport_t *
*return_old); static inline int tprb_append(tport_t **, tport_t
*); static inline void tprb_remove(tport_t **, tport_t *); static
inline tport_t *tprb_succ(tport_t const *); static inline tport_t
*tprb_prec(tport_t const *); static inline tport_t *tprb_first
(tport_t const *); static inline tport_t *tprb_last(tport_t const
*); static inline int tprb_height(tport_t const *)
;
124
125RBTREE_BODIES(su_inline, tprb, tport_t,static inline void tprb_left_rotate(tport_t **top, tport_t *x
) { tport_t *c = ((x)->tp_right), *dad = ((x)->tp_dad);
((void) sizeof ((c) ? 1 : 0), __extension__ ({ if (c) ; else
__assert_fail ("c", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); if ((((x)->tp_right) = ((c)->tp_left))) ((((x)->
tp_right))->tp_dad) = x; if (!(((c)->tp_dad) = dad)) *top
= c; else if (((dad)->tp_left) == x) ((dad)->tp_left) =
c; else ((void) sizeof ((((dad)->tp_right) == x) ? 1 : 0)
, __extension__ ({ if (((dad)->tp_right) == x) ; else __assert_fail
("TP_RIGHT(dad) == x", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })), ((dad)->tp_right) = c; ((c)->tp_left) = x; ((x)
->tp_dad) = c; } extern int const tprb_dummy; static inline
void tprb_right_rotate(tport_t **top, tport_t *x) { tport_t *
c = ((x)->tp_left), *dad = ((x)->tp_dad); ((void) sizeof
((c) ? 1 : 0), __extension__ ({ if (c) ; else __assert_fail (
"c", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }));
if ((((x)->tp_left) = ((c)->tp_right))) ((((x)->tp_left
))->tp_dad) = x; if (!(((c)->tp_dad) = dad)) *top = c; else
if (((dad)->tp_right) == x) ((dad)->tp_right) = c; else
((void) sizeof ((((dad)->tp_left) == x) ? 1 : 0), __extension__
({ if (((dad)->tp_left) == x) ; else __assert_fail ("TP_LEFT(dad) == x"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })), ((
dad)->tp_left) = c; ((c)->tp_right) = x; ((x)->tp_dad
) = c; } extern int const tprb_dummy; static inline void tprb_balance_insert
(tport_t **top, tport_t *node) { tport_t *dad, *uncle, *granddad
; ((node)->tp_black = 0); for (dad = ((node)->tp_dad); node
!= *top && ((dad) && (dad)->tp_black == 0
); dad = ((node)->tp_dad)) { granddad = ((dad)->tp_dad)
; ((void) sizeof ((granddad) ? 1 : 0), __extension__ ({ if (granddad
) ; else __assert_fail ("granddad", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })); if (dad == ((granddad)->tp_left
)) { uncle = ((granddad)->tp_right); if (((uncle) &&
(uncle)->tp_black == 0)) { ((dad)->tp_black = 1); ((uncle
)->tp_black = 1); ((granddad)->tp_black = 0); node = granddad
; } else { if (node == ((dad)->tp_right)) { tprb_left_rotate
(top, node = dad); dad = ((node)->tp_dad); ((void) sizeof (
(dad) ? 1 : 0), __extension__ ({ if (dad) ; else __assert_fail
("dad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }
)); granddad = ((dad)->tp_dad); ((void) sizeof ((granddad)
? 1 : 0), __extension__ ({ if (granddad) ; else __assert_fail
("granddad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); } ((dad)->tp_black = 1); ((granddad)->tp_black =
0); tprb_right_rotate(top, granddad); } } else { ((void) sizeof
((dad == ((granddad)->tp_right)) ? 1 : 0), __extension__ (
{ if (dad == ((granddad)->tp_right)) ; else __assert_fail (
"dad == TP_RIGHT(granddad)", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); uncle = ((granddad)->tp_left); if (((uncle) &&
(uncle)->tp_black == 0)) { ((dad)->tp_black = 1); ((uncle
)->tp_black = 1); ((granddad)->tp_black = 0); node = granddad
; } else { if (node == ((dad)->tp_left)) { tprb_right_rotate
(top, node = dad); dad = ((node)->tp_dad); ((void) sizeof (
(dad) ? 1 : 0), __extension__ ({ if (dad) ; else __assert_fail
("dad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }
)); granddad = ((dad)->tp_dad); ((void) sizeof ((granddad)
? 1 : 0), __extension__ ({ if (granddad) ; else __assert_fail
("granddad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); } ((dad)->tp_black = 1); ((granddad)->tp_black =
0); tprb_left_rotate(top, granddad); } } } ((void) sizeof ((
*top) ? 1 : 0), __extension__ ({ if (*top) ; else __assert_fail
("*top", "tport.c", 128, __extension__ __PRETTY_FUNCTION__);
})); (((*top))->tp_black = 1); } extern int const tprb_dummy
; static inline void tprb_balance_delete(tport_t **top, tport_t
*node) { tport_t *dad, *brother; for (dad = ((node)->tp_dad
); node != *top && ((dad) && (dad)->tp_black
== 0); dad = ((node)->tp_dad)) { if (node == ((dad)->tp_left
)) { brother = ((dad)->tp_right); if (!brother) { node = dad
; continue; } ((void) sizeof (((!(brother) || (brother)->tp_black
== 1)) ? 1 : 0), __extension__ ({ if ((!(brother) || (brother
)->tp_black == 1)) ; else __assert_fail ("TP_IS_BLACK(brother)"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); if
((!(((brother)->tp_left)) || (((brother)->tp_left))->
tp_black == 1) && (!(((brother)->tp_right)) || (((
brother)->tp_right))->tp_black == 1)) { ((brother)->
tp_black = 0); node = dad; continue; } if ((!(((brother)->
tp_right)) || (((brother)->tp_right))->tp_black == 1)) {
((brother)->tp_black = 0); ((((brother)->tp_left))->
tp_black = 1); tprb_right_rotate(top, brother); brother = ((dad
)->tp_right); } ((brother)->tp_black = (dad)->tp_black
); ((dad)->tp_black = 1); if (((brother)->tp_right)) ((
((brother)->tp_right))->tp_black = 1); tprb_left_rotate
(top, dad); node = *top; break; } else { ((void) sizeof ((node
== ((dad)->tp_right)) ? 1 : 0), __extension__ ({ if (node
== ((dad)->tp_right)) ; else __assert_fail ("node == TP_RIGHT(dad)"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); brother
= ((dad)->tp_left); if (!brother) { node = dad; continue;
} ((void) sizeof (((!(brother) || (brother)->tp_black == 1
)) ? 1 : 0), __extension__ ({ if ((!(brother) || (brother)->
tp_black == 1)) ; else __assert_fail ("TP_IS_BLACK(brother)",
"tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); if (
(!(((brother)->tp_left)) || (((brother)->tp_left))->
tp_black == 1) && (!(((brother)->tp_right)) || (((
brother)->tp_right))->tp_black == 1)) { ((brother)->
tp_black = 0); node = dad; continue; } if ((!(((brother)->
tp_left)) || (((brother)->tp_left))->tp_black == 1)) { (
(((brother)->tp_right))->tp_black = 1); ((brother)->
tp_black = 0); tprb_left_rotate(top, brother); brother = ((dad
)->tp_left); } ((brother)->tp_black = (((node)->tp_dad
))->tp_black); ((((node)->tp_dad))->tp_black = 1); if
(((brother)->tp_left)) ((((brother)->tp_left))->tp_black
= 1); tprb_right_rotate(top, dad); node = *top; break; } } (
(node)->tp_black = 1); } extern int const tprb_dummy; static
inline int tprb_insert(tport_t **const tree, tport_t * const
node, tport_t **return_old) { tport_t *old, *dad, **slot; if
(tree == ((void*)0) || node == ((void*)0)) return -1; for (slot
= tree, old = *slot, dad = ((void*)0); old; old = *slot) { int
result = tp_cmp(node, old); if (result < 0) dad = old, slot
= &(((old)->tp_left)); else if (result > 0) dad = old
, slot = &(((old)->tp_right)); else break; } if (old ==
node) old = ((void*)0); else if (old) { if (!return_old) return
-1; if ((((node)->tp_left) = ((old)->tp_left))) ((((node
)->tp_left))->tp_dad) = node; if ((((node)->tp_right
) = ((old)->tp_right))) ((((node)->tp_right))->tp_dad
) = node; if (!(((node)->tp_dad) = ((old)->tp_dad))) *tree
= node; else if (((((node)->tp_dad))->tp_left) == old)
((((node)->tp_dad))->tp_left) = node; else ((void) sizeof
((((((node)->tp_dad))->tp_right) == old) ? 1 : 0), __extension__
({ if (((((node)->tp_dad))->tp_right) == old) ; else __assert_fail
("TP_RIGHT(TP_PARENT(node)) == old", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })), ((((node)->tp_dad))->tp_right
) = node; ((node)->tp_black = (old)->tp_black); ((old)->
tp_left = (old)->tp_right = (old)->tp_dad = ((void*)0))
; } else { *slot = node; ((node)->tp_dad) = dad; if (tree !=
slot) { tprb_balance_insert(tree, node); } else { ((node)->
tp_black = 1); } } ((void)0); if (return_old) *return_old = old
; return 0; } extern int const tprb_dummy; static inline int tprb_append
(tport_t **const tree, tport_t * const node) { tport_t *old, *
dad, **slot; if (tree == ((void*)0) || node == ((void*)0)) return
-1; for (slot = tree, old = *slot, dad = ((void*)0); old; old
= *slot) { if (old == node) return 0; if (tp_cmp(node, old) <
0) dad = old, slot = &(((old)->tp_left)); else dad = old
, slot = &(((old)->tp_right)); } *slot = node; ((node)
->tp_dad) = dad; if (tree != slot) { tprb_balance_insert(tree
, node); } else { ((node)->tp_black = 1); } ((void)0); return
0; } extern int const tprb_dummy; static inline void tprb_remove
(tport_t **top, tport_t *node) { tport_t *kid, *dad; int need_to_balance
; if (top == ((void*)0) || node == ((void*)0)) return; for (dad
= node; dad; dad = ((dad)->tp_dad)) if (dad == *top) break
; if (!dad) return; if (!((node)->tp_left) || !((node)->
tp_right)) dad = node; else for (dad = ((node)->tp_right);
((dad)->tp_left); dad = ((dad)->tp_left)) ; kid = ((dad
)->tp_left) ? ((dad)->tp_left) : ((dad)->tp_right); if
(!(((dad)->tp_dad))) *top = kid; else if (((((dad)->tp_dad
))->tp_left) == dad) ((((dad)->tp_dad))->tp_left) = kid
; else ((void) sizeof ((((((dad)->tp_dad))->tp_right) ==
dad) ? 1 : 0), __extension__ ({ if (((((dad)->tp_dad))->
tp_right) == dad) ; else __assert_fail ("TP_RIGHT(TP_PARENT(dad)) == dad"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })), ((
((dad)->tp_dad))->tp_right) = kid; if (kid) ((kid)->
tp_dad) = ((dad)->tp_dad); need_to_balance = kid &&
(!(dad) || (dad)->tp_black == 1); if (node != dad) { if (
!(((dad)->tp_dad) = ((node)->tp_dad))) *top = dad; else
if (((((dad)->tp_dad))->tp_left) == node) ((((dad)->
tp_dad))->tp_left) = dad; else ((void) sizeof ((((((dad)->
tp_dad))->tp_right) == node) ? 1 : 0), __extension__ ({ if
(((((dad)->tp_dad))->tp_right) == node) ; else __assert_fail
("TP_RIGHT(TP_PARENT(dad)) == node", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })), ((((dad)->tp_dad))->tp_right
) = dad; ((dad)->tp_black = (node)->tp_black); if ((((dad
)->tp_left) = ((node)->tp_left))) ((((dad)->tp_left)
)->tp_dad) = dad; if ((((dad)->tp_right) = ((node)->
tp_right))) ((((dad)->tp_right))->tp_dad) = dad; } ((node
)->tp_left = (node)->tp_right = (node)->tp_dad = ((void
*)0)); ((node)->tp_black = 0); if (need_to_balance) tprb_balance_delete
(top, kid); } extern int const tprb_dummy; static inline tport_t
*tprb_succ(tport_t const *node) { tport_t const *dad; if (((
node)->tp_right)) { for (node = ((node)->tp_right); ((node
)->tp_left); node = ((node)->tp_left)) ; return (tport_t
*)node; } for (dad = ((node)->tp_dad); dad && node
== ((dad)->tp_right); dad = ((node)->tp_dad)) node = dad
; return (tport_t *)dad; } extern int const tprb_dummy; static
inline tport_t *tprb_prec(tport_t const *node) { tport_t const
*dad; if (((node)->tp_left)) { for (node = ((node)->tp_left
); ((node)->tp_right); node = ((node)->tp_right)) ; return
(tport_t *)node; } for (dad = ((node)->tp_dad); dad &&
node == ((dad)->tp_left); dad = ((node)->tp_dad)) node
= dad; return (tport_t *)dad; } extern int const tprb_dummy;
static inline tport_t *tprb_first(tport_t const *node) { while
(node && ((node)->tp_left)) node = ((node)->tp_left
); return (tport_t *)node; } extern int const tprb_dummy; static
inline tport_t *tprb_last(tport_t const *node) { while (node
&& ((node)->tp_right)) node = ((node)->tp_right
); return (tport_t *)node; } extern int const tprb_dummy; static
inline int tprb_height(tport_t const *node) { int left, right
; if (!node) return 0; left = ((node)->tp_left) ? tprb_height
(((node)->tp_left)) : 0; right = ((node)->tp_right) ? tprb_height
(((node)->tp_right)) : 0; if (left > right) return left
+ 1; else return right + 1; } extern int const tprb_dummy
126 TP_LEFT, TP_RIGHT, TP_PARENT,static inline void tprb_left_rotate(tport_t **top, tport_t *x
) { tport_t *c = ((x)->tp_right), *dad = ((x)->tp_dad);
((void) sizeof ((c) ? 1 : 0), __extension__ ({ if (c) ; else
__assert_fail ("c", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); if ((((x)->tp_right) = ((c)->tp_left))) ((((x)->
tp_right))->tp_dad) = x; if (!(((c)->tp_dad) = dad)) *top
= c; else if (((dad)->tp_left) == x) ((dad)->tp_left) =
c; else ((void) sizeof ((((dad)->tp_right) == x) ? 1 : 0)
, __extension__ ({ if (((dad)->tp_right) == x) ; else __assert_fail
("TP_RIGHT(dad) == x", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })), ((dad)->tp_right) = c; ((c)->tp_left) = x; ((x)
->tp_dad) = c; } extern int const tprb_dummy; static inline
void tprb_right_rotate(tport_t **top, tport_t *x) { tport_t *
c = ((x)->tp_left), *dad = ((x)->tp_dad); ((void) sizeof
((c) ? 1 : 0), __extension__ ({ if (c) ; else __assert_fail (
"c", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }));
if ((((x)->tp_left) = ((c)->tp_right))) ((((x)->tp_left
))->tp_dad) = x; if (!(((c)->tp_dad) = dad)) *top = c; else
if (((dad)->tp_right) == x) ((dad)->tp_right) = c; else
((void) sizeof ((((dad)->tp_left) == x) ? 1 : 0), __extension__
({ if (((dad)->tp_left) == x) ; else __assert_fail ("TP_LEFT(dad) == x"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })), ((
dad)->tp_left) = c; ((c)->tp_right) = x; ((x)->tp_dad
) = c; } extern int const tprb_dummy; static inline void tprb_balance_insert
(tport_t **top, tport_t *node) { tport_t *dad, *uncle, *granddad
; ((node)->tp_black = 0); for (dad = ((node)->tp_dad); node
!= *top && ((dad) && (dad)->tp_black == 0
); dad = ((node)->tp_dad)) { granddad = ((dad)->tp_dad)
; ((void) sizeof ((granddad) ? 1 : 0), __extension__ ({ if (granddad
) ; else __assert_fail ("granddad", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })); if (dad == ((granddad)->tp_left
)) { uncle = ((granddad)->tp_right); if (((uncle) &&
(uncle)->tp_black == 0)) { ((dad)->tp_black = 1); ((uncle
)->tp_black = 1); ((granddad)->tp_black = 0); node = granddad
; } else { if (node == ((dad)->tp_right)) { tprb_left_rotate
(top, node = dad); dad = ((node)->tp_dad); ((void) sizeof (
(dad) ? 1 : 0), __extension__ ({ if (dad) ; else __assert_fail
("dad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }
)); granddad = ((dad)->tp_dad); ((void) sizeof ((granddad)
? 1 : 0), __extension__ ({ if (granddad) ; else __assert_fail
("granddad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); } ((dad)->tp_black = 1); ((granddad)->tp_black =
0); tprb_right_rotate(top, granddad); } } else { ((void) sizeof
((dad == ((granddad)->tp_right)) ? 1 : 0), __extension__ (
{ if (dad == ((granddad)->tp_right)) ; else __assert_fail (
"dad == TP_RIGHT(granddad)", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); uncle = ((granddad)->tp_left); if (((uncle) &&
(uncle)->tp_black == 0)) { ((dad)->tp_black = 1); ((uncle
)->tp_black = 1); ((granddad)->tp_black = 0); node = granddad
; } else { if (node == ((dad)->tp_left)) { tprb_right_rotate
(top, node = dad); dad = ((node)->tp_dad); ((void) sizeof (
(dad) ? 1 : 0), __extension__ ({ if (dad) ; else __assert_fail
("dad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }
)); granddad = ((dad)->tp_dad); ((void) sizeof ((granddad)
? 1 : 0), __extension__ ({ if (granddad) ; else __assert_fail
("granddad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); } ((dad)->tp_black = 1); ((granddad)->tp_black =
0); tprb_left_rotate(top, granddad); } } } ((void) sizeof ((
*top) ? 1 : 0), __extension__ ({ if (*top) ; else __assert_fail
("*top", "tport.c", 128, __extension__ __PRETTY_FUNCTION__);
})); (((*top))->tp_black = 1); } extern int const tprb_dummy
; static inline void tprb_balance_delete(tport_t **top, tport_t
*node) { tport_t *dad, *brother; for (dad = ((node)->tp_dad
); node != *top && ((dad) && (dad)->tp_black
== 0); dad = ((node)->tp_dad)) { if (node == ((dad)->tp_left
)) { brother = ((dad)->tp_right); if (!brother) { node = dad
; continue; } ((void) sizeof (((!(brother) || (brother)->tp_black
== 1)) ? 1 : 0), __extension__ ({ if ((!(brother) || (brother
)->tp_black == 1)) ; else __assert_fail ("TP_IS_BLACK(brother)"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); if
((!(((brother)->tp_left)) || (((brother)->tp_left))->
tp_black == 1) && (!(((brother)->tp_right)) || (((
brother)->tp_right))->tp_black == 1)) { ((brother)->
tp_black = 0); node = dad; continue; } if ((!(((brother)->
tp_right)) || (((brother)->tp_right))->tp_black == 1)) {
((brother)->tp_black = 0); ((((brother)->tp_left))->
tp_black = 1); tprb_right_rotate(top, brother); brother = ((dad
)->tp_right); } ((brother)->tp_black = (dad)->tp_black
); ((dad)->tp_black = 1); if (((brother)->tp_right)) ((
((brother)->tp_right))->tp_black = 1); tprb_left_rotate
(top, dad); node = *top; break; } else { ((void) sizeof ((node
== ((dad)->tp_right)) ? 1 : 0), __extension__ ({ if (node
== ((dad)->tp_right)) ; else __assert_fail ("node == TP_RIGHT(dad)"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); brother
= ((dad)->tp_left); if (!brother) { node = dad; continue;
} ((void) sizeof (((!(brother) || (brother)->tp_black == 1
)) ? 1 : 0), __extension__ ({ if ((!(brother) || (brother)->
tp_black == 1)) ; else __assert_fail ("TP_IS_BLACK(brother)",
"tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); if (
(!(((brother)->tp_left)) || (((brother)->tp_left))->
tp_black == 1) && (!(((brother)->tp_right)) || (((
brother)->tp_right))->tp_black == 1)) { ((brother)->
tp_black = 0); node = dad; continue; } if ((!(((brother)->
tp_left)) || (((brother)->tp_left))->tp_black == 1)) { (
(((brother)->tp_right))->tp_black = 1); ((brother)->
tp_black = 0); tprb_left_rotate(top, brother); brother = ((dad
)->tp_left); } ((brother)->tp_black = (((node)->tp_dad
))->tp_black); ((((node)->tp_dad))->tp_black = 1); if
(((brother)->tp_left)) ((((brother)->tp_left))->tp_black
= 1); tprb_right_rotate(top, dad); node = *top; break; } } (
(node)->tp_black = 1); } extern int const tprb_dummy; static
inline int tprb_insert(tport_t **const tree, tport_t * const
node, tport_t **return_old) { tport_t *old, *dad, **slot; if
(tree == ((void*)0) || node == ((void*)0)) return -1; for (slot
= tree, old = *slot, dad = ((void*)0); old; old = *slot) { int
result = tp_cmp(node, old); if (result < 0) dad = old, slot
= &(((old)->tp_left)); else if (result > 0) dad = old
, slot = &(((old)->tp_right)); else break; } if (old ==
node) old = ((void*)0); else if (old) { if (!return_old) return
-1; if ((((node)->tp_left) = ((old)->tp_left))) ((((node
)->tp_left))->tp_dad) = node; if ((((node)->tp_right
) = ((old)->tp_right))) ((((node)->tp_right))->tp_dad
) = node; if (!(((node)->tp_dad) = ((old)->tp_dad))) *tree
= node; else if (((((node)->tp_dad))->tp_left) == old)
((((node)->tp_dad))->tp_left) = node; else ((void) sizeof
((((((node)->tp_dad))->tp_right) == old) ? 1 : 0), __extension__
({ if (((((node)->tp_dad))->tp_right) == old) ; else __assert_fail
("TP_RIGHT(TP_PARENT(node)) == old", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })), ((((node)->tp_dad))->tp_right
) = node; ((node)->tp_black = (old)->tp_black); ((old)->
tp_left = (old)->tp_right = (old)->tp_dad = ((void*)0))
; } else { *slot = node; ((node)->tp_dad) = dad; if (tree !=
slot) { tprb_balance_insert(tree, node); } else { ((node)->
tp_black = 1); } } ((void)0); if (return_old) *return_old = old
; return 0; } extern int const tprb_dummy; static inline int tprb_append
(tport_t **const tree, tport_t * const node) { tport_t *old, *
dad, **slot; if (tree == ((void*)0) || node == ((void*)0)) return
-1; for (slot = tree, old = *slot, dad = ((void*)0); old; old
= *slot) { if (old == node) return 0; if (tp_cmp(node, old) <
0) dad = old, slot = &(((old)->tp_left)); else dad = old
, slot = &(((old)->tp_right)); } *slot = node; ((node)
->tp_dad) = dad; if (tree != slot) { tprb_balance_insert(tree
, node); } else { ((node)->tp_black = 1); } ((void)0); return
0; } extern int const tprb_dummy; static inline void tprb_remove
(tport_t **top, tport_t *node) { tport_t *kid, *dad; int need_to_balance
; if (top == ((void*)0) || node == ((void*)0)) return; for (dad
= node; dad; dad = ((dad)->tp_dad)) if (dad == *top) break
; if (!dad) return; if (!((node)->tp_left) || !((node)->
tp_right)) dad = node; else for (dad = ((node)->tp_right);
((dad)->tp_left); dad = ((dad)->tp_left)) ; kid = ((dad
)->tp_left) ? ((dad)->tp_left) : ((dad)->tp_right); if
(!(((dad)->tp_dad))) *top = kid; else if (((((dad)->tp_dad
))->tp_left) == dad) ((((dad)->tp_dad))->tp_left) = kid
; else ((void) sizeof ((((((dad)->tp_dad))->tp_right) ==
dad) ? 1 : 0), __extension__ ({ if (((((dad)->tp_dad))->
tp_right) == dad) ; else __assert_fail ("TP_RIGHT(TP_PARENT(dad)) == dad"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })), ((
((dad)->tp_dad))->tp_right) = kid; if (kid) ((kid)->
tp_dad) = ((dad)->tp_dad); need_to_balance = kid &&
(!(dad) || (dad)->tp_black == 1); if (node != dad) { if (
!(((dad)->tp_dad) = ((node)->tp_dad))) *top = dad; else
if (((((dad)->tp_dad))->tp_left) == node) ((((dad)->
tp_dad))->tp_left) = dad; else ((void) sizeof ((((((dad)->
tp_dad))->tp_right) == node) ? 1 : 0), __extension__ ({ if
(((((dad)->tp_dad))->tp_right) == node) ; else __assert_fail
("TP_RIGHT(TP_PARENT(dad)) == node", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })), ((((dad)->tp_dad))->tp_right
) = dad; ((dad)->tp_black = (node)->tp_black); if ((((dad
)->tp_left) = ((node)->tp_left))) ((((dad)->tp_left)
)->tp_dad) = dad; if ((((dad)->tp_right) = ((node)->
tp_right))) ((((dad)->tp_right))->tp_dad) = dad; } ((node
)->tp_left = (node)->tp_right = (node)->tp_dad = ((void
*)0)); ((node)->tp_black = 0); if (need_to_balance) tprb_balance_delete
(top, kid); } extern int const tprb_dummy; static inline tport_t
*tprb_succ(tport_t const *node) { tport_t const *dad; if (((
node)->tp_right)) { for (node = ((node)->tp_right); ((node
)->tp_left); node = ((node)->tp_left)) ; return (tport_t
*)node; } for (dad = ((node)->tp_dad); dad && node
== ((dad)->tp_right); dad = ((node)->tp_dad)) node = dad
; return (tport_t *)dad; } extern int const tprb_dummy; static
inline tport_t *tprb_prec(tport_t const *node) { tport_t const
*dad; if (((node)->tp_left)) { for (node = ((node)->tp_left
); ((node)->tp_right); node = ((node)->tp_right)) ; return
(tport_t *)node; } for (dad = ((node)->tp_dad); dad &&
node == ((dad)->tp_left); dad = ((node)->tp_dad)) node
= dad; return (tport_t *)dad; } extern int const tprb_dummy;
static inline tport_t *tprb_first(tport_t const *node) { while
(node && ((node)->tp_left)) node = ((node)->tp_left
); return (tport_t *)node; } extern int const tprb_dummy; static
inline tport_t *tprb_last(tport_t const *node) { while (node
&& ((node)->tp_right)) node = ((node)->tp_right
); return (tport_t *)node; } extern int const tprb_dummy; static
inline int tprb_height(tport_t const *node) { int left, right
; if (!node) return 0; left = ((node)->tp_left) ? tprb_height
(((node)->tp_left)) : 0; right = ((node)->tp_right) ? tprb_height
(((node)->tp_right)) : 0; if (left > right) return left
+ 1; else return right + 1; } extern int const tprb_dummy
127 TP_IS_RED, TP_SET_RED, TP_IS_BLACK, TP_SET_BLACK, TP_COPY_COLOR,static inline void tprb_left_rotate(tport_t **top, tport_t *x
) { tport_t *c = ((x)->tp_right), *dad = ((x)->tp_dad);
((void) sizeof ((c) ? 1 : 0), __extension__ ({ if (c) ; else
__assert_fail ("c", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); if ((((x)->tp_right) = ((c)->tp_left))) ((((x)->
tp_right))->tp_dad) = x; if (!(((c)->tp_dad) = dad)) *top
= c; else if (((dad)->tp_left) == x) ((dad)->tp_left) =
c; else ((void) sizeof ((((dad)->tp_right) == x) ? 1 : 0)
, __extension__ ({ if (((dad)->tp_right) == x) ; else __assert_fail
("TP_RIGHT(dad) == x", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })), ((dad)->tp_right) = c; ((c)->tp_left) = x; ((x)
->tp_dad) = c; } extern int const tprb_dummy; static inline
void tprb_right_rotate(tport_t **top, tport_t *x) { tport_t *
c = ((x)->tp_left), *dad = ((x)->tp_dad); ((void) sizeof
((c) ? 1 : 0), __extension__ ({ if (c) ; else __assert_fail (
"c", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }));
if ((((x)->tp_left) = ((c)->tp_right))) ((((x)->tp_left
))->tp_dad) = x; if (!(((c)->tp_dad) = dad)) *top = c; else
if (((dad)->tp_right) == x) ((dad)->tp_right) = c; else
((void) sizeof ((((dad)->tp_left) == x) ? 1 : 0), __extension__
({ if (((dad)->tp_left) == x) ; else __assert_fail ("TP_LEFT(dad) == x"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })), ((
dad)->tp_left) = c; ((c)->tp_right) = x; ((x)->tp_dad
) = c; } extern int const tprb_dummy; static inline void tprb_balance_insert
(tport_t **top, tport_t *node) { tport_t *dad, *uncle, *granddad
; ((node)->tp_black = 0); for (dad = ((node)->tp_dad); node
!= *top && ((dad) && (dad)->tp_black == 0
); dad = ((node)->tp_dad)) { granddad = ((dad)->tp_dad)
; ((void) sizeof ((granddad) ? 1 : 0), __extension__ ({ if (granddad
) ; else __assert_fail ("granddad", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })); if (dad == ((granddad)->tp_left
)) { uncle = ((granddad)->tp_right); if (((uncle) &&
(uncle)->tp_black == 0)) { ((dad)->tp_black = 1); ((uncle
)->tp_black = 1); ((granddad)->tp_black = 0); node = granddad
; } else { if (node == ((dad)->tp_right)) { tprb_left_rotate
(top, node = dad); dad = ((node)->tp_dad); ((void) sizeof (
(dad) ? 1 : 0), __extension__ ({ if (dad) ; else __assert_fail
("dad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }
)); granddad = ((dad)->tp_dad); ((void) sizeof ((granddad)
? 1 : 0), __extension__ ({ if (granddad) ; else __assert_fail
("granddad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); } ((dad)->tp_black = 1); ((granddad)->tp_black =
0); tprb_right_rotate(top, granddad); } } else { ((void) sizeof
((dad == ((granddad)->tp_right)) ? 1 : 0), __extension__ (
{ if (dad == ((granddad)->tp_right)) ; else __assert_fail (
"dad == TP_RIGHT(granddad)", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); uncle = ((granddad)->tp_left); if (((uncle) &&
(uncle)->tp_black == 0)) { ((dad)->tp_black = 1); ((uncle
)->tp_black = 1); ((granddad)->tp_black = 0); node = granddad
; } else { if (node == ((dad)->tp_left)) { tprb_right_rotate
(top, node = dad); dad = ((node)->tp_dad); ((void) sizeof (
(dad) ? 1 : 0), __extension__ ({ if (dad) ; else __assert_fail
("dad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }
)); granddad = ((dad)->tp_dad); ((void) sizeof ((granddad)
? 1 : 0), __extension__ ({ if (granddad) ; else __assert_fail
("granddad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); } ((dad)->tp_black = 1); ((granddad)->tp_black =
0); tprb_left_rotate(top, granddad); } } } ((void) sizeof ((
*top) ? 1 : 0), __extension__ ({ if (*top) ; else __assert_fail
("*top", "tport.c", 128, __extension__ __PRETTY_FUNCTION__);
})); (((*top))->tp_black = 1); } extern int const tprb_dummy
; static inline void tprb_balance_delete(tport_t **top, tport_t
*node) { tport_t *dad, *brother; for (dad = ((node)->tp_dad
); node != *top && ((dad) && (dad)->tp_black
== 0); dad = ((node)->tp_dad)) { if (node == ((dad)->tp_left
)) { brother = ((dad)->tp_right); if (!brother) { node = dad
; continue; } ((void) sizeof (((!(brother) || (brother)->tp_black
== 1)) ? 1 : 0), __extension__ ({ if ((!(brother) || (brother
)->tp_black == 1)) ; else __assert_fail ("TP_IS_BLACK(brother)"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); if
((!(((brother)->tp_left)) || (((brother)->tp_left))->
tp_black == 1) && (!(((brother)->tp_right)) || (((
brother)->tp_right))->tp_black == 1)) { ((brother)->
tp_black = 0); node = dad; continue; } if ((!(((brother)->
tp_right)) || (((brother)->tp_right))->tp_black == 1)) {
((brother)->tp_black = 0); ((((brother)->tp_left))->
tp_black = 1); tprb_right_rotate(top, brother); brother = ((dad
)->tp_right); } ((brother)->tp_black = (dad)->tp_black
); ((dad)->tp_black = 1); if (((brother)->tp_right)) ((
((brother)->tp_right))->tp_black = 1); tprb_left_rotate
(top, dad); node = *top; break; } else { ((void) sizeof ((node
== ((dad)->tp_right)) ? 1 : 0), __extension__ ({ if (node
== ((dad)->tp_right)) ; else __assert_fail ("node == TP_RIGHT(dad)"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); brother
= ((dad)->tp_left); if (!brother) { node = dad; continue;
} ((void) sizeof (((!(brother) || (brother)->tp_black == 1
)) ? 1 : 0), __extension__ ({ if ((!(brother) || (brother)->
tp_black == 1)) ; else __assert_fail ("TP_IS_BLACK(brother)",
"tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); if (
(!(((brother)->tp_left)) || (((brother)->tp_left))->
tp_black == 1) && (!(((brother)->tp_right)) || (((
brother)->tp_right))->tp_black == 1)) { ((brother)->
tp_black = 0); node = dad; continue; } if ((!(((brother)->
tp_left)) || (((brother)->tp_left))->tp_black == 1)) { (
(((brother)->tp_right))->tp_black = 1); ((brother)->
tp_black = 0); tprb_left_rotate(top, brother); brother = ((dad
)->tp_left); } ((brother)->tp_black = (((node)->tp_dad
))->tp_black); ((((node)->tp_dad))->tp_black = 1); if
(((brother)->tp_left)) ((((brother)->tp_left))->tp_black
= 1); tprb_right_rotate(top, dad); node = *top; break; } } (
(node)->tp_black = 1); } extern int const tprb_dummy; static
inline int tprb_insert(tport_t **const tree, tport_t * const
node, tport_t **return_old) { tport_t *old, *dad, **slot; if
(tree == ((void*)0) || node == ((void*)0)) return -1; for (slot
= tree, old = *slot, dad = ((void*)0); old; old = *slot) { int
result = tp_cmp(node, old); if (result < 0) dad = old, slot
= &(((old)->tp_left)); else if (result > 0) dad = old
, slot = &(((old)->tp_right)); else break; } if (old ==
node) old = ((void*)0); else if (old) { if (!return_old) return
-1; if ((((node)->tp_left) = ((old)->tp_left))) ((((node
)->tp_left))->tp_dad) = node; if ((((node)->tp_right
) = ((old)->tp_right))) ((((node)->tp_right))->tp_dad
) = node; if (!(((node)->tp_dad) = ((old)->tp_dad))) *tree
= node; else if (((((node)->tp_dad))->tp_left) == old)
((((node)->tp_dad))->tp_left) = node; else ((void) sizeof
((((((node)->tp_dad))->tp_right) == old) ? 1 : 0), __extension__
({ if (((((node)->tp_dad))->tp_right) == old) ; else __assert_fail
("TP_RIGHT(TP_PARENT(node)) == old", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })), ((((node)->tp_dad))->tp_right
) = node; ((node)->tp_black = (old)->tp_black); ((old)->
tp_left = (old)->tp_right = (old)->tp_dad = ((void*)0))
; } else { *slot = node; ((node)->tp_dad) = dad; if (tree !=
slot) { tprb_balance_insert(tree, node); } else { ((node)->
tp_black = 1); } } ((void)0); if (return_old) *return_old = old
; return 0; } extern int const tprb_dummy; static inline int tprb_append
(tport_t **const tree, tport_t * const node) { tport_t *old, *
dad, **slot; if (tree == ((void*)0) || node == ((void*)0)) return
-1; for (slot = tree, old = *slot, dad = ((void*)0); old; old
= *slot) { if (old == node) return 0; if (tp_cmp(node, old) <
0) dad = old, slot = &(((old)->tp_left)); else dad = old
, slot = &(((old)->tp_right)); } *slot = node; ((node)
->tp_dad) = dad; if (tree != slot) { tprb_balance_insert(tree
, node); } else { ((node)->tp_black = 1); } ((void)0); return
0; } extern int const tprb_dummy; static inline void tprb_remove
(tport_t **top, tport_t *node) { tport_t *kid, *dad; int need_to_balance
; if (top == ((void*)0) || node == ((void*)0)) return; for (dad
= node; dad; dad = ((dad)->tp_dad)) if (dad == *top) break
; if (!dad) return; if (!((node)->tp_left) || !((node)->
tp_right)) dad = node; else for (dad = ((node)->tp_right);
((dad)->tp_left); dad = ((dad)->tp_left)) ; kid = ((dad
)->tp_left) ? ((dad)->tp_left) : ((dad)->tp_right); if
(!(((dad)->tp_dad))) *top = kid; else if (((((dad)->tp_dad
))->tp_left) == dad) ((((dad)->tp_dad))->tp_left) = kid
; else ((void) sizeof ((((((dad)->tp_dad))->tp_right) ==
dad) ? 1 : 0), __extension__ ({ if (((((dad)->tp_dad))->
tp_right) == dad) ; else __assert_fail ("TP_RIGHT(TP_PARENT(dad)) == dad"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })), ((
((dad)->tp_dad))->tp_right) = kid; if (kid) ((kid)->
tp_dad) = ((dad)->tp_dad); need_to_balance = kid &&
(!(dad) || (dad)->tp_black == 1); if (node != dad) { if (
!(((dad)->tp_dad) = ((node)->tp_dad))) *top = dad; else
if (((((dad)->tp_dad))->tp_left) == node) ((((dad)->
tp_dad))->tp_left) = dad; else ((void) sizeof ((((((dad)->
tp_dad))->tp_right) == node) ? 1 : 0), __extension__ ({ if
(((((dad)->tp_dad))->tp_right) == node) ; else __assert_fail
("TP_RIGHT(TP_PARENT(dad)) == node", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })), ((((dad)->tp_dad))->tp_right
) = dad; ((dad)->tp_black = (node)->tp_black); if ((((dad
)->tp_left) = ((node)->tp_left))) ((((dad)->tp_left)
)->tp_dad) = dad; if ((((dad)->tp_right) = ((node)->
tp_right))) ((((dad)->tp_right))->tp_dad) = dad; } ((node
)->tp_left = (node)->tp_right = (node)->tp_dad = ((void
*)0)); ((node)->tp_black = 0); if (need_to_balance) tprb_balance_delete
(top, kid); } extern int const tprb_dummy; static inline tport_t
*tprb_succ(tport_t const *node) { tport_t const *dad; if (((
node)->tp_right)) { for (node = ((node)->tp_right); ((node
)->tp_left); node = ((node)->tp_left)) ; return (tport_t
*)node; } for (dad = ((node)->tp_dad); dad && node
== ((dad)->tp_right); dad = ((node)->tp_dad)) node = dad
; return (tport_t *)dad; } extern int const tprb_dummy; static
inline tport_t *tprb_prec(tport_t const *node) { tport_t const
*dad; if (((node)->tp_left)) { for (node = ((node)->tp_left
); ((node)->tp_right); node = ((node)->tp_right)) ; return
(tport_t *)node; } for (dad = ((node)->tp_dad); dad &&
node == ((dad)->tp_left); dad = ((node)->tp_dad)) node
= dad; return (tport_t *)dad; } extern int const tprb_dummy;
static inline tport_t *tprb_first(tport_t const *node) { while
(node && ((node)->tp_left)) node = ((node)->tp_left
); return (tport_t *)node; } extern int const tprb_dummy; static
inline tport_t *tprb_last(tport_t const *node) { while (node
&& ((node)->tp_right)) node = ((node)->tp_right
); return (tport_t *)node; } extern int const tprb_dummy; static
inline int tprb_height(tport_t const *node) { int left, right
; if (!node) return 0; left = ((node)->tp_left) ? tprb_height
(((node)->tp_left)) : 0; right = ((node)->tp_right) ? tprb_height
(((node)->tp_right)) : 0; if (left > right) return left
+ 1; else return right + 1; } extern int const tprb_dummy
128 tp_cmp, TP_INSERT, TP_REMOVE)static inline void tprb_left_rotate(tport_t **top, tport_t *x
) { tport_t *c = ((x)->tp_right), *dad = ((x)->tp_dad);
((void) sizeof ((c) ? 1 : 0), __extension__ ({ if (c) ; else
__assert_fail ("c", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); if ((((x)->tp_right) = ((c)->tp_left))) ((((x)->
tp_right))->tp_dad) = x; if (!(((c)->tp_dad) = dad)) *top
= c; else if (((dad)->tp_left) == x) ((dad)->tp_left) =
c; else ((void) sizeof ((((dad)->tp_right) == x) ? 1 : 0)
, __extension__ ({ if (((dad)->tp_right) == x) ; else __assert_fail
("TP_RIGHT(dad) == x", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })), ((dad)->tp_right) = c; ((c)->tp_left) = x; ((x)
->tp_dad) = c; } extern int const tprb_dummy; static inline
void tprb_right_rotate(tport_t **top, tport_t *x) { tport_t *
c = ((x)->tp_left), *dad = ((x)->tp_dad); ((void) sizeof
((c) ? 1 : 0), __extension__ ({ if (c) ; else __assert_fail (
"c", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }));
if ((((x)->tp_left) = ((c)->tp_right))) ((((x)->tp_left
))->tp_dad) = x; if (!(((c)->tp_dad) = dad)) *top = c; else
if (((dad)->tp_right) == x) ((dad)->tp_right) = c; else
((void) sizeof ((((dad)->tp_left) == x) ? 1 : 0), __extension__
({ if (((dad)->tp_left) == x) ; else __assert_fail ("TP_LEFT(dad) == x"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })), ((
dad)->tp_left) = c; ((c)->tp_right) = x; ((x)->tp_dad
) = c; } extern int const tprb_dummy; static inline void tprb_balance_insert
(tport_t **top, tport_t *node) { tport_t *dad, *uncle, *granddad
; ((node)->tp_black = 0); for (dad = ((node)->tp_dad); node
!= *top && ((dad) && (dad)->tp_black == 0
); dad = ((node)->tp_dad)) { granddad = ((dad)->tp_dad)
; ((void) sizeof ((granddad) ? 1 : 0), __extension__ ({ if (granddad
) ; else __assert_fail ("granddad", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })); if (dad == ((granddad)->tp_left
)) { uncle = ((granddad)->tp_right); if (((uncle) &&
(uncle)->tp_black == 0)) { ((dad)->tp_black = 1); ((uncle
)->tp_black = 1); ((granddad)->tp_black = 0); node = granddad
; } else { if (node == ((dad)->tp_right)) { tprb_left_rotate
(top, node = dad); dad = ((node)->tp_dad); ((void) sizeof (
(dad) ? 1 : 0), __extension__ ({ if (dad) ; else __assert_fail
("dad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }
)); granddad = ((dad)->tp_dad); ((void) sizeof ((granddad)
? 1 : 0), __extension__ ({ if (granddad) ; else __assert_fail
("granddad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); } ((dad)->tp_black = 1); ((granddad)->tp_black =
0); tprb_right_rotate(top, granddad); } } else { ((void) sizeof
((dad == ((granddad)->tp_right)) ? 1 : 0), __extension__ (
{ if (dad == ((granddad)->tp_right)) ; else __assert_fail (
"dad == TP_RIGHT(granddad)", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); uncle = ((granddad)->tp_left); if (((uncle) &&
(uncle)->tp_black == 0)) { ((dad)->tp_black = 1); ((uncle
)->tp_black = 1); ((granddad)->tp_black = 0); node = granddad
; } else { if (node == ((dad)->tp_left)) { tprb_right_rotate
(top, node = dad); dad = ((node)->tp_dad); ((void) sizeof (
(dad) ? 1 : 0), __extension__ ({ if (dad) ; else __assert_fail
("dad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__); }
)); granddad = ((dad)->tp_dad); ((void) sizeof ((granddad)
? 1 : 0), __extension__ ({ if (granddad) ; else __assert_fail
("granddad", "tport.c", 128, __extension__ __PRETTY_FUNCTION__
); })); } ((dad)->tp_black = 1); ((granddad)->tp_black =
0); tprb_left_rotate(top, granddad); } } } ((void) sizeof ((
*top) ? 1 : 0), __extension__ ({ if (*top) ; else __assert_fail
("*top", "tport.c", 128, __extension__ __PRETTY_FUNCTION__);
})); (((*top))->tp_black = 1); } extern int const tprb_dummy
; static inline void tprb_balance_delete(tport_t **top, tport_t
*node) { tport_t *dad, *brother; for (dad = ((node)->tp_dad
); node != *top && ((dad) && (dad)->tp_black
== 0); dad = ((node)->tp_dad)) { if (node == ((dad)->tp_left
)) { brother = ((dad)->tp_right); if (!brother) { node = dad
; continue; } ((void) sizeof (((!(brother) || (brother)->tp_black
== 1)) ? 1 : 0), __extension__ ({ if ((!(brother) || (brother
)->tp_black == 1)) ; else __assert_fail ("TP_IS_BLACK(brother)"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); if
((!(((brother)->tp_left)) || (((brother)->tp_left))->
tp_black == 1) && (!(((brother)->tp_right)) || (((
brother)->tp_right))->tp_black == 1)) { ((brother)->
tp_black = 0); node = dad; continue; } if ((!(((brother)->
tp_right)) || (((brother)->tp_right))->tp_black == 1)) {
((brother)->tp_black = 0); ((((brother)->tp_left))->
tp_black = 1); tprb_right_rotate(top, brother); brother = ((dad
)->tp_right); } ((brother)->tp_black = (dad)->tp_black
); ((dad)->tp_black = 1); if (((brother)->tp_right)) ((
((brother)->tp_right))->tp_black = 1); tprb_left_rotate
(top, dad); node = *top; break; } else { ((void) sizeof ((node
== ((dad)->tp_right)) ? 1 : 0), __extension__ ({ if (node
== ((dad)->tp_right)) ; else __assert_fail ("node == TP_RIGHT(dad)"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); brother
= ((dad)->tp_left); if (!brother) { node = dad; continue;
} ((void) sizeof (((!(brother) || (brother)->tp_black == 1
)) ? 1 : 0), __extension__ ({ if ((!(brother) || (brother)->
tp_black == 1)) ; else __assert_fail ("TP_IS_BLACK(brother)",
"tport.c", 128, __extension__ __PRETTY_FUNCTION__); })); if (
(!(((brother)->tp_left)) || (((brother)->tp_left))->
tp_black == 1) && (!(((brother)->tp_right)) || (((
brother)->tp_right))->tp_black == 1)) { ((brother)->
tp_black = 0); node = dad; continue; } if ((!(((brother)->
tp_left)) || (((brother)->tp_left))->tp_black == 1)) { (
(((brother)->tp_right))->tp_black = 1); ((brother)->
tp_black = 0); tprb_left_rotate(top, brother); brother = ((dad
)->tp_left); } ((brother)->tp_black = (((node)->tp_dad
))->tp_black); ((((node)->tp_dad))->tp_black = 1); if
(((brother)->tp_left)) ((((brother)->tp_left))->tp_black
= 1); tprb_right_rotate(top, dad); node = *top; break; } } (
(node)->tp_black = 1); } extern int const tprb_dummy; static
inline int tprb_insert(tport_t **const tree, tport_t * const
node, tport_t **return_old) { tport_t *old, *dad, **slot; if
(tree == ((void*)0) || node == ((void*)0)) return -1; for (slot
= tree, old = *slot, dad = ((void*)0); old; old = *slot) { int
result = tp_cmp(node, old); if (result < 0) dad = old, slot
= &(((old)->tp_left)); else if (result > 0) dad = old
, slot = &(((old)->tp_right)); else break; } if (old ==
node) old = ((void*)0); else if (old) { if (!return_old) return
-1; if ((((node)->tp_left) = ((old)->tp_left))) ((((node
)->tp_left))->tp_dad) = node; if ((((node)->tp_right
) = ((old)->tp_right))) ((((node)->tp_right))->tp_dad
) = node; if (!(((node)->tp_dad) = ((old)->tp_dad))) *tree
= node; else if (((((node)->tp_dad))->tp_left) == old)
((((node)->tp_dad))->tp_left) = node; else ((void) sizeof
((((((node)->tp_dad))->tp_right) == old) ? 1 : 0), __extension__
({ if (((((node)->tp_dad))->tp_right) == old) ; else __assert_fail
("TP_RIGHT(TP_PARENT(node)) == old", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })), ((((node)->tp_dad))->tp_right
) = node; ((node)->tp_black = (old)->tp_black); ((old)->
tp_left = (old)->tp_right = (old)->tp_dad = ((void*)0))
; } else { *slot = node; ((node)->tp_dad) = dad; if (tree !=
slot) { tprb_balance_insert(tree, node); } else { ((node)->
tp_black = 1); } } ((void)0); if (return_old) *return_old = old
; return 0; } extern int const tprb_dummy; static inline int tprb_append
(tport_t **const tree, tport_t * const node) { tport_t *old, *
dad, **slot; if (tree == ((void*)0) || node == ((void*)0)) return
-1; for (slot = tree, old = *slot, dad = ((void*)0); old; old
= *slot) { if (old == node) return 0; if (tp_cmp(node, old) <
0) dad = old, slot = &(((old)->tp_left)); else dad = old
, slot = &(((old)->tp_right)); } *slot = node; ((node)
->tp_dad) = dad; if (tree != slot) { tprb_balance_insert(tree
, node); } else { ((node)->tp_black = 1); } ((void)0); return
0; } extern int const tprb_dummy; static inline void tprb_remove
(tport_t **top, tport_t *node) { tport_t *kid, *dad; int need_to_balance
; if (top == ((void*)0) || node == ((void*)0)) return; for (dad
= node; dad; dad = ((dad)->tp_dad)) if (dad == *top) break
; if (!dad) return; if (!((node)->tp_left) || !((node)->
tp_right)) dad = node; else for (dad = ((node)->tp_right);
((dad)->tp_left); dad = ((dad)->tp_left)) ; kid = ((dad
)->tp_left) ? ((dad)->tp_left) : ((dad)->tp_right); if
(!(((dad)->tp_dad))) *top = kid; else if (((((dad)->tp_dad
))->tp_left) == dad) ((((dad)->tp_dad))->tp_left) = kid
; else ((void) sizeof ((((((dad)->tp_dad))->tp_right) ==
dad) ? 1 : 0), __extension__ ({ if (((((dad)->tp_dad))->
tp_right) == dad) ; else __assert_fail ("TP_RIGHT(TP_PARENT(dad)) == dad"
, "tport.c", 128, __extension__ __PRETTY_FUNCTION__); })), ((
((dad)->tp_dad))->tp_right) = kid; if (kid) ((kid)->
tp_dad) = ((dad)->tp_dad); need_to_balance = kid &&
(!(dad) || (dad)->tp_black == 1); if (node != dad) { if (
!(((dad)->tp_dad) = ((node)->tp_dad))) *top = dad; else
if (((((dad)->tp_dad))->tp_left) == node) ((((dad)->
tp_dad))->tp_left) = dad; else ((void) sizeof ((((((dad)->
tp_dad))->tp_right) == node) ? 1 : 0), __extension__ ({ if
(((((dad)->tp_dad))->tp_right) == node) ; else __assert_fail
("TP_RIGHT(TP_PARENT(dad)) == node", "tport.c", 128, __extension__
__PRETTY_FUNCTION__); })), ((((dad)->tp_dad))->tp_right
) = dad; ((dad)->tp_black = (node)->tp_black); if ((((dad
)->tp_left) = ((node)->tp_left))) ((((dad)->tp_left)
)->tp_dad) = dad; if ((((dad)->tp_right) = ((node)->
tp_right))) ((((dad)->tp_right))->tp_dad) = dad; } ((node
)->tp_left = (node)->tp_right = (node)->tp_dad = ((void
*)0)); ((node)->tp_black = 0); if (need_to_balance) tprb_balance_delete
(top, kid); } extern int const tprb_dummy; static inline tport_t
*tprb_succ(tport_t const *node) { tport_t const *dad; if (((
node)->tp_right)) { for (node = ((node)->tp_right); ((node
)->tp_left); node = ((node)->tp_left)) ; return (tport_t
*)node; } for (dad = ((node)->tp_dad); dad && node
== ((dad)->tp_right); dad = ((node)->tp_dad)) node = dad
; return (tport_t *)dad; } extern int const tprb_dummy; static
inline tport_t *tprb_prec(tport_t const *node) { tport_t const
*dad; if (((node)->tp_left)) { for (node = ((node)->tp_left
); ((node)->tp_right); node = ((node)->tp_right)) ; return
(tport_t *)node; } for (dad = ((node)->tp_dad); dad &&
node == ((dad)->tp_left); dad = ((node)->tp_dad)) node
= dad; return (tport_t *)dad; } extern int const tprb_dummy;
static inline tport_t *tprb_first(tport_t const *node) { while
(node && ((node)->tp_left)) node = ((node)->tp_left
); return (tport_t *)node; } extern int const tprb_dummy; static
inline tport_t *tprb_last(tport_t const *node) { while (node
&& ((node)->tp_right)) node = ((node)->tp_right
); return (tport_t *)node; } extern int const tprb_dummy; static
inline int tprb_height(tport_t const *node) { int left, right
; if (!node) return 0; left = ((node)->tp_left) ? tprb_height
(((node)->tp_left)) : 0; right = ((node)->tp_right) ? tprb_height
(((node)->tp_right)) : 0; if (left > right) return left
+ 1; else return right + 1; } extern int const tprb_dummy
;
129
130#ifdef __clang__1
131#pragma clang diagnostic pop
132#endif
133
134static void tplist_insert(tport_t **list, tport_t *tp)
135{
136 if (*list == NULL((void*)0))
137 *list = tp;
138 else
139 tp->tp_right = *list, (*list)->tp_left = tp, *list = tp;
140
141 for (tp = *list; tp; tp = tp->tp_right) {
142 assert(tp->tp_left == NULL || tp == tp->tp_left->tp_right)((void) sizeof ((tp->tp_left == ((void*)0) || tp == tp->
tp_left->tp_right) ? 1 : 0), __extension__ ({ if (tp->tp_left
== ((void*)0) || tp == tp->tp_left->tp_right) ; else __assert_fail
("tp->tp_left == NULL || tp == tp->tp_left->tp_right"
, "tport.c", 142, __extension__ __PRETTY_FUNCTION__); }))
;
143 assert(tp->tp_right == NULL || tp == tp->tp_right->tp_left)((void) sizeof ((tp->tp_right == ((void*)0) || tp == tp->
tp_right->tp_left) ? 1 : 0), __extension__ ({ if (tp->tp_right
== ((void*)0) || tp == tp->tp_right->tp_left) ; else __assert_fail
("tp->tp_right == NULL || tp == tp->tp_right->tp_left"
, "tport.c", 143, __extension__ __PRETTY_FUNCTION__); }))
;
144 }
145}
146
147static void tplist_remove(tport_t **list, tport_t *tp)
148{
149 if (*list == tp) {
150 *list = tp->tp_right; assert(tp->tp_left == NULL)((void) sizeof ((tp->tp_left == ((void*)0)) ? 1 : 0), __extension__
({ if (tp->tp_left == ((void*)0)) ; else __assert_fail ("tp->tp_left == NULL"
, "tport.c", 150, __extension__ __PRETTY_FUNCTION__); }))
;
151 }
152 else if (tp->tp_left) {
153 tp->tp_left->tp_right = tp->tp_right;
154 }
155 if (tp->tp_right) {
156 tp->tp_right->tp_left = tp->tp_left;
157 }
158 TP_REMOVE(tp)((tp)->tp_left = (tp)->tp_right = (tp)->tp_dad = ((void
*)0))
;
159}
160
161enum {
162 /** Default per-thread read queue length */
163 THRP_PENDING = 8
164};
165
166struct tport_pending_s {
167 /* tport_pending_t *p_left, *p_right, *p_parent; */
168 void *p_client;
169 tport_pending_error_f *p_callback;
170 msg_t *p_msg;
171 unsigned short p_reported;
172 unsigned short p_on_success;
173};
174
175/** Return true if transport is master. */
176int tport_is_master(tport_t const *self)
177{
178 return
179 self &&
180 self->tp_master->mr_master == self;
181}
182
183/** Return true if transport is primary. */
184int tport_is_primary(tport_t const *self)
185{
186 return
187 self &&
188 self->tp_pri->pri_primary == self;
189}
190
191/** Return true if transport is secondary. */
192int tport_is_secondary(tport_t const *self)
193{
194 return
195 self &&
196 self->tp_master->mr_master != self &&
197 self->tp_pri->pri_primary != self;
198}
199
200/** Test if transport has been registered to su_root_t */
201int tport_is_registered(tport_t const *self)
202{
203 return self && self->tp_index != 0;
204}
205
206/** Test if transport is stream. */
207int tport_is_stream(tport_t const *self)
208{
209 return self && !self->tp_pre_framed && self->tp_addrinfo->ai_socktype == SOCK_STREAMSOCK_STREAM;
210}
211
212/** Test if transport is dgram. */
213int tport_is_dgram(tport_t const *self)
214{
215 return self && self->tp_addrinfo->ai_socktype == SOCK_DGRAMSOCK_DGRAM;
216}
217
218/** Test if transport is udp. */
219int tport_is_udp(tport_t const *self)
220{
221 return self && self->tp_addrinfo->ai_protocol == IPPROTO_UDPIPPROTO_UDP;
222}
223
224/** Test if transport is tcp. */
225int tport_is_tcp(tport_t const *self)
226{
227 return self && self->tp_addrinfo->ai_protocol == IPPROTO_TCPIPPROTO_TCP;
228}
229
230/** Return 1 if transport is reliable, 0 otherwise.
231 *
232 * (Note that this is part of external API).
233 */
234int tport_is_reliable(tport_t const *self)
235{
236 return self != NULL((void*)0) &&
237 (self->tp_addrinfo->ai_socktype == SOCK_STREAMSOCK_STREAM ||
238 self->tp_addrinfo->ai_socktype == SOCK_SEQPACKETSOCK_SEQPACKET);
239}
240
241/** Return 0 if self is local, nonzero otherwise.
242 *
243 * The return valu is the tport_via enum.
244 *
245 * @sa TPTAG_PUBLIC(), enum tport_via.
246 */
247int tport_is_public(tport_t const *self)
248{
249 return self && self->tp_pri->pri_public;
250}
251
252/** Return true if transport supports IPv4 */
253int tport_has_ip4(tport_t const *self)
254{
255 return self &&
256 (self->tp_addrinfo->ai_family == 0 ||
257 self->tp_addrinfo->ai_family == AF_INET2);
258}
259
260
261#if SU_HAVE_IN61
262/** Return true if transport supports IPv6 */
263int tport_has_ip6(tport_t const *self)
264{
265 return self &&
266 (self->tp_addrinfo->ai_family == 0 ||
267 self->tp_addrinfo->ai_family == AF_INET610);
268}
269#endif
270
271/** Return true if transport supports TLS. */
272int tport_has_tls(tport_t const *self)
273{
274 return self && self->tp_pri->pri_has_tls;
275}
276
277/** Return true if transport certificate verified successfully */
278int tport_is_verified(tport_t const *self)
279{
280 return tport_has_tls(self) && self->tp_is_connected && self->tp_verified;
281}
282
283/** Return true if transport is being updated. */
284int tport_is_updating(tport_t const *self)
285{
286 tport_primary_t *pri;
287
288 if (tport_is_master(self)) {
289 for (pri = self->tp_master->mr_primaries; pri; pri = pri->pri_next)
290 if (pri->pri_updating)
291 return 1;
292 }
293 else if (tport_is_primary(self)) {
294 return self->tp_pri->pri_updating;
295 }
296
297 return 0;
298}
299
300/** Test if transport has been closed.
301 *
302 * @since New in @VERSION_1_12_4
303 */
304inline int tport_is_closed(tport_t const *self)
305{
306 return self->tp_closed;
307}
308
309/** Test if transport has been shut down.
310 *
311 * @since New in @VERSION_1_12_4
312 */
313inline int tport_is_shutdown(tport_t const *self)
314{
315 return self->tp_closed || self->tp_send_close || self->tp_recv_close;
316}
317
318/** Test if transport connection has been established. @NEW_1_12_5. */
319int tport_is_connected(tport_t const *self)
320{
321 return self->tp_is_connected;
322}
323
324/** Test if transport can be used to send message. @NEW_1_12_7. */
325int tport_is_clear_to_send(tport_t const *self)
326{
327 return
328 tport_is_master(self) ||
329 tport_is_primary(self) ||
330 (tport_is_secondary(self) &&
331 tport_is_registered(self) &&
332 self->tp_reusable &&
333 !self->tp_closed &&
334 !self->tp_send_close);
335}
336
337/** Return true if transport has message in send queue. @NEW_1_12_7. */
338int tport_has_queued(tport_t const *self)
339{
340 return self && self->tp_queue && self->tp_queue[self->tp_qhead];
341}
342
343/** MTU for transport */
344su_inlinestatic inline unsigned tport_mtu(tport_t const *self)
345{
346 return self->tp_params->tpp_mtu;
347}
348
349/** Set IP TOS for socket */
350void tport_set_tos(su_socket_t socket, su_addrinfo_t *ai, int tos)
351{
352 if (tos >= 0 &&
353 ai->ai_family == AF_INET2 &&
354 setsockopt(socket, IPPROTO_IPIPPROTO_IP, IP_TOS1, (const void*)&tos, sizeof(tos)) < 0) {
355 SU_DEBUG_3(("tport: setsockopt(IP_TOS): %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 356, "tport: setsockopt(IP_TOS): %s\n", su_strerror
(su_errno()))) : (void)0)
356 su_strerror(su_errno())))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 356, "tport: setsockopt(IP_TOS): %s\n", su_strerror
(su_errno()))) : (void)0)
;
357 }
358}
359
360static
361tport_t *tport_connect(tport_primary_t *pri, su_addrinfo_t *ai,
362 tp_name_t const *tpn);
363
364static int bind6only_check(tport_master_t *mr);
365
366static
367int tport_server_addrinfo(tport_master_t *mr,
368 char const *canon,
369 int family,
370 char const *host,
371 char const *service,
372 char const *protocol,
373 char const * const transports[],
374 su_addrinfo_t **res);
375
376static int tport_get_local_addrinfo(tport_master_t *mr,
377 char const *port,
378 su_addrinfo_t const *hints,
379 su_addrinfo_t **return_ai);
380
381int tport_getaddrinfo(char const *node, char const *service,
382 su_addrinfo_t const *hints,
383 su_addrinfo_t **res);
384
385static void tport_freeaddrinfo(su_addrinfo_t *ai);
386
387static
388int tport_addrinfo_copy(su_addrinfo_t *dst, void *addr, socklen_t addrlen,
389 su_addrinfo_t const *src);
390
391static int
392 tport_bind_client(tport_master_t *self, tp_name_t const *tpn,
393 char const * const transports[], enum tport_via public,
394 tagi_t *tags),
395 tport_bind_server(tport_master_t *, tp_name_t const *tpn,
396 char const * const transports[], enum tport_via public,
397 tagi_t *tags),
398
399 tport_wakeup_pri(su_root_magic_t *m, su_wait_t *w, tport_t *self),
400 tport_base_wakeup(tport_t *self, int events),
401 tport_connected(su_root_magic_t *m, su_wait_t *w, tport_t *self),
402 tport_resolve(tport_t *self, msg_t *msg, tp_name_t const *tpn),
403 tport_send_error(tport_t *, msg_t *, tp_name_t const *, char const *who),
404 tport_send_fatal(tport_t *, msg_t *, tp_name_t const *, char const *who),
405 tport_queue(tport_t *self, msg_t *msg),
406 tport_queue_rest(tport_t *self, msg_t *msg, msg_iovec_t iov[], size_t iovused),
407 tport_pending_error(tport_t *self, su_sockaddr_t const *dst, int error),
408 tport_pending_errmsg(tport_t *self, msg_t *msg, int error);
409
410static ssize_t tport_vsend(tport_t *self, msg_t *msg, tp_name_t const *tpn,
411 msg_iovec_t iov[], size_t iovused,
412 struct sigcomp_compartment *cc);
413
414tport_t *tport_by_addrinfo(tport_primary_t const *pri,
415 su_addrinfo_t const *ai,
416 tp_name_t const *tpn);
417
418void tport_peer_address(tport_t *self, msg_t *msg);
419
420static void tport_parse(tport_t *self, int complete, su_time_t now);
421
422static tport_primary_t *tport_alloc_primary(tport_master_t *mr,
423 tport_vtable_t const *vtable,
424 tp_name_t tpn[1],
425 su_addrinfo_t *ai,
426 tagi_t const *tags,
427 char const **return_culprit);
428
429static tport_primary_t *tport_listen(tport_master_t *mr,
430 tport_vtable_t const *vtable,
431 tp_name_t tpn[1],
432 su_addrinfo_t *ai,
433 tagi_t *tags);
434static void tport_zap_primary(tport_primary_t *);
435
436static char *localipname(int pf, char *buf, size_t bufsiz);
437static int getprotohints(su_addrinfo_t *hints,
438 char const *proto, int flags);
439
440
441/* Stack class used when transports are being destroyed */
442static
443void tport_destroy_recv(tp_stack_t *stack, tport_t *tp,
444 msg_t *msg, tp_magic_t *magic,
445 su_time_t received)
446{
447 msg_destroy(msg);
448}
449
450static
451void tport_destroy_error(tp_stack_t *stack, tport_t *tp,
452 int errcode, char const *remote)
453{
454}
455
456static
457msg_t *tport_destroy_alloc(tp_stack_t *stack, int flags,
458 char const data[], usize_t len,
459 tport_t const *tp,
460 tp_client_t *tpc)
461{
462 return NULL((void*)0);
463}
464
465/** Name for "any" transport. @internal */
466static char const tpn_any[] = "*";
467
468/** Create the master transport.
469 *
470 * Master transport object is used to bind the protocol using transport with
471 * actual transport objects corresponding to TCP, UDP, etc.
472 *
473 * @sa tport_tbind()
474 *
475 * @TAGS
476 * TPTAG_LOG(), TPTAG_DUMP(), tags used with tport_set_params(), especially
477 * TPTAG_QUEUESIZE().
478 */
479tport_t *tport_tcreate(tp_stack_t *stack,
480 tp_stack_class_t const *tpac,
481 su_root_t *root,
482 tag_type_t tag, tag_value_t value, ...)
483{
484 tport_master_t *mr;
485 tp_name_t *tpn;
486 tport_params_t *tpp;
487 ta_list ta;
488
489 if (!stack || !tpac || !root) {
490 su_seterrno(EINVAL22);
491 return NULL((void*)0);
492 }
493
494 mr = su_home_clone(NULL((void*)0), sizeof *mr);
495 if (!mr)
496 return NULL((void*)0);
497
498 SU_DEBUG_7(("%s(): %p\n", "tport_create", (void *)mr))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 498, "%s(): %p\n", "tport_create", (void *)
mr)) : (void)0)
;
499
500 mr->mr_stack = stack;
501 mr->mr_tpac = tpac;
502 mr->mr_root = root;
503
504 mr->mr_master->tp_master = mr;
505 mr->mr_master->tp_params = tpp = mr->mr_params;
506
507 mr->mr_master->tp_reusable = 1;
508 tpp->tpp_mtu = UINT_MAX(2147483647 *2U +1U);
509 tpp->tpp_thrprqsize = THRP_PENDING;
510 tpp->tpp_qsize = TPORT_QUEUESIZE;
511 tpp->tpp_sdwn_error = 1;
512 tpp->tpp_idle = UINT_MAX(2147483647 *2U +1U);
513 tpp->tpp_timeout = UINT_MAX(2147483647 *2U +1U);
514 tpp->tpp_sigcomp_lifetime = UINT_MAX(2147483647 *2U +1U);
515 tpp->tpp_socket_keepalive = 30;
516 tpp->tpp_keepalive = 0;
517 tpp->tpp_pingpong = 0;
518 tpp->tpp_pong2ping = 0;
519 tpp->tpp_stun_server = 1;
520 tpp->tpp_tos = -1; /* set invalid, valid values are 0-255 */
521
522 tpn = mr->mr_master->tp_name;
523 tpn->tpn_proto = "*";
524 tpn->tpn_host = "*";
525 tpn->tpn_canon = "*";
526 tpn->tpn_port = "*";
527
528 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
529
530 tport_set_params(mr->mr_master, ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
531
532#if HAVE_SOFIA_STUN
533 tport_init_stun_server(mr, ta_args(ta)(ta).tl);
534#endif
535
536 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
537
538 return mr->mr_master;
539}
540
541/** Destroy the master transport. */
542void tport_destroy(tport_t *self)
543{
544 tport_master_t *mr;
545
546 static tp_stack_class_t tport_destroy_tpac[1] =
547 {{
548 sizeof tport_destroy_tpac,
549 /* tpac_recv */ tport_destroy_recv,
550 /* tpac_error */ tport_destroy_error,
551 /* tpac_alloc */ tport_destroy_alloc,
552 /* tpac_address */ NULL((void*)0)
553 }};
554
555 SU_DEBUG_7(("%s(%p)\n", __func__, (void *)self))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 555, "%s(%p)\n", __func__, (void *)self)) :
(void)0)
;
556
557 if (self == NULL((void*)0))
558 return;
559
560 assert(tport_is_master(self))((void) sizeof ((tport_is_master(self)) ? 1 : 0), __extension__
({ if (tport_is_master(self)) ; else __assert_fail ("tport_is_master(self)"
, "tport.c", 560, __extension__ __PRETTY_FUNCTION__); }))
;
561 if (!tport_is_master(self))
562 return;
563
564 mr = (tport_master_t *)self;
565 mr->mr_tpac = tport_destroy_tpac;
566
567 while (mr->mr_primaries)
568 tport_zap_primary(mr->mr_primaries);
569
570#if HAVE_SOFIA_STUN
571 tport_deinit_stun_server(mr);
572#endif
573
574 if (mr->mr_dump_file)
575 fclose(mr->mr_dump_file), mr->mr_dump_file = NULL((void*)0);
576
577 if (mr->mr_timer)
578 su_timer_destroy(mr->mr_timer), mr->mr_timer = NULL((void*)0);
579
580 su_home_zap(mr->mr_home)su_home_unref((mr->mr_master->tp_home));
581}
582
583
584/** Allocate a primary transport */
585static
586tport_primary_t *tport_alloc_primary(tport_master_t *mr,
587 tport_vtable_t const *vtable,
588 tp_name_t tpn[1],
589 su_addrinfo_t *ai,
590 tagi_t const *tags,
591 char const **return_culprit)
592{
593 tport_primary_t *pri, **next;
594 tport_t *tp;
595 int save_errno;
596
597 for (next = &mr->mr_primaries; *next; next = &(*next)->pri_next)
598 ;
599
600 assert(vtable->vtp_pri_size >= sizeof *pri)((void) sizeof ((vtable->vtp_pri_size >= sizeof *pri) ?
1 : 0), __extension__ ({ if (vtable->vtp_pri_size >= sizeof
*pri) ; else __assert_fail ("vtable->vtp_pri_size >= sizeof *pri"
, "tport.c", 600, __extension__ __PRETTY_FUNCTION__); }))
;
601
602 if ((pri = su_home_clone(mr->mr_homemr_master->tp_home, vtable->vtp_pri_size))) {
603 tport_t *tp = pri->pri_primary;
604 pri->pri_vtable = vtable;
605 pri->pri_public = vtable->vtp_public;
606
607 tp->tp_master = mr;
608 tp->tp_pri = pri;
609 tp->tp_socket = INVALID_SOCKET((su_socket_t)INVALID_SOCKET);
610
611 tp->tp_magic = mr->mr_master->tp_magic;
612
613 tp->tp_params = pri->pri_params;
614 memcpy(tp->tp_params, mr->mr_params, sizeof (*tp->tp_params));
615 tp->tp_reusable = mr->mr_master->tp_reusable;
616
617 if (!pri->pri_public)
618 tp->tp_addrinfo->ai_addr = &tp->tp_addr->su_sa;
619
620 SU_DEBUG_5(("%s(%p): new primary tport %p\n", __func__, (void *)mr,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 621, "%s(%p): new primary tport %p\n", __func__
, (void *)mr, (void *)pri)) : (void)0)
621 (void *)pri))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 621, "%s(%p): new primary tport %p\n", __func__
, (void *)mr, (void *)pri)) : (void)0)
;
622 }
623
624 *next = pri;
625 tp = pri->pri_primary;
626
627 if (!tp)
628 *return_culprit = "alloc";
629 else if (tport_set_params(tp, TAG_NEXT(tags)tag_next, (tag_value_t)(tags)) < 0)
630 *return_culprit = "tport_set_params";
631 else if (vtable->vtp_init_primary &&
632 vtable->vtp_init_primary(pri, tpn, ai, tags, return_culprit) < 0)
633 ;
634 else if (tport_setname(tp, vtable->vtp_name, ai, tpn->tpn_canon) == -1)
635 *return_culprit = "tport_setname";
636 else if (tpn->tpn_ident &&
637 !(tp->tp_name->tpn_ident = su_strdup(tp->tp_home, tpn->tpn_ident)))
638 *return_culprit = "alloc ident";
639 else
640 return pri; /* Success */
641
642 save_errno = su_errno();
643 tport_zap_primary(pri);
644 su_seterrno(save_errno);
645
646 return NULL((void*)0);
647}
648
649
650/** Destroy a primary transport and its secondary transports. @internal */
651static
652void tport_zap_primary(tport_primary_t *pri)
653{
654 tport_primary_t **prip;
655
656 if (pri == NULL((void*)0))
657 return;
658
659 assert(tport_is_primary(pri->pri_primary))((void) sizeof ((tport_is_primary(pri->pri_primary)) ? 1 :
0), __extension__ ({ if (tport_is_primary(pri->pri_primary
)) ; else __assert_fail ("tport_is_primary(pri->pri_primary)"
, "tport.c", 659, __extension__ __PRETTY_FUNCTION__); }))
;
660
661 if (pri->pri_vtable->vtp_deinit_primary)
662 pri->pri_vtable->vtp_deinit_primary(pri);
663
664 while (pri->pri_open)
665 tport_zap_secondary(pri->pri_open);
666 while (pri->pri_closed)
667 tport_zap_secondary(pri->pri_closed);
668
669 /* We have just a single-linked list for primary transports */
670 for (prip = &pri->pri_masterpri_primary->tp_master->mr_primaries;
671 *prip != pri;
672 prip = &(*prip)->pri_next)
673 assert(*prip)((void) sizeof ((*prip) ? 1 : 0), __extension__ ({ if (*prip)
; else __assert_fail ("*prip", "tport.c", 673, __extension__
__PRETTY_FUNCTION__); }))
;
674
675 *prip = pri->pri_next;
676
677 tport_zap_secondary((tport_t *)pri);
678}
679
680/**Create a primary transport object with socket.
681 *
682 * Creates a primary transport object with a server socket, and then
683 * registers the socket with suitable events to the root.
684 *
685 * @param dad parent (master or primary) transport object
686 * @param ai pointer to addrinfo structure
687 * @param canon canonical name of node
688 * @param protoname name of the protocol
689 */
690static
691tport_primary_t *tport_listen(tport_master_t *mr,
692 tport_vtable_t const *vtable,
693 tp_name_t tpn[1],
694 su_addrinfo_t *ai,
695 tagi_t *tags)
696{
697 tport_primary_t *pri = NULL((void*)0);
698
699 int err;
700 int errlevel = 3;
701 char buf[TPORT_HOSTPORTSIZE(55)];
702
703 char const *protoname = vtable->vtp_name;
704 char const *culprit = "unknown";
705
706 su_sockaddr_t *su = (void *)ai->ai_addr;
707
708 /* Log an error, return error */
709#define TPORT_LISTEN_ERROR(errno, what)((void)(err = (*__errno_location ()), ((err == 98 || err == 97
|| err == 94 || err == 93 || err == 92 ? 7 : 3) < ((tport_log
!= ((void*)0) && tport_log->log_init) == 0 ? 9 : (
(tport_log != ((void*)0) && tport_log->log_init >
1) ? tport_log->log_level : su_log_default->log_level)
) ? _su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 709, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, pri ? (void
*)pri : (void *)mr, what, ai->ai_family, protoname, tport_hostport
(buf, sizeof(buf), su, 2), su_strerror(err)) : (void)0), tport_zap_primary
(pri), su_seterrno(err)), (void *)((void*)0))
\
710 ((void)(err = errno(*__errno_location ()), \
711 ((err == EADDRINUSE98 || err == EAFNOSUPPORT97 || \
712 err == ESOCKTNOSUPPORT94 || err == EPROTONOSUPPORT93 || \
713 err == ENOPROTOOPT92 ? 7 : 3) < SU_LOG_LEVEL((tport_log != ((void*)0) && tport_log->log_init) ==
0 ? 9 : ((tport_log != ((void*)0) && tport_log->log_init
> 1) ? tport_log->log_level : su_log_default->log_level
))
? \
714 su_llog(tport_log, errlevel, \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 719, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, pri ? (void
*)pri : (void *)mr, what, ai->ai_family, protoname, tport_hostport
(buf, sizeof(buf), su, 2), su_strerror(err))
715 "%s(%p): %s(pf=%d %s/%s): %s\n", \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 719, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, pri ? (void
*)pri : (void *)mr, what, ai->ai_family, protoname, tport_hostport
(buf, sizeof(buf), su, 2), su_strerror(err))
716 __func__, pri ? (void *)pri : (void *)mr, what, \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 719, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, pri ? (void
*)pri : (void *)mr, what, ai->ai_family, protoname, tport_hostport
(buf, sizeof(buf), su, 2), su_strerror(err))
717 ai->ai_family, protoname, \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 719, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, pri ? (void
*)pri : (void *)mr, what, ai->ai_family, protoname, tport_hostport
(buf, sizeof(buf), su, 2), su_strerror(err))
718 tport_hostport(buf, sizeof(buf), su, 2), \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 719, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, pri ? (void
*)pri : (void *)mr, what, ai->ai_family, protoname, tport_hostport
(buf, sizeof(buf), su, 2), su_strerror(err))
719 su_strerror(err))_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 719, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, pri ? (void
*)pri : (void *)mr, what, ai->ai_family, protoname, tport_hostport
(buf, sizeof(buf), su, 2), su_strerror(err))
: (void)0), \
720 tport_zap_primary(pri), \
721 su_seterrno(err)), \
722 (void *)NULL((void*)0))
723
724 /* Create a primary transport object for another transport. */
725 pri = tport_alloc_primary(mr, vtable, tpn, ai, tags, &culprit);
726 if (pri == NULL((void*)0))
727 return TPORT_LISTEN_ERROR(su_errno(), culprit)((void)(err = su_errno(), ((err == 98 || err == 97 || err == 94
|| err == 93 || err == 92 ? 7 : 3) < ((tport_log != ((void
*)0) && tport_log->log_init) == 0 ? 9 : ((tport_log
!= ((void*)0) && tport_log->log_init > 1) ? tport_log
->log_level : su_log_default->log_level)) ? _su_llog(tport_log
, errlevel, "tport.c", (const char *)__func__, 727, "%s(%p): %s(pf=%d %s/%s): %s\n"
, __func__, pri ? (void *)pri : (void *)mr, culprit, ai->ai_family
, protoname, tport_hostport(buf, sizeof(buf), su, 2), su_strerror
(err)) : (void)0), tport_zap_primary(pri), su_seterrno(err)),
(void *)((void*)0))
;
728
729 if (pri->pri_primary->tp_socket != INVALID_SOCKET((su_socket_t)INVALID_SOCKET)) {
730 int index = 0;
731 tport_t *tp = pri->pri_primary;
732 su_wait_t wait[1] = { SU_WAIT_INIT{ ((su_socket_t)INVALID_SOCKET), 0, 0 } };
733
734 if (su_wait_create(wait, tp->tp_socket, tp->tp_events) == -1)
735 return TPORT_LISTEN_ERROR(su_errno(), "su_wait_create")((void)(err = su_errno(), ((err == 98 || err == 97 || err == 94
|| err == 93 || err == 92 ? 7 : 3) < ((tport_log != ((void
*)0) && tport_log->log_init) == 0 ? 9 : ((tport_log
!= ((void*)0) && tport_log->log_init > 1) ? tport_log
->log_level : su_log_default->log_level)) ? _su_llog(tport_log
, errlevel, "tport.c", (const char *)__func__, 735, "%s(%p): %s(pf=%d %s/%s): %s\n"
, __func__, pri ? (void *)pri : (void *)mr, "su_wait_create",
ai->ai_family, protoname, tport_hostport(buf, sizeof(buf)
, su, 2), su_strerror(err)) : (void)0), tport_zap_primary(pri
), su_seterrno(err)), (void *)((void*)0))
;
736
737 /* Register receiving or accepting function with events specified above */
738 index = su_root_register(mr->mr_root, wait, tport_wakeup_pri, tp, 0);
739 if (index == -1) {
740 su_wait_destroy(wait);
741 return TPORT_LISTEN_ERROR(su_errno(), "su_root_register")((void)(err = su_errno(), ((err == 98 || err == 97 || err == 94
|| err == 93 || err == 92 ? 7 : 3) < ((tport_log != ((void
*)0) && tport_log->log_init) == 0 ? 9 : ((tport_log
!= ((void*)0) && tport_log->log_init > 1) ? tport_log
->log_level : su_log_default->log_level)) ? _su_llog(tport_log
, errlevel, "tport.c", (const char *)__func__, 741, "%s(%p): %s(pf=%d %s/%s): %s\n"
, __func__, pri ? (void *)pri : (void *)mr, "su_root_register"
, ai->ai_family, protoname, tport_hostport(buf, sizeof(buf
), su, 2), su_strerror(err)) : (void)0), tport_zap_primary(pri
), su_seterrno(err)), (void *)((void*)0))
;
742 }
743
744 tp->tp_index = index;
745 }
746
747 pri->pri_primary->tp_has_connection = 0;
748
749 SU_DEBUG_5(("%s(%p): %s " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 751, "%s(%p): %s " "%s/%s:%s%s%s%s%s" "\n",
__func__, (void *)pri, "listening at", (pri->pri_primary->
tp_name)->tpn_proto, (pri->pri_primary->tp_name)->
tpn_host, (pri->pri_primary->tp_name)->tpn_port, (pri
->pri_primary->tp_name)->tpn_comp ? ";comp=" : "", (
pri->pri_primary->tp_name)->tpn_comp ? (pri->pri_primary
->tp_name)->tpn_comp : "", (pri->pri_primary->tp_name
)->tpn_ident ? "/" : "", (pri->pri_primary->tp_name)
->tpn_ident ? (pri->pri_primary->tp_name)->tpn_ident
: "")) : (void)0)
750 __func__, (void *)pri, "listening at",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 751, "%s(%p): %s " "%s/%s:%s%s%s%s%s" "\n",
__func__, (void *)pri, "listening at", (pri->pri_primary->
tp_name)->tpn_proto, (pri->pri_primary->tp_name)->
tpn_host, (pri->pri_primary->tp_name)->tpn_port, (pri
->pri_primary->tp_name)->tpn_comp ? ";comp=" : "", (
pri->pri_primary->tp_name)->tpn_comp ? (pri->pri_primary
->tp_name)->tpn_comp : "", (pri->pri_primary->tp_name
)->tpn_ident ? "/" : "", (pri->pri_primary->tp_name)
->tpn_ident ? (pri->pri_primary->tp_name)->tpn_ident
: "")) : (void)0)
751 TPN_ARGS(pri->pri_primary->tp_name)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 751, "%s(%p): %s " "%s/%s:%s%s%s%s%s" "\n",
__func__, (void *)pri, "listening at", (pri->pri_primary->
tp_name)->tpn_proto, (pri->pri_primary->tp_name)->
tpn_host, (pri->pri_primary->tp_name)->tpn_port, (pri
->pri_primary->tp_name)->tpn_comp ? ";comp=" : "", (
pri->pri_primary->tp_name)->tpn_comp ? (pri->pri_primary
->tp_name)->tpn_comp : "", (pri->pri_primary->tp_name
)->tpn_ident ? "/" : "", (pri->pri_primary->tp_name)
->tpn_ident ? (pri->pri_primary->tp_name)->tpn_ident
: "")) : (void)0)
;
752
753 return pri;
754}
755
756int tport_bind_socket(int socket,
757 su_addrinfo_t *ai,
758 char const **return_culprit)
759{
760 su_sockaddr_t *su = (su_sockaddr_t *)ai->ai_addr;
761 socklen_t sulen = (socklen_t)(ai->ai_addrlen);
762
763 if (bind(socket, ai->ai_addr, sulen) == -1) {
764 return *return_culprit = "bind", -1;
765 }
766
767 if (getsockname(socket, &su->su_sa, &sulen) == SOCKET_ERRORSOCKET_ERROR) {
768 return *return_culprit = "getsockname", -1;
769 }
770
771 ai->ai_addrlen = sulen;
772
773#if defined (__linux__1) && defined (SU_HAVE_IN61)
774 if (ai->ai_family == AF_INET610) {
775 if (!SU_SOCKADDR_INADDR_ANY(su)((su)->su_sa.sa_family == 2 ? ((su)->su_sin.sin_addr.s_addr
== ((in_addr_t) 0x00000000)) : ((su)->su_sa.sa_family == 10
? (memcmp(&(su)->su_sin6.sin6_addr, (&in6addr_any
), sizeof(*(&in6addr_any))) == 0) : 0))
&&
776 (IN6_IS_ADDR_V4MAPPED(&su->su_sin6.sin6_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&su->su_sin6.sin6_addr); __a->__in6_u.__u6_addr32
[0] == 0 && __a->__in6_u.__u6_addr32[1] == 0 &&
__a->__in6_u.__u6_addr32[2] == htonl (0xffff); }))
||
777 IN6_IS_ADDR_V4COMPAT(&su->su_sin6.sin6_addr)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr
*) (&su->su_sin6.sin6_addr); __a->__in6_u.__u6_addr32
[0] == 0 && __a->__in6_u.__u6_addr32[1] == 0 &&
__a->__in6_u.__u6_addr32[2] == 0 && ntohl (__a->
__in6_u.__u6_addr32[3]) > 1; }))
)) {
778 su_sockaddr_t su0[1];
779
780 memcpy(su0, su, sizeof su0);
781
782 memset(su, 0, ai->ai_addrlen = sizeof su->su_sin);
783 su->su_familysu_sa.sa_family = ai->ai_family = AF_INET2;
784 su->su_portsu_sin.sin_port = su0->su_portsu_sin.sin_port;
785
786#ifndef IN6_V4MAPPED_TO_INADDR
787#define IN6_V4MAPPED_TO_INADDR(in6, in4)memcpy((in4), 12 + (uint8_t *)(in6), sizeof(struct in_addr)) \
788 memcpy((in4), 12 + (uint8_t *)(in6), sizeof(struct in_addr))
789#endif
790 IN6_V4MAPPED_TO_INADDR(&su0->su_sin6.sin6_addr, &su->su_sin.sin_addr)memcpy((&su->su_sin.sin_addr), 12 + (uint8_t *)(&su0
->su_sin6.sin6_addr), sizeof(struct in_addr))
;
791 }
792 }
793#endif
794
795 return 0;
796}
797
798
799/** Indicate stack that a transport has been updated */
800void tport_has_been_updated(tport_t *self)
801{
802 self->tp_pri->pri_updating = 0;
803
804 if (self->tp_master->mr_tpac->tpac_address)
805 self->tp_master->mr_tpac->tpac_address(self->tp_master->mr_stack, self);
806}
807
808
809static
810int tport_set_events(tport_t *self, int set, int clear)
811{
812 int events;
813
814 if (self == NULL((void*)0))
815 return -1;
816
817 events = (self->tp_events | set) & ~clear;
818 self->tp_events = events;
819
820 if (self->tp_pri->pri_vtable->vtp_set_events)
821 return self->tp_pri->pri_vtable->vtp_set_events(self);
822
823 SU_DEBUG_7(("tport_set_events(%p): events%s%s%s\n", (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 827, "tport_set_events(%p): events%s%s%s\n"
, (void *)self, (events & (0x001)) ? " IN" : "", (events &
(0x004)) ? " OUT" : "", (0x004) != (0x004) && (events
& (0x004)) ? " CONNECT" : "")) : (void)0)
824 (events & SU_WAIT_IN) ? " IN" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 827, "tport_set_events(%p): events%s%s%s\n"
, (void *)self, (events & (0x001)) ? " IN" : "", (events &
(0x004)) ? " OUT" : "", (0x004) != (0x004) && (events
& (0x004)) ? " CONNECT" : "")) : (void)0)
825 (events & SU_WAIT_OUT) ? " OUT" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 827, "tport_set_events(%p): events%s%s%s\n"
, (void *)self, (events & (0x001)) ? " IN" : "", (events &
(0x004)) ? " OUT" : "", (0x004) != (0x004) && (events
& (0x004)) ? " CONNECT" : "")) : (void)0)
826 SU_WAIT_CONNECT != SU_WAIT_OUT &&(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 827, "tport_set_events(%p): events%s%s%s\n"
, (void *)self, (events & (0x001)) ? " IN" : "", (events &
(0x004)) ? " OUT" : "", (0x004) != (0x004) && (events
& (0x004)) ? " CONNECT" : "")) : (void)0)
827 (events & SU_WAIT_CONNECT) ? " CONNECT" : ""))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 827, "tport_set_events(%p): events%s%s%s\n"
, (void *)self, (events & (0x001)) ? " IN" : "", (events &
(0x004)) ? " OUT" : "", (0x004) != (0x004) && (events
& (0x004)) ? " CONNECT" : "")) : (void)0)
;
828
829 return
830 su_root_eventmask(self->tp_master->mr_root,
831 self->tp_index,
832 self->tp_socket,
833 self->tp_events = events);
834}
835
836/**Allocate a secondary transport. @internal
837 *
838 * Create a secondary transport object. The new transport initally shares
839 * parameters structure with the original transport.
840 *
841 * @param pri primary transport
842 * @param socket socket for transport
843 * @parma accepted true if the socket was accepted from server socket
844 *
845 * @return
846 * Pointer to the newly created transport, or NULL upon an error.
847 *
848 * @note The socket is always closed upon error.
849 */
850tport_t *tport_alloc_secondary(tport_primary_t *pri,
851 int socket,
852 int accepted,
853 char const **return_reason)
854{
855 tport_master_t *mr = pri->pri_masterpri_primary->tp_master;
856 tport_t *self;
857
858 self = su_home_clone(mr->mr_homemr_master->tp_home, pri->pri_vtable->vtp_secondary_size);
859
860 if (self) {
861 SU_DEBUG_7(("%s(%p): new secondary tport %p\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 862, "%s(%p): new secondary tport %p\n", __func__
, (void *)pri, (void *)self)) : (void)0)
862 __func__, (void *)pri, (void *)self))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 862, "%s(%p): new secondary tport %p\n", __func__
, (void *)pri, (void *)self)) : (void)0)
;
863
864 self->tp_refs = -1; /* Freshly allocated */
865 self->tp_master = mr;
866 self->tp_pri = pri;
867 self->tp_params = pri->pri_params;
868 self->tp_accepted = accepted != 0;
869 self->tp_reusable = pri->pri_primary->tp_reusable;
870
871 self->tp_magic = pri->pri_primary->tp_magic;
872
873 self->tp_addrinfo->ai_addr = (void *)self->tp_addr;
874
875 self->tp_socket = socket;
876
877 self->tp_timer = su_timer_create(su_root_task(mr->mr_root), 0);
878 self->tp_stime = self->tp_ktime = self->tp_rtime = su_now();
879
880 if (pri->pri_vtable->vtp_init_secondary &&
881
882 pri->pri_vtable->vtp_init_secondary(self, socket, accepted, return_reason) < 0) {
883
884 if (pri->pri_vtable->vtp_deinit_secondary) {
885 pri->pri_vtable->vtp_deinit_secondary(self);
886 }
887 su_timer_destroy(self->tp_timer);
888 su_home_zap(self->tp_home)su_home_unref((self->tp_home));
889
890 return NULL((void*)0);
891 }
892
893 /* Set IP TOS if it is set in primary */
894 tport_set_tos(socket,
895 pri->pri_primary->tp_addrinfo,
896 pri->pri_params->tpp_tos);
897 }
898 else {
899 *return_reason = "malloc";
900 }
901
902 return self;
903}
904
905
906/** Create a connected transport object with socket.
907 *
908 * The function tport_connect() creates a secondary transport with a
909 * connected socket. It registers the socket with suitable events to the
910 * root.
911 *
912 * @param pri primary transport object
913 * @param ai pointer to addrinfo structure
914 * @param tpn canonical name of node
915 */
916static
917tport_t *tport_connect(tport_primary_t *pri,
918 su_addrinfo_t *ai,
919 tp_name_t const *tpn)
920{
921 tport_t *tp;
922
923 if (ai == NULL((void*)0) || ai->ai_addrlen > sizeof (pri->pri_primary->tp_addr))
924 return NULL((void*)0);
925
926 if (pri->pri_vtable->vtp_connect)
927 return pri->pri_vtable->vtp_connect(pri, ai, tpn);
928
929 tp = tport_base_connect(pri, ai, ai, tpn);
930 if (tp)
931 tport_set_secondary_timer(tp);
932 return tp;
933}
934
935/**Create a connected transport object with socket.
936 *
937 * The function tport_connect() creates a secondary transport with a
938 * connected socket. It registers the socket with suitable events to the
939 * root.
940 *
941 * @param pri primary transport object
942 * @param ai pointer to addrinfo structure describing socket
943 * @param real_ai pointer to addrinfo structure describing real target
944 * @param tpn canonical name of node
945 */
946tport_t *tport_base_connect(tport_primary_t *pri,
947 su_addrinfo_t *ai,
948 su_addrinfo_t *real_ai,
949 tp_name_t const *tpn)
950{
951 tport_t *self = NULL((void*)0);
952
953 su_socket_t s, server_socket;
954 su_wakeup_f wakeup = tport_wakeup;
955 int events = SU_WAIT_IN(0x001) | SU_WAIT_ERR(0x008);
956
957 int err;
958 unsigned errlevel = 3;
959 char buf[TPORT_HOSTPORTSIZE(55)];
960 char const *what;
961
962 /* Log an error, return error */
963#define TPORT_CONNECT_ERROR(errno, what)return ((void)(err = (*__errno_location ()), (((tport_log != (
(void*)0) && tport_log->log_init) == 0 ? 9 : ((tport_log
!= ((void*)0) && tport_log->log_init > 1) ? tport_log
->log_level : su_log_default->log_level)) >= errlevel
? _su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 963, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, (void *)pri
, "what", ai->ai_family, tpn->tpn_proto, tport_hostport
(buf, sizeof(buf), (void *)ai->ai_addr, 2), su_strerror(err
)) : (void)0), tport_zap_secondary(self), su_seterrno(err)), (
void *)((void*)0))
\
964 return \
965 ((void)(err = errno(*__errno_location ()), \
966 (SU_LOG_LEVEL((tport_log != ((void*)0) && tport_log->log_init) ==
0 ? 9 : ((tport_log != ((void*)0) && tport_log->log_init
> 1) ? tport_log->log_level : su_log_default->log_level
))
>= errlevel ? \
967 su_llog(tport_log, errlevel, \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 973, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, (void *)pri
, #what, ai->ai_family, tpn->tpn_proto, tport_hostport(
buf, sizeof(buf), (void *)ai->ai_addr, 2), su_strerror(err
))
968 "%s(%p): %s(pf=%d %s/%s): %s\n", \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 973, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, (void *)pri
, #what, ai->ai_family, tpn->tpn_proto, tport_hostport(
buf, sizeof(buf), (void *)ai->ai_addr, 2), su_strerror(err
))
969 __func__, (void *)pri, #what, ai->ai_family, \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 973, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, (void *)pri
, #what, ai->ai_family, tpn->tpn_proto, tport_hostport(
buf, sizeof(buf), (void *)ai->ai_addr, 2), su_strerror(err
))
970 tpn->tpn_proto, \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 973, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, (void *)pri
, #what, ai->ai_family, tpn->tpn_proto, tport_hostport(
buf, sizeof(buf), (void *)ai->ai_addr, 2), su_strerror(err
))
971 tport_hostport(buf, sizeof(buf), \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 973, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, (void *)pri
, #what, ai->ai_family, tpn->tpn_proto, tport_hostport(
buf, sizeof(buf), (void *)ai->ai_addr, 2), su_strerror(err
))
972 (void *)ai->ai_addr, 2), \_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 973, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, (void *)pri
, #what, ai->ai_family, tpn->tpn_proto, tport_hostport(
buf, sizeof(buf), (void *)ai->ai_addr, 2), su_strerror(err
))
973 su_strerror(err))_su_llog(tport_log, errlevel, "tport.c", (const char *)__func__
, 973, "%s(%p): %s(pf=%d %s/%s): %s\n", __func__, (void *)pri
, #what, ai->ai_family, tpn->tpn_proto, tport_hostport(
buf, sizeof(buf), (void *)ai->ai_addr, 2), su_strerror(err
))
: (void)0), \
974 tport_zap_secondary(self), \
975 su_seterrno(err)), \
976 (void *)NULL((void*)0))
977
978 s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
979 if (s == INVALID_SOCKET((su_socket_t)INVALID_SOCKET))
980 TPORT_CONNECT_ERROR(su_errno(), "socket")return ((void)(err = su_errno(), (((tport_log != ((void*)0) &&
tport_log->log_init) == 0 ? 9 : ((tport_log != ((void*)0)
&& tport_log->log_init > 1) ? tport_log->log_level
: su_log_default->log_level)) >= errlevel ? _su_llog(tport_log
, errlevel, "tport.c", (const char *)__func__, 980, "%s(%p): %s(pf=%d %s/%s): %s\n"
, __func__, (void *)pri, "\"socket\"", ai->ai_family, tpn->
tpn_proto, tport_hostport(buf, sizeof(buf), (void *)ai->ai_addr
, 2), su_strerror(err)) : (void)0), tport_zap_secondary(self)
, su_seterrno(err)), (void *)((void*)0))
;
981
982 what = "tport_alloc_secondary";
983 if ((self = tport_alloc_secondary(pri, s, 0, &what)) == NULL((void*)0))
984 TPORT_CONNECT_ERROR(su_errno(), what)return ((void)(err = su_errno(), (((tport_log != ((void*)0) &&
tport_log->log_init) == 0 ? 9 : ((tport_log != ((void*)0)
&& tport_log->log_init > 1) ? tport_log->log_level
: su_log_default->log_level)) >= errlevel ? _su_llog(tport_log
, errlevel, "tport.c", (const char *)__func__, 984, "%s(%p): %s(pf=%d %s/%s): %s\n"
, __func__, (void *)pri, "what", ai->ai_family, tpn->tpn_proto
, tport_hostport(buf, sizeof(buf), (void *)ai->ai_addr, 2)
, su_strerror(err)) : (void)0), tport_zap_secondary(self), su_seterrno
(err)), (void *)((void*)0))
;
985
986 self->tp_conn_orient = 1;
987
988 if ((server_socket = pri->pri_primary->tp_socket) != INVALID_SOCKET((su_socket_t)INVALID_SOCKET)) {
989 su_sockaddr_t susa;
990 socklen_t susalen = sizeof(susa);
991
992 /* Bind this socket to same IP address as the primary server socket */
993 if (getsockname(server_socket, &susa.su_sa, &susalen) < 0) {
994 SU_DEBUG_3(("%s(%p): getsockname(): %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 995, "%s(%p): getsockname(): %s\n", __func__
, (void *)self, su_strerror(su_errno()))) : (void)0)
995 __func__, (void *)self, su_strerror(su_errno())))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 995, "%s(%p): getsockname(): %s\n", __func__
, (void *)self, su_strerror(su_errno()))) : (void)0)
;
996 }
997 else {
998 susa.su_portsu_sin.sin_port = 0;
999 if (bind(s, &susa.su_sa, susalen) < 0) {
1000 SU_DEBUG_3(("%s(%p): bind(local-ip): %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1001, "%s(%p): bind(local-ip): %s\n", __func__
, (void *)self, su_strerror(su_errno()))) : (void)0)
1001 __func__, (void *)self, su_strerror(su_errno())))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1001, "%s(%p): bind(local-ip): %s\n", __func__
, (void *)self, su_strerror(su_errno()))) : (void)0)
;
1002 }
1003 }
1004 }
1005
1006 /* Set sockname for the tport */
1007 if (tport_setname(self, tpn->tpn_proto, real_ai, tpn->tpn_canon) == -1)
1008 TPORT_CONNECT_ERROR(su_errno(), tport_setname)return ((void)(err = su_errno(), (((tport_log != ((void*)0) &&
tport_log->log_init) == 0 ? 9 : ((tport_log != ((void*)0)
&& tport_log->log_init > 1) ? tport_log->log_level
: su_log_default->log_level)) >= errlevel ? _su_llog(tport_log
, errlevel, "tport.c", (const char *)__func__, 1008, "%s(%p): %s(pf=%d %s/%s): %s\n"
, __func__, (void *)pri, "tport_setname", ai->ai_family, tpn
->tpn_proto, tport_hostport(buf, sizeof(buf), (void *)ai->
ai_addr, 2), su_strerror(err)) : (void)0), tport_zap_secondary
(self), su_seterrno(err)), (void *)((void*)0))
;
1009
1010 /* Try to have a non-blocking connect().
1011 * The tport_register_secondary() below makes the socket non-blocking anyway. */
1012 su_setblocking(s, 0);
1013
1014 if (connect(s, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == SOCKET_ERRORSOCKET_ERROR) {
1015 err = su_errno();
1016 if (!su_is_blocking(err)((err) == 115 || (err) == 11 || (err) == 11 || (err) == 4))
1017 TPORT_CONNECT_ERROR(err, connect)return ((void)(err = err, (((tport_log != ((void*)0) &&
tport_log->log_init) == 0 ? 9 : ((tport_log != ((void*)0)
&& tport_log->log_init > 1) ? tport_log->log_level
: su_log_default->log_level)) >= errlevel ? _su_llog(tport_log
, errlevel, "tport.c", (const char *)__func__, 1017, "%s(%p): %s(pf=%d %s/%s): %s\n"
, __func__, (void *)pri, "connect", ai->ai_family, tpn->
tpn_proto, tport_hostport(buf, sizeof(buf), (void *)ai->ai_addr
, 2), su_strerror(err)) : (void)0), tport_zap_secondary(self)
, su_seterrno(err)), (void *)((void*)0))
;
1018 events = SU_WAIT_CONNECT(0x004) | SU_WAIT_ERR(0x008);
1019 wakeup = tport_connected;
1020 what = "connecting";
1021 }
1022 else {
1023 what = "connected";
1024 self->tp_is_connected = 1;
1025 }
1026
1027 if (tport_register_secondary(self, wakeup, events) == -1)
1028 TPORT_CONNECT_ERROR(su_errno(), tport_register_secondary)return ((void)(err = su_errno(), (((tport_log != ((void*)0) &&
tport_log->log_init) == 0 ? 9 : ((tport_log != ((void*)0)
&& tport_log->log_init > 1) ? tport_log->log_level
: su_log_default->log_level)) >= errlevel ? _su_llog(tport_log
, errlevel, "tport.c", (const char *)__func__, 1028, "%s(%p): %s(pf=%d %s/%s): %s\n"
, __func__, (void *)pri, "tport_register_secondary", ai->ai_family
, tpn->tpn_proto, tport_hostport(buf, sizeof(buf), (void *
)ai->ai_addr, 2), su_strerror(err)) : (void)0), tport_zap_secondary
(self), su_seterrno(err)), (void *)((void*)0))
;
1029
1030 if (ai == real_ai) {
1031 SU_DEBUG_5(("%s(%p): %s to " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1032, "%s(%p): %s to " "%s/%s:%s%s%s%s%s" "\n"
, __func__, (void *)self, what, (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
1032 __func__, (void *)self, what, TPN_ARGS(self->tp_name)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1032, "%s(%p): %s to " "%s/%s:%s%s%s%s%s" "\n"
, __func__, (void *)self, what, (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
;
1033 }
1034 else {
1035 SU_DEBUG_5(("%s(%p): %s via %s to " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1038, "%s(%p): %s via %s to " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)self, what, tport_hostport(buf, sizeof
(buf), (void *)ai->ai_addr, 2), (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
1036 __func__, (void *)self, what,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1038, "%s(%p): %s via %s to " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)self, what, tport_hostport(buf, sizeof
(buf), (void *)ai->ai_addr, 2), (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
1037 tport_hostport(buf, sizeof(buf), (void *)ai->ai_addr, 2),(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1038, "%s(%p): %s via %s to " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)self, what, tport_hostport(buf, sizeof
(buf), (void *)ai->ai_addr, 2), (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
1038 TPN_ARGS(self->tp_name)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1038, "%s(%p): %s via %s to " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)self, what, tport_hostport(buf, sizeof
(buf), (void *)ai->ai_addr, 2), (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
;
1039 }
1040
1041 return self;
1042}
1043
1044/** Register a new secondary transport. @internal */
1045int tport_register_secondary(tport_t *self, su_wakeup_f wakeup, int events)
1046{
1047 int i;
1048 su_root_t *root = tport_is_secondary(self) ? self->tp_master->mr_root : NULL((void*)0);
1049 su_wait_t wait[1] = { SU_WAIT_INIT{ ((su_socket_t)INVALID_SOCKET), 0, 0 } };
1050
1051 if (root != NULL((void*)0)
1052 /* Create wait object with appropriate events. */
1053 &&
1054 su_wait_create(wait, self->tp_socket, events) != -1
1055 /* Register socket to root */
1056 &&
1057 (i = su_root_register(root, wait, wakeup, self, 0)) != -1) {
1058
1059 /* Can't be added to list of opened if already closed */
1060 if (tport_is_closed(self)) goto fail;
1061
1062 self->tp_index = i;
1063 self->tp_events = events;
1064
1065 tprb_append(&self->tp_pri->pri_open, self);
1066
1067 return 0;
1068 }
1069
1070fail:
1071 SU_DEBUG_9(("%s(%p): tport is %s!\n", __func__, (void *)self, (tport_is_closed(self) ? "closed" : "opened")))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 1071, "%s(%p): tport is %s!\n", __func__, (
void *)self, (tport_is_closed(self) ? "closed" : "opened"))) :
(void)0)
;
1072 su_wait_destroy(wait);
1073 return -1;
1074}
1075
1076/** Destroy a secondary transport. @internal */
1077void tport_zap_secondary(tport_t *self)
1078{
1079 tport_master_t *mr;
1080
1081 if (self == NULL((void*)0))
1082 return;
1083
1084 /* Remove from rbtree */
1085 if (!tport_is_closed(self))
1086 tprb_remove(&self->tp_pri->pri_open, self);
1087 else
1088 tplist_remove(&self->tp_pri->pri_closed, self);
1089
1090 if (self->tp_timer)
1091 su_timer_destroy(self->tp_timer), self->tp_timer = NULL((void*)0);
1092
1093 /* Do not deinit primary as secondary! */
1094 if (tport_is_secondary(self) &&
1095 self->tp_pri->pri_vtable->vtp_deinit_secondary)
1096 self->tp_pri->pri_vtable->vtp_deinit_secondary(self);
1097
1098 if (self->tp_msg) {
1099 msg_destroy(self->tp_msg), self->tp_msg = NULL((void*)0);
1100 SU_DEBUG_3(("%s(%p): zapped partially received message\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1101, "%s(%p): zapped partially received message\n"
, __func__, (void *)self)) : (void)0)
1101 __func__, (void *)self))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1101, "%s(%p): zapped partially received message\n"
, __func__, (void *)self)) : (void)0)
;
1102 }
1103
1104 if (tport_has_queued(self)) {
1105 size_t n = 0, i, N = self->tp_params->tpp_qsize;
1106 for (i = self->tp_qhead; self->tp_queue[i]; i = (i + 1) % N) {
1107 msg_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL((void*)0);
1108 n++;
1109 }
1110 SU_DEBUG_3(("%s(%p): zapped %lu queued messages\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1111, "%s(%p): zapped %lu queued messages\n"
, __func__, (void *)self, (LU)n)) : (void)0)
1111 __func__, (void *)self, (LU)n))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1111, "%s(%p): zapped %lu queued messages\n"
, __func__, (void *)self, (LU)n)) : (void)0)
;
1112 }
1113
1114 if (self->tp_pused) {
1115 SU_DEBUG_3(("%s(%p): zapped while pending\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1116, "%s(%p): zapped while pending\n", __func__
, (void *)self)) : (void)0)
1116 __func__, (void *)self))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1116, "%s(%p): zapped while pending\n", __func__
, (void *)self)) : (void)0)
;
1117 }
1118
1119 mr = self->tp_master;
1120
1121#if HAVE_SOFIA_STUN
1122 tport_stun_server_remove_socket(self);
1123#endif
1124
1125 if (self->tp_index)
1126 su_root_deregister(mr->mr_root, self->tp_index);
1127 self->tp_index = 0;
1128 if (self->tp_socket != INVALID_SOCKET((su_socket_t)INVALID_SOCKET))
1129 su_close(self->tp_socket);
1130 self->tp_socket = INVALID_SOCKET((su_socket_t)INVALID_SOCKET);
1131
1132 su_home_zap(self->tp_home)su_home_unref((self->tp_home));
1133}
1134
1135/** Create a new reference to a transport object. */
1136tport_t *tport_ref(tport_t *tp)
1137{
1138 if (tp) {
1139 if (tp->tp_refs >= 0)
1140 tp->tp_refs++;
1141 else if (tp->tp_refs == -1)
1142 tp->tp_refs = 1;
1143 }
1144 return tp;
1145}
1146
1147/** Destroy reference to a transport object. */
1148void tport_unref(tport_t *tp)
1149{
1150 if (tp == NULL((void*)0) || tp->tp_refs <= 0)
1151 return;
1152 if (--tp->tp_refs > 0)
1153 return;
1154
1155 if (!tport_is_secondary(tp))
1156 return;
1157
1158 if (tp->tp_params->tpp_idle == 0)
1159 tport_close(tp);
1160
1161 tport_set_secondary_timer(tp);
1162}
1163
1164/** Create a new reference to transport object. */
1165tport_t *tport_incref(tport_t *tp)
1166{
1167 return tport_ref(tp);
1168}
1169
1170/** Destroy a transport reference. */
1171void tport_decref(tport_t **ttp)
1172{
1173 assert(ttp)((void) sizeof ((ttp) ? 1 : 0), __extension__ ({ if (ttp) ; else
__assert_fail ("ttp", "tport.c", 1173, __extension__ __PRETTY_FUNCTION__
); }))
;
1174
1175 if (*ttp) {
1176 tport_unref(*ttp);
1177 *ttp = NULL((void*)0);
1178 }
1179}
1180
1181/** Get transport parameters.
1182 *
1183 * @param self pointer to a transport object
1184 * @param tag,value,... list of tags
1185 *
1186 * @TAGS
1187 * TPTAG_MTU_REF(), TPTAG_QUEUESIZE_REF(), TPTAG_IDLE_REF(),
1188 * TPTAG_TIMEOUT_REF(), TPTAG_KEEPALIVE_REF(), TPTAG_PINGPONG_REF(),
1189 * TPTAG_PONG2PING_REF(), TPTAG_DEBUG_DROP_REF(), TPTAG_THRPSIZE_REF(),
1190 * TPTAG_THRPRQSIZE_REF(), TPTAG_SIGCOMP_LIFETIME_REF(),
1191 * TPTAG_CONNECT_REF(), TPTAG_SDWN_ERROR_REF(), TPTAG_REUSE_REF(),
1192 * TPTAG_STUN_SERVER_REF(), TPTAG_PUBLIC_REF() and TPTAG_TOS_REF().
1193 */
1194int tport_get_params(tport_t const *self,
1195 tag_type_t tag, tag_value_t value, ...)
1196{
1197 ta_list ta;
1198 int n;
1199 tport_params_t const *tpp;
1200 int connect;
1201 tport_master_t *mr = self->tp_master;
1202
1203 if (self == NULL((void*)0))
1204 return su_seterrno(EINVAL22);
1205
1206 tpp = self->tp_params;
1207 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
1208
1209 connect = tpp->tpp_conn_orient
1210 /* Only dgram primary is *not* connection-oriented */
1211 || !tport_is_primary(self) || !tport_is_dgram(self);
1212
1213 n = tl_tgets(ta_args(ta)(ta).tl,
1214 TPTAG_MTU((usize_t)tpp->tpp_mtu)tptag_mtu, tag_usize_v(((usize_t)tpp->tpp_mtu)),
1215 TPTAG_REUSE(self->tp_reusable)tptag_reuse, tag_bool_v((self->tp_reusable)),
1216 TPTAG_CONNECT(connect)tptag_connect, tag_bool_v((connect)),
1217 TPTAG_QUEUESIZE(tpp->tpp_qsize)tptag_queuesize, tag_uint_v((tpp->tpp_qsize)),
1218 TPTAG_IDLE(tpp->tpp_idle)tptag_idle, tag_uint_v((tpp->tpp_idle)),
1219 TPTAG_TIMEOUT(tpp->tpp_timeout)tptag_timeout, tag_uint_v((tpp->tpp_timeout)),
1220 TPTAG_SOCKET_KEEPALIVE(tpp->tpp_socket_keepalive)tptag_socket_keepalive, tag_uint_v((tpp->tpp_socket_keepalive
))
,
1221 TPTAG_KEEPALIVE(tpp->tpp_keepalive)tptag_keepalive, tag_uint_v((tpp->tpp_keepalive)),
1222 TPTAG_PINGPONG(tpp->tpp_pingpong)tptag_pingpong, tag_uint_v((tpp->tpp_pingpong)),
1223 TPTAG_PONG2PING(tpp->tpp_pong2ping)tptag_pong2ping, tag_bool_v((tpp->tpp_pong2ping)),
1224 TPTAG_SDWN_ERROR(tpp->tpp_sdwn_error)tptag_sdwn_error, tag_bool_v((tpp->tpp_sdwn_error)),
1225 TPTAG_DEBUG_DROP(tpp->tpp_drop)tptag_debug_drop, tag_uint_v((tpp->tpp_drop)),
1226 TPTAG_THRPSIZE(tpp->tpp_thrpsize)tptag_thrpsize, tag_uint_v((tpp->tpp_thrpsize)),
1227 TPTAG_THRPRQSIZE(tpp->tpp_thrprqsize)tptag_thrprqsize, tag_uint_v((tpp->tpp_thrprqsize)),
1228 TPTAG_SIGCOMP_LIFETIME(tpp->tpp_sigcomp_lifetime)tptag_sigcomp_lifetime, tag_uint_v((tpp->tpp_sigcomp_lifetime
))
,
1229 TPTAG_STUN_SERVER(tpp->tpp_stun_server)tptag_stun_server, tag_bool_v((tpp->tpp_stun_server)),
1230 TAG_IF(self->tp_pri,!(self->tp_pri) ? tag_skip : tptag_public, tag_int_v((self
->tp_pri ? self->tp_pri->pri_public : 0))
1231 TPTAG_PUBLIC(self->tp_pri ?!(self->tp_pri) ? tag_skip : tptag_public, tag_int_v((self
->tp_pri ? self->tp_pri->pri_public : 0))
1232 self->tp_pri->pri_public : 0))!(self->tp_pri) ? tag_skip : tptag_public, tag_int_v((self
->tp_pri ? self->tp_pri->pri_public : 0))
,
1233 TPTAG_TOS(tpp->tpp_tos)tptag_tos, tag_int_v((tpp->tpp_tos)),
1234 TAG_IF((void *)self == (void *)mr,!((void *)self == (void *)mr) ? tag_skip : tptag_log, tag_bool_v
((mr->mr_log != 0))
1235 TPTAG_LOG(mr->mr_log != 0))!((void *)self == (void *)mr) ? tag_skip : tptag_log, tag_bool_v
((mr->mr_log != 0))
,
1236 TAG_IF((void *)self == (void *)mr,!((void *)self == (void *)mr) ? tag_skip : tptag_dump, tag_str_v
((mr->mr_dump))
1237 TPTAG_DUMP(mr->mr_dump))!((void *)self == (void *)mr) ? tag_skip : tptag_dump, tag_str_v
((mr->mr_dump))
,
1238 TAG_END()(tag_type_t)0, (tag_value_t)0);
1239
1240 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
1241
1242 return n;
1243}
1244
1245/** Set transport parameters.
1246 *
1247 * @param self pointer to a transport object
1248 * @param tag,value,... list of tags
1249 *
1250 * @TAGS
1251 * TPTAG_MTU(), TPTAG_QUEUESIZE(), TPTAG_IDLE(), TPTAG_TIMEOUT(),
1252 * TPTAG_KEEPALIVE(), TPTAG_PINGPONG(), TPTAG_PONG2PING(),
1253 * TPTAG_DEBUG_DROP(), TPTAG_THRPSIZE(), TPTAG_THRPRQSIZE(),
1254 * TPTAG_SIGCOMP_LIFETIME(), TPTAG_CONNECT(), TPTAG_SDWN_ERROR(),
1255 * TPTAG_REUSE(), TPTAG_STUN_SERVER(), and TPTAG_TOS().
1256 */
1257int tport_set_params(tport_t *self,
1258 tag_type_t tag, tag_value_t value, ...)
1259{
1260 ta_list ta;
1261 int n, m = 0;
1262 tport_params_t tpp[1], *tpp0;
1263
1264 usize_t mtu;
1265 int connect, sdwn_error, reusable, stun_server, pong2ping;
1266
1267 if (self == NULL((void*)0))
1268 return su_seterrno(EINVAL22);
1269
1270 memcpy(tpp, tpp0 = self->tp_params, sizeof tpp);
1271
1272 mtu = tpp->tpp_mtu;
1273 connect = tpp->tpp_conn_orient;
1274 sdwn_error = tpp->tpp_sdwn_error;
1275 reusable = self->tp_reusable;
1276 stun_server = tpp->tpp_stun_server;
1277 pong2ping = tpp->tpp_pong2ping;
1278
1279 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
1280
1281 n = tl_gets(ta_args(ta)(ta).tl,
1282 TPTAG_MTU_REF(mtu)tptag_mtu_ref, tag_usize_vr(&(mtu)),
1283 TAG_IF(!self->tp_queue, TPTAG_QUEUESIZE_REF(tpp->tpp_qsize))!(!self->tp_queue) ? tag_skip : tptag_queuesize_ref, tag_uint_vr
(&(tpp->tpp_qsize))
,
1284 TPTAG_IDLE_REF(tpp->tpp_idle)tptag_idle_ref, tag_uint_vr(&(tpp->tpp_idle)),
1285 TPTAG_TIMEOUT_REF(tpp->tpp_timeout)tptag_timeout_ref, tag_uint_vr(&(tpp->tpp_timeout)),
1286 TPTAG_SOCKET_KEEPALIVE_REF(tpp->tpp_socket_keepalive)tptag_socket_keepalive_ref, tag_uint_vr(&(tpp->tpp_socket_keepalive
))
,
1287 TPTAG_KEEPALIVE_REF(tpp->tpp_keepalive)tptag_keepalive_ref, tag_uint_vr(&(tpp->tpp_keepalive)
)
,
1288 TPTAG_PINGPONG_REF(tpp->tpp_pingpong)tptag_pingpong_ref, tag_uint_vr(&(tpp->tpp_pingpong)),
1289 TPTAG_PONG2PING_REF(pong2ping)tptag_pong2ping_ref, tag_bool_vr(&(pong2ping)),
1290 TPTAG_DEBUG_DROP_REF(tpp->tpp_drop)tptag_debug_drop_ref, tag_uint_vr(&(tpp->tpp_drop)),
1291 TPTAG_THRPSIZE_REF(tpp->tpp_thrpsize)tptag_thrpsize_ref, tag_uint_vr(&(tpp->tpp_thrpsize)),
1292 TPTAG_THRPRQSIZE_REF(tpp->tpp_thrprqsize)tptag_thrprqsize_ref, tag_uint_vr(&(tpp->tpp_thrprqsize
))
,
1293 TPTAG_SIGCOMP_LIFETIME_REF(tpp->tpp_sigcomp_lifetime)tptag_sigcomp_lifetime_ref, tag_uint_vr(&(tpp->tpp_sigcomp_lifetime
))
,
1294 TPTAG_CONNECT_REF(connect)tptag_connect_ref, tag_bool_vr(&(connect)),
1295 TPTAG_SDWN_ERROR_REF(sdwn_error)tptag_sdwn_error_ref, tag_bool_vr(&(sdwn_error)),
1296 TPTAG_REUSE_REF(reusable)tptag_reuse_ref, tag_bool_vr(&(reusable)),
1297 TPTAG_STUN_SERVER_REF(stun_server)tptag_stun_server_ref, tag_bool_vr(&(stun_server)),
1298 TPTAG_TOS_REF(tpp->tpp_tos)tptag_tos_ref, tag_int_vr(&(tpp->tpp_tos)),
1299 TAG_END()(tag_type_t)0, (tag_value_t)0);
1300
1301 if (self == (tport_t *)self->tp_master)
1302 m = tport_open_log(self->tp_master, ta_args(ta)(ta).tl);
1303
1304 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
1305
1306 if (n == 0)
1307 return m;
1308
1309 if (tpp->tpp_idle > 0 && tpp->tpp_idle < 100)
1310 tpp->tpp_idle = 100;
1311 if (tpp->tpp_timeout < 100)
1312 tpp->tpp_timeout = 100;
1313 if (tpp->tpp_drop > 1000)
1314 tpp->tpp_drop = 1000;
1315 if (tpp->tpp_thrprqsize > 0)
1316 tpp->tpp_thrprqsize = tpp0->tpp_thrprqsize;
1317 if (tpp->tpp_sigcomp_lifetime != 0 && tpp->tpp_sigcomp_lifetime < 30)
1318 tpp->tpp_sigcomp_lifetime = 30;
1319 if (tpp->tpp_qsize >= 1000)
1320 tpp->tpp_qsize = 1000;
1321
1322 if (mtu > UINT_MAX(2147483647 *2U +1U))
1323 mtu = UINT_MAX(2147483647 *2U +1U);
1324 tpp->tpp_mtu = (unsigned)mtu;
1325 /* Currently only primary UDP transport can *not* be connection oriented */
1326 tpp->tpp_conn_orient = connect;
1327 tpp->tpp_sdwn_error = sdwn_error;
1328 self->tp_reusable = reusable;
1329 tpp->tpp_stun_server = stun_server;
1330 tpp->tpp_pong2ping = pong2ping;
1331
1332 if (memcmp(tpp0, tpp, sizeof tpp) == 0)
1333 return n + m;
1334
1335 if (tport_is_secondary(self) &&
1336 self->tp_params == self->tp_pri->pri_primary->tp_params) {
1337 tpp0 = su_zalloc(self->tp_home, sizeof *tpp0); if (!tpp0) return -1;
1338 self->tp_params = tpp0;
1339 }
1340
1341 memcpy(tpp0, tpp, sizeof tpp);
1342
1343 if (tport_is_secondary(self))
1344 tport_set_secondary_timer(self);
1345
1346 return n + m;
1347}
1348
1349extern tport_vtable_t const tport_udp_vtable;
1350extern tport_vtable_t const tport_tcp_vtable;
1351extern tport_vtable_t const tport_tls_vtable;
1352extern tport_vtable_t const tport_ws_vtable;
1353extern tport_vtable_t const tport_wss_vtable;
1354extern tport_vtable_t const tport_sctp_vtable;
1355extern tport_vtable_t const tport_udp_client_vtable;
1356extern tport_vtable_t const tport_tcp_client_vtable;
1357extern tport_vtable_t const tport_sctp_client_vtable;
1358extern tport_vtable_t const tport_ws_client_vtable;
1359extern tport_vtable_t const tport_wss_client_vtable;
1360extern tport_vtable_t const tport_tls_client_vtable;
1361extern tport_vtable_t const tport_http_connect_vtable;
1362extern tport_vtable_t const tport_threadpool_vtable;
1363
1364#define TPORT_NUMBER_OF_TYPES64 64
1365
1366tport_vtable_t const *tport_vtables[TPORT_NUMBER_OF_TYPES64 + 1] =
1367{
1368#if HAVE_SOFIA_NTH1
1369 &tport_http_connect_vtable,
1370 &tport_ws_client_vtable,
1371 &tport_ws_vtable,
1372 &tport_wss_client_vtable,
1373 &tport_wss_vtable,
1374#endif
1375#if HAVE_TLS1
1376 &tport_tls_client_vtable,
1377 &tport_tls_vtable,
1378#endif
1379#if HAVE_SCTP /* SCTP is broken */
1380 &tport_sctp_client_vtable,
1381 &tport_sctp_vtable,
1382#endif
1383 &tport_tcp_client_vtable,
1384 &tport_tcp_vtable,
1385 &tport_udp_client_vtable,
1386 &tport_udp_vtable,
1387#if 0
1388 &tport_threadpool_vtable,
1389#endif
1390#if HAVE_SOFIA_STUN
1391 &tport_stun_vtable,
1392#endif
1393};
1394
1395/** Register new transport vtable */
1396int tport_register_type(tport_vtable_t const *vtp)
1397{
1398 int i;
1399
1400 for (i = TPORT_NUMBER_OF_TYPES64; i >= 0; i--) {
1401 if (tport_vtables[i] == NULL((void*)0)) {
1402 tport_vtables[i] = vtp;
1403 return 0;
1404 }
1405 }
1406
1407 su_seterrno(ENOMEM12);
1408 return -1;
1409}
1410
1411/**Get a vtable for given protocol */
1412tport_vtable_t const *tport_vtable_by_name(char const *protoname,
1413 enum tport_via public)
1414{
1415 int i;
1416
1417 for (i = TPORT_NUMBER_OF_TYPES64; i >= 0; i--) {
1418 tport_vtable_t const *vtable = tport_vtables[i];
1419
1420 if (vtable == NULL((void*)0))
1421 continue;
1422 if (vtable->vtp_public != public)
1423 continue;
1424 if (!su_casematch(protoname, vtable->vtp_name))
1425 continue;
1426
1427 assert(vtable->vtp_pri_size >= sizeof (tport_primary_t))((void) sizeof ((vtable->vtp_pri_size >= sizeof (tport_primary_t
)) ? 1 : 0), __extension__ ({ if (vtable->vtp_pri_size >=
sizeof (tport_primary_t)) ; else __assert_fail ("vtable->vtp_pri_size >= sizeof (tport_primary_t)"
, "tport.c", 1427, __extension__ __PRETTY_FUNCTION__); }))
;
1428 assert(vtable->vtp_secondary_size >= sizeof (tport_t))((void) sizeof ((vtable->vtp_secondary_size >= sizeof (
tport_t)) ? 1 : 0), __extension__ ({ if (vtable->vtp_secondary_size
>= sizeof (tport_t)) ; else __assert_fail ("vtable->vtp_secondary_size >= sizeof (tport_t)"
, "tport.c", 1428, __extension__ __PRETTY_FUNCTION__); }))
;
1429
1430 return vtable;
1431 }
1432
1433 return NULL((void*)0);
1434}
1435
1436#if 0
1437tport_set_f const *tport_set_methods[TPORT_NUMBER_OF_TYPES64 + 1] =
1438 {
1439 tport_server_bind_set,
1440 tport_client_bind_set,
1441 tport_threadpool_set,
1442#if HAVE_SOFIA_NTH1
1443 tport_http_connect_set,
1444#endif
1445#if HAVE_TLS1
1446 tport_tls_set,
1447#endif
1448 NULL((void*)0)
1449 };
1450
1451int tport_bind_set(tport_master_t *mr,
1452 tp_name_t const *tpn,
1453 char const * const transports[],
1454 tagi_t const *taglist,
1455 tport_set_t **return_set,
1456 int set_size)
1457{
1458 int i;
1459
1460 for (i = TPORT_NUMBER_OF_TYPES64; i >= 0; i--) {
1461 tport_set_f const *perhaps = tport_vtables[i];
1462 int result;
1463
1464 if (perhaps == NULL((void*)0))
1465 continue;
1466
1467 result = perhaps(mr, tpn, transports, taglist, return_set, set_size);
1468 if (result != 0)
1469 return result;
1470 }
1471
1472 return 0;
1473}
1474#endif
1475
1476/** Bind transport objects.
1477 *
1478 * @param self pointer to a transport object
1479 * @param tpn desired transport address
1480 * @param transports list of protocol names supported by stack
1481 * @param tag,value,... tagged argument list
1482 *
1483 * @TAGS
1484 * TPTAG_SERVER(), TPTAG_PUBLIC(), TPTAG_IDENT(), TPTAG_HTTP_CONNECT(),
1485 * TPTAG_CERTIFICATE(), TPTAG_TLS_VERSION(), TPTAG_TLS_VERIFY_POLICY, and
1486 * tags used with tport_set_params(), especially TPTAG_QUEUESIZE().
1487 */
1488int tport_tbind(tport_t *self,
1489 tp_name_t const *tpn,
1490 char const * const transports[],
1491 tag_type_t tag, tag_value_t value, ...)
1492{
1493 ta_list ta;
1494 int server = 1, retval, public = 0;
1495 tp_name_t mytpn[1];
1496 tport_master_t *mr;
1497 char const *http_connect = NULL((void*)0);
1498
1499 if (self == NULL((void*)0) || tport_is_secondary(self) ||
1500 tpn == NULL((void*)0) || transports == NULL((void*)0)) {
1501 su_seterrno(EINVAL22);
1502 return -1;
1503 }
1504
1505 *mytpn = *tpn;
1506
1507 if (mytpn->tpn_ident == NULL((void*)0))
1508 mytpn->tpn_ident = self->tp_identtp_name->tpn_ident;
1509
1510 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
1511
1512 tl_gets(ta_args(ta)(ta).tl,
1513 TPTAG_SERVER_REF(server)tptag_server_ref, tag_bool_vr(&(server)),
1514 TPTAG_PUBLIC_REF(public)tptag_public_ref, tag_int_vr(&(public)),
1515 TPTAG_IDENT_REF(mytpn->tpn_ident)tptag_ident_ref, tag_str_vr(&(mytpn->tpn_ident)),
1516 TPTAG_HTTP_CONNECT_REF(http_connect)tptag_http_connect_ref, tag_str_vr(&(http_connect)),
1517 TAG_END()(tag_type_t)0, (tag_value_t)0);
1518
1519 mr = self->tp_master; assert(mr)((void) sizeof ((mr) ? 1 : 0), __extension__ ({ if (mr) ; else
__assert_fail ("mr", "tport.c", 1519, __extension__ __PRETTY_FUNCTION__
); }))
;
1520
1521 if (http_connect && public == 0)
1522 public = tport_type_connect;
1523
1524 if (public && public != tport_type_stun)
1525 server = 0;
1526
1527 if (server)
1528 retval = tport_bind_server(mr, mytpn, transports, (enum tport_via)public, ta_args(ta)(ta).tl);
1529 else
1530 retval = tport_bind_client(mr, mytpn, transports, (enum tport_via)public, ta_args(ta)(ta).tl);
1531
1532 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
1533
1534 return retval;
1535}
1536
1537
1538/** Bind primary transport objects used by a client-only application.
1539 * @internal
1540 */
1541int tport_bind_client(tport_master_t *mr,
1542 tp_name_t const *tpn,
1543 char const * const transports[],
1544 enum tport_via public,
1545 tagi_t *tags)
1546{
1547 int i;
1548 tport_primary_t *pri = NULL((void*)0), **tbf;
1549 tp_name_t tpn0[1] = {{ "*", "*", "*", "*", NULL((void*)0), NULL((void*)0) }};
1550 char const *why = "unknown";
1551
1552 tport_vtable_t const *vtable;
1553
1554 if (public == tport_type_local)
1555 public = tport_type_client;
1556
1557 SU_DEBUG_5(("%s(%p) to " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1558, "%s(%p) to " "%s/%s:%s%s%s%s%s" "\n",
__func__, (void *)mr, (tpn)->tpn_proto, (tpn)->tpn_host
, (tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
1558 __func__, (void *)mr, TPN_ARGS(tpn)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1558, "%s(%p) to " "%s/%s:%s%s%s%s%s" "\n",
__func__, (void *)mr, (tpn)->tpn_proto, (tpn)->tpn_host
, (tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
;
1559
1560 memset(tpn0, 0, sizeof(tpn0));
1561
1562 for (tbf = &mr->mr_primaries; *tbf; tbf = &(*tbf)->pri_next)
1563 ;
1564
1565 for (i = 0; transports[i]; i++) {
1566 su_addrinfo_t hints[1];
1567 char const *proto = transports[i];
1568
1569 if (strcmp(proto, tpn->tpn_proto) != 0 &&
1570 strcmp(tpn->tpn_proto, tpn_any) != 0)
1571 continue;
1572
1573 vtable = tport_vtable_by_name(proto, public);
1574 if (!vtable)
1575 continue;
1576
1577 /* Resolve protocol, skip unknown transport protocols */
1578 if (getprotohints(hints, proto, AI_PASSIVE0x0001) < 0)
1579 continue;
1580
1581 tpn0->tpn_proto = proto;
1582 tpn0->tpn_comp = tpn->tpn_comp;
1583 tpn0->tpn_ident = tpn->tpn_ident;
1584
1585 hints->ai_canonname = "*";
1586
1587 if (!(pri = tport_alloc_primary(mr, vtable, tpn0, hints, tags, &why)))
1588 break;
1589
1590 pri->pri_public = tport_type_client; /* XXX */
1591 }
1592
1593 if (!pri) {
1594 SU_DEBUG_3(("tport_alloc_primary: %s failed\n", why))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1594, "tport_alloc_primary: %s failed\n", why
)) : (void)0)
;
1595 tport_zap_primary(*tbf);
1596 }
1597
1598 return pri ? 0 : -1;
1599}
1600
1601/** Bind primary transport objects used by a server application. */
1602int tport_bind_server(tport_master_t *mr,
1603 tp_name_t const *tpn,
1604 char const * const transports[],
1605 enum tport_via public,
1606 tagi_t *tags)
1607{
1608 char hostname[TPORT_HOSTPORTSIZE(55)];
1609 char const *canon = NULL((void*)0), *host, *service;
1610 int error = 0, family = 0;
1611 tport_primary_t *pri = NULL((void*)0), **tbf;
1612 su_addrinfo_t *ai, *res = NULL((void*)0);
1613 unsigned port, port0, port1, old;
1614 unsigned short step = 0;
1615
1616 bind6only_check(mr);
1617
1618 (void)hostname;
1619
1620 SU_DEBUG_5(("%s(%p) to " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1621, "%s(%p) to " "%s/%s:%s%s%s%s%s" "\n",
__func__, (void *)mr, (tpn)->tpn_proto, (tpn)->tpn_host
, (tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
1621 __func__, (void *)mr, TPN_ARGS(tpn)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 1621, "%s(%p) to " "%s/%s:%s%s%s%s%s" "\n",
__func__, (void *)mr, (tpn)->tpn_proto, (tpn)->tpn_host
, (tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
;
1622
1623 if (tpn->tpn_host == NULL((void*)0) || strcmp(tpn->tpn_host, tpn_any) == 0) {
1624 /* Use a local IP address */
1625 host = NULL((void*)0);
1626 }
1627#ifdef SU_HAVE_IN61
1628 else if (host_is_ip6_reference(tpn->tpn_host)) {
1629 /* Remove [] around IPv6 addresses. */
1630 size_t len = strlen(tpn->tpn_host);
1631 assert(len < sizeof hostname)((void) sizeof ((len < sizeof hostname) ? 1 : 0), __extension__
({ if (len < sizeof hostname) ; else __assert_fail ("len < sizeof hostname"
, "tport.c", 1631, __extension__ __PRETTY_FUNCTION__); }))
;
1632 host = memcpy(hostname, tpn->tpn_host + 1, len - 2);
1633 hostname[len - 2] = '\0';
1634 }
1635#endif
1636 else
1637 host = tpn->tpn_host;
1638
1639 if (tpn->tpn_port != NULL((void*)0) && strlen(tpn->tpn_port) > 0 &&
1640 strcmp(tpn->tpn_port, tpn_any) != 0)
1641 service = tpn->tpn_port;
1642 else
1643 service = "";
1644
1645 if (host && (strcmp(host, "0.0.0.0") == 0 || strcmp(host, "0") == 0))
1646 host = NULL((void*)0), family = AF_INET2;
1647#if SU_HAVE_IN61
1648 else if (host && strcmp(host, "::") == 0)
1649 host = NULL((void*)0), family = AF_INET610;
1650#endif
1651
1652 if (tpn->tpn_canon && strcmp(tpn->tpn_canon, tpn_any) &&
1653 (host || tpn->tpn_canon != tpn->tpn_host))
1654 canon = tpn->tpn_canon;
1655
1656 if (tport_server_addrinfo(mr, canon, family,
1657 host, service, tpn->tpn_proto,
1658 transports, &res) < 0)
1659 return -1;
1660
1661 for (tbf = &mr->mr_primaries; *tbf; tbf = &(*tbf)->pri_next)
1662 ;
1663
1664 if (!res)
1665 return -1;
1666 port = port0 = port1 = ntohs(((su_sockaddr_t *)res->ai_addr)->su_portsu_sin.sin_port);
1667 error = EPROTONOSUPPORT93;
1668
1669 /*
1670 * Loop until we can bind all the transports requested
1671 * by the transport user to the same port.
1672 */
1673 for (;;) {
1674 for (ai = res; ai; ai = ai->ai_next) {
1675 tp_name_t tpname[1];
1676 su_addrinfo_t ainfo[1];
1677 su_sockaddr_t su[1];
1678 tport_vtable_t const *vtable;
1679
1680 vtable = tport_vtable_by_name(ai->ai_canonname, public);
1681 if (!vtable)
1682 continue;
1683
1684 tport_addrinfo_copy(ainfo, su, sizeof su, ai);
1685 ainfo->ai_canonname = (char *)canon;
1686 su->su_portsu_sin.sin_port = htons(port);
1687
1688 memcpy(tpname, tpn, sizeof tpname);
1689 tpname->tpn_canon = canon;
1690 tpname->tpn_host = host;
1691
1692 SU_DEBUG_9(("%s(%p): calling tport_listen for %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 1693, "%s(%p): calling tport_listen for %s\n"
, __func__, (void *)mr, ai->ai_canonname)) : (void)0)
1693 __func__, (void *)mr, ai->ai_canonname))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 1693, "%s(%p): calling tport_listen for %s\n"
, __func__, (void *)mr, ai->ai_canonname)) : (void)0)
;
1694
1695 pri = tport_listen(mr, vtable, tpname, ainfo, tags);
1696 if (!pri) {
1697 switch (error = su_errno()) {
1698 case EADDRNOTAVAIL99: /* Not our address */
1699 case ENOPROTOOPT92: /* Protocol not supported */
1700 case ESOCKTNOSUPPORT94: /* Socket type not supported */
1701 continue;
1702 default:
1703 break;
1704 }
1705 break;
1706 }
1707
1708 if (port0 == 0 && port == 0) {
1709 port = port1 = ntohs(su->su_portsu_sin.sin_port);
1710 assert(public != tport_type_server || port != 0)((void) sizeof ((public != tport_type_server || port != 0) ? 1
: 0), __extension__ ({ if (public != tport_type_server || port
!= 0) ; else __assert_fail ("public != tport_type_server || port != 0"
, "tport.c", 1710, __extension__ __PRETTY_FUNCTION__); }))
;
1711 }
1712 }
1713
1714 if (ai == NULL((void*)0))
1715 break;
1716
1717 while (*tbf)
1718 tport_zap_primary(*tbf);
1719
1720 if (error != EADDRINUSE98 || port0 != 0 || port == 0)
1721 break;
1722
1723 while (step == 0) {
1724 /* step should be relative prime to 65536 - 1024 */
1725 /* 65536 - 1024 = 7 * 3 * 3 * 1024 */
1726 step = su_randint(1, 65535 - 1024 - 1) | 1;
1727 if (step % 3 == 0)
1728 step = (step + 2) % (65536 - 1024);
1729 if (step % 7 == 0)
1730 step = (step + 2) % (65536 - 1024);
1731 }
1732 old = port; port += step; if (port >= 65536) port -= (65536 - 1024);
1733
1734 if (port == port1) /* All ports in use! */
1735 break;
1736
1737 SU_DEBUG_3(("%s(%p): cannot bind all transports to port %u, trying %u\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1738, "%s(%p): cannot bind all transports to port %u, trying %u\n"
, __func__, (void *)mr, old, port)) : (void)0)
1738 __func__, (void *)mr, old, port))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1738, "%s(%p): cannot bind all transports to port %u, trying %u\n"
, __func__, (void *)mr, old, port)) : (void)0)
;
1739 }
1740
1741 tport_freeaddrinfo(res);
1742
1743 if (!*tbf) {
1744 su_seterrno(error);
1745 return -1;
1746 }
1747
1748 return 0;
1749}
1750
1751
1752/** Check if we can bind to IPv6 separately from IPv4 bind */
1753static
1754int bind6only_check(tport_master_t *mr)
1755{
1756 int retval = 0;
1757#if SU_HAVE_IN61
1758 su_sockaddr_t su[1], su4[1];
1759 socklen_t sulen, su4len;
1760 int s6, s4;
1761
1762 if (mr->mr_boundserver)
1763 return 0;
1764
1765 s4 = su_socket(AF_INET2, SOCK_DGRAMSOCK_DGRAM, IPPROTO_UDPIPPROTO_UDP);
1766 s6 = su_socket(AF_INET610, SOCK_DGRAMSOCK_DGRAM, IPPROTO_UDPIPPROTO_UDP);
1767
1768 memset(su, 0, sizeof *su);
1769 su->su_lensu_array[0] = sulen = (sizeof su->su_sin6);
1770 su->su_familysu_sa.sa_family = AF_INET610;
1771
1772 memset(su4, 0, sizeof *su4);
1773 su4->su_lensu_array[0] = su4len = (sizeof su->su_sin);
1774 su4->su_familysu_sa.sa_family = AF_INET2;
1775
1776 if (bind(s6, &su->su_sa, sulen) < 0)
1777 ;
1778 else if (getsockname(s6, &su->su_sa, &sulen) < 0)
1779 ;
1780 else if ((su4->su_portsu_sin.sin_port = su->su_portsu_sin.sin_port) != 0 &&
1781 bind(s4, &su4->su_sa, su4len) == 0)
1782 retval = 1;
1783
1784 su_close(s6), su_close(s4);
1785
1786 mr->mr_bindv6only = retval;
1787 mr->mr_boundserver = 1;
1788#endif
1789
1790 return retval;
1791}
1792
1793/* Number of supported transports */
1794#define TPORT_N(8) (8)
1795
1796/** Return list of addrinfo structures matching to
1797 * canon/host/service/protocol
1798 */
1799static
1800int tport_server_addrinfo(tport_master_t *mr,
1801 char const *canon,
1802 int family,
1803 char const *host,
1804 char const *service,
1805 char const *protocol,
1806 char const * const transports[],
1807 su_addrinfo_t **return_addrinfo)
1808{
1809 int i, N;
1810 su_addrinfo_t hints[TPORT_N(8) + 1];
1811
1812 *return_addrinfo = NULL((void*)0);
1813
1814 /*
1815 * Resolve all the transports requested by the protocol
1816 */
1817 for (i = 0, N = 0; transports[i] && N < TPORT_N(8); i++) {
1818 su_addrinfo_t *ai = &hints[N];
1819
1820 if (!su_casematch(protocol, transports[i]) && !su_strmatch(protocol, "*"))
1821 continue;
1822
1823 /* Resolve protocol, skip unknown transport protocols. */
1824 if (getprotohints(ai, transports[i], AI_PASSIVE0x0001) < 0)
1825 continue;
1826
1827 ai->ai_family = family;
1828 ai->ai_next = &hints[++N];
1829 }
1830
1831 if (N == 0)
1832 return su_seterrno(EPROTONOSUPPORT93);
1833 if (transports[i] /* Too many protocols */)
1834 return su_seterrno(ENOMEM12);
1835
1836 hints[N - 1].ai_next = NULL((void*)0);
1837
1838 if (host) {
1839 int error = tport_getaddrinfo(host, service, hints, return_addrinfo);
1840 if (error || !*return_addrinfo) {
1841 SU_DEBUG_3(("%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1844, "%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, (void *)mr, host ? host : "\"\"", service, protocol
, su_gai_strerror(error))) : (void)0)
1842 __func__, (void *)mr,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1844, "%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, (void *)mr, host ? host : "\"\"", service, protocol
, su_gai_strerror(error))) : (void)0)
1843 host ? host : "\"\"", service, protocol,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1844, "%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, (void *)mr, host ? host : "\"\"", service, protocol
, su_gai_strerror(error))) : (void)0)
1844 su_gai_strerror(error)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1844, "%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, (void *)mr, host ? host : "\"\"", service, protocol
, su_gai_strerror(error))) : (void)0)
;
1845 return su_seterrno(error != EAI_MEMORY-10 ? ENOENT2 : ENOMEM12);
1846 }
1847 return 0;
1848 }
1849
1850 return tport_get_local_addrinfo(mr, service, hints, return_addrinfo);
1851}
1852
1853/** Convert localinfo into addrinfo */
1854static
1855int
1856tport_get_local_addrinfo(tport_master_t *mr,
1857 char const *port,
1858 su_addrinfo_t const *hints,
1859 su_addrinfo_t **return_ai)
1860{
1861 int error, family;
1862 su_localinfo_t lihints[1] = {{ 0 }};
1863 su_localinfo_t *li, *li_result;
1864 su_addrinfo_t const *h;
1865 su_addrinfo_t *ai, **prev;
1866 su_sockaddr_t *su;
1867 unsigned long lport = 0;
1868 char *rest;
1869
1870 prev = return_ai, *prev = NULL((void*)0);
1871
1872 if (port) {
1873 lport = strtoul(port, &rest, 10);
1874 if (lport >= 65536) {
1875 su_seterrno(EINVAL22);
1876 return -1;
1877 }
1878 }
1879
1880 family = hints->ai_family;
1881
1882 for (h = hints->ai_next; h && family; h = h->ai_next)
1883 if (h->ai_family != family)
1884 family = 0;
1885
1886 lihints->li_flags = 0;
1887 lihints->li_family = family;
1888 lihints->li_scope = LI_SCOPE_GLOBAL | LI_SCOPE_SITE | LI_SCOPE_HOST;
1889
1890 error = su_getlocalinfo(lihints, &li_result);
1891 if (error) {
1892#if SU_HAVE_IN61
1893 SU_DEBUG_3(("%s(%p): su_getlocalinfo() for %s address: %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1897, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 10 ? "ip6" : family == 2 ? "ip4"
: "ip", su_gli_strerror(error))) : (void)0)
1894 __func__, (void *)mr,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1897, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 10 ? "ip6" : family == 2 ? "ip4"
: "ip", su_gli_strerror(error))) : (void)0)
1895 family == AF_INET6 ? "ip6"(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1897, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 10 ? "ip6" : family == 2 ? "ip4"
: "ip", su_gli_strerror(error))) : (void)0)
1896 : family == AF_INET ? "ip4" : "ip",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1897, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 10 ? "ip6" : family == 2 ? "ip4"
: "ip", su_gli_strerror(error))) : (void)0)
1897 su_gli_strerror(error)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1897, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 10 ? "ip6" : family == 2 ? "ip4"
: "ip", su_gli_strerror(error))) : (void)0)
;
1898#else
1899 SU_DEBUG_3(("%s(%p): su_getlocalinfo() for %s address: %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1902, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 2 ? "ip4" : "ip", su_gli_strerror
(error))) : (void)0)
1900 __func__, (void *)mr,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1902, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 2 ? "ip4" : "ip", su_gli_strerror
(error))) : (void)0)
1901 family == AF_INET ? "ip4" : "ip",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1902, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 2 ? "ip4" : "ip", su_gli_strerror
(error))) : (void)0)
1902 su_gli_strerror(error)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 1902, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 2 ? "ip4" : "ip", su_gli_strerror
(error))) : (void)0)
;
1903#endif
1904 su_seterrno(ENOENT2);
1905 return -1;
1906 }
1907
1908 for (li = li_result; li; li = li->li_next) {
1909 for (h = hints; h; h = h->ai_next) {
1910 if (h->ai_family && h->ai_family != li->li_family)
1911 continue;
1912
1913 ai = calloc(1, sizeof *ai + li->li_addrlen);
1914 if (ai == NULL((void*)0))
1915 break;
1916
1917 *prev = ai, prev = &ai->ai_next;
1918
1919 ai->ai_flags = AI_PASSIVE0x0001 | TP_AI_ANY0x80000;
1920 ai->ai_family = li->li_family;
1921 ai->ai_socktype = h->ai_socktype;
1922 ai->ai_protocol = h->ai_protocol;
1923 ai->ai_canonname = h->ai_canonname;
1924 ai->ai_addr = memcpy(ai + 1, li->li_addr,
1925 ai->ai_addrlen = li->li_addrlen);
1926 su = (void *)ai->ai_addr;
1927 su->su_portsu_sin.sin_port = htons(lport);
1928 }
1929 }
1930
1931 su_freelocalinfo(li_result);
1932
1933 if (li) {
1934 tport_freeaddrinfo(*return_ai);
1935 su_seterrno(ENOMEM12);
1936 return -1;
1937 }
1938
1939 if (*return_ai == NULL((void*)0)) {
1940 su_seterrno(ENOENT2);
1941 return -1;
1942 }
1943
1944 return 0;
1945}
1946
1947su_inlinestatic inline su_addrinfo_t *get_next_addrinfo(su_addrinfo_t **all);
1948
1949/** Translate address and service.
1950 *
1951 * This is a getaddrinfo() supporting multiple hints in a list.
1952 */
1953int tport_getaddrinfo(char const *node, char const *service,
1954 su_addrinfo_t const *hints,
1955 su_addrinfo_t **res)
1956{
1957 su_addrinfo_t const *h0;
1958 su_addrinfo_t *tbf, **prev;
1959 int error = EAI_SOCKTYPE-7;
1960 int i, N;
1961 su_addrinfo_t *all[TPORT_N(8) + 1]; /* Lists for all supported transports */
1962 su_addrinfo_t *results[TPORT_N(8) + 1];
1963 void *addr;
1964 int addrlen;
1965
1966 *res = NULL((void*)0);
1967
1968 for (N = 0, h0 = hints; h0; h0 = h0->ai_next) {
1969 su_addrinfo_t h[1];
1970
1971 *h = *h0, h->ai_next = NULL((void*)0), h->ai_canonname = NULL((void*)0);
1972
1973 error = su_getaddrinfo(node, service, h, &all[N]);
1974 results[N] = all[N];
1975 if (error == EAI_SOCKTYPE-7) {
1976 SU_DEBUG_7(("%s(): su_getaddrinfo(%s, %s) for %s: %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 1978, "%s(): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, node ? node : "\"\"", service, h0->ai_canonname
, su_gai_strerror(error))) : (void)0)
1977 __func__, node ? node : "\"\"", service,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 1978, "%s(): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, node ? node : "\"\"", service, h0->ai_canonname
, su_gai_strerror(error))) : (void)0)
1978 h0->ai_canonname, su_gai_strerror(error)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 1978, "%s(): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, node ? node : "\"\"", service, h0->ai_canonname
, su_gai_strerror(error))) : (void)0)
;
1979 continue;
1980 }
1981
1982 if (error || !all[N])
1983 break;
1984 N++;
1985 }
1986
1987 if (h0)
1988 for (i = 0; i < N; i++)
1989 su_freeaddrinfo(all[i]);
1990 if (error)
1991 return error;
1992
1993 /* Combine all the valid addrinfo structures to a single list */
1994 prev = &tbf, tbf = NULL((void*)0);
1995
1996 for (;;) {
1997 su_addrinfo_t *ai = NULL((void*)0), *ai0;
1998
1999 for (i = 0, h0 = hints; i < N; i++, h0 = h0->ai_next) {
2000 if ((ai = get_next_addrinfo(&results[i])))
2001 break;
2002 }
2003 if (i == N)
2004 break;
2005
2006 assert(ai)((void) sizeof ((ai) ? 1 : 0), __extension__ ({ if (ai) ; else
__assert_fail ("ai", "tport.c", 2006, __extension__ __PRETTY_FUNCTION__
); }))
;
2007 addr = SU_ADDR((su_sockaddr_t *)ai->ai_addr)(((su_sockaddr_t *)ai->ai_addr)->su_sa.sa_family == 2 ?
(void *)&((su_sockaddr_t *)ai->ai_addr)->su_sin.sin_addr
: (((su_sockaddr_t *)ai->ai_addr)->su_sa.sa_family == 10
? (void *)&((su_sockaddr_t *)ai->ai_addr)->su_sin6
.sin6_addr : (void *)&((su_sockaddr_t *)ai->ai_addr)->
su_sa.sa_data))
;
2008 addrlen = SU_ADDRLEN((su_sockaddr_t *)ai->ai_addr)(((su_sockaddr_t *)ai->ai_addr)->su_sa.sa_family == 2 ?
(socklen_t)sizeof(((su_sockaddr_t *)ai->ai_addr)->su_sin
.sin_addr) : (((su_sockaddr_t *)ai->ai_addr)->su_sa.sa_family
== 10 ? (socklen_t)sizeof(((su_sockaddr_t *)ai->ai_addr)->
su_sin6.sin6_addr) : (socklen_t)sizeof(((su_sockaddr_t *)ai->
ai_addr)->su_sa.sa_data)))
;
2009
2010 /* Copy all the addrinfo structures with same address to the list */
2011 for (; i < N; i++, h0 = h0->ai_next) {
2012 while ((ai0 = get_next_addrinfo(&results[i]))) {
2013 void *a = SU_ADDR((su_sockaddr_t *)ai0->ai_addr)(((su_sockaddr_t *)ai0->ai_addr)->su_sa.sa_family == 2 ?
(void *)&((su_sockaddr_t *)ai0->ai_addr)->su_sin.sin_addr
: (((su_sockaddr_t *)ai0->ai_addr)->su_sa.sa_family ==
10 ? (void *)&((su_sockaddr_t *)ai0->ai_addr)->su_sin6
.sin6_addr : (void *)&((su_sockaddr_t *)ai0->ai_addr)->
su_sa.sa_data))
;
2014
2015 if (memcmp(addr, a, addrlen)) /* Different address */
2016 break;
2017
2018 results[i] = ai0->ai_next;
2019
2020 ai = calloc(1, sizeof *ai + ai0->ai_addrlen);
2021 if (ai == NULL((void*)0))
2022 goto error;
2023 *prev = memcpy(ai, ai0, sizeof *ai); prev = &ai->ai_next; *prev = NULL((void*)0);
2024 ai->ai_addr = memcpy(ai + 1, ai0->ai_addr, ai0->ai_addrlen);
2025 ai->ai_canonname = h0->ai_canonname;
2026 }
2027 }
2028 }
2029
2030 for (i = 0; i < N; i++)
2031 su_freeaddrinfo(all[i]);
2032
2033 *res = tbf;
2034 return 0;
2035
2036 error:
2037 for (i = 0; i < N; i++)
2038 su_freeaddrinfo(all[i]);
2039 tport_freeaddrinfo(tbf);
2040 return EAI_MEMORY-10;
2041}
2042
2043su_inlinestatic inline
2044su_addrinfo_t *get_next_addrinfo(su_addrinfo_t **all)
2045{
2046 su_addrinfo_t *ai;
2047
2048 while ((ai = *all)) {
2049 if (ai->ai_family == AF_INET2)
2050 return ai;
2051#if SU_HAVE_IN61
2052 if (ai->ai_family == AF_INET610)
2053 return ai;
2054#endif
2055 *all = ai->ai_next;
2056 }
2057 return ai;
2058}
2059
2060static
2061void tport_freeaddrinfo(su_addrinfo_t *ai)
2062{
2063 su_addrinfo_t *ai_next;
2064
2065 while (ai) {
2066 ai_next = ai->ai_next;
2067 free(ai);
2068 ai = ai_next;
2069 }
2070}
2071
2072static
2073int tport_addrinfo_copy(su_addrinfo_t *dst, void *addr, socklen_t addrlen,
2074 su_addrinfo_t const *src)
2075{
2076 if (addrlen < src->ai_addrlen)
2077 return -1;
2078
2079 memcpy(dst, src, sizeof *dst);
2080
2081 if (src->ai_addrlen < addrlen)
2082 memset(addr, 0, addrlen);
2083
2084 dst->ai_addr = memcpy(addr, src->ai_addr, src->ai_addrlen);
2085 dst->ai_next = NULL((void*)0);
2086
2087 return 0;
2088}
2089
2090/** Close a transport.
2091 *
2092 * Close the socket associated with a transport object. Report an error to
2093 * all pending clients, if required. Set/reset timer, too.
2094 */
2095void tport_close(tport_t *self)
2096{
2097 SU_DEBUG_5(("%s(%p): " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 2098, "%s(%p): " "%s/%s:%s%s%s%s%s" "\n", __func__
, (void *)self, (self->tp_name)->tpn_proto, (self->tp_name
)->tpn_host, (self->tp_name)->tpn_port, (self->tp_name
)->tpn_comp ? ";comp=" : "", (self->tp_name)->tpn_comp
? (self->tp_name)->tpn_comp : "", (self->tp_name)->
tpn_ident ? "/" : "", (self->tp_name)->tpn_ident ? (self
->tp_name)->tpn_ident : "")) : (void)0)
2098 __func__, (void *)self, TPN_ARGS(self->tp_name)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 2098, "%s(%p): " "%s/%s:%s%s%s%s%s" "\n", __func__
, (void *)self, (self->tp_name)->tpn_proto, (self->tp_name
)->tpn_host, (self->tp_name)->tpn_port, (self->tp_name
)->tpn_comp ? ";comp=" : "", (self->tp_name)->tpn_comp
? (self->tp_name)->tpn_comp : "", (self->tp_name)->
tpn_ident ? "/" : "", (self->tp_name)->tpn_ident ? (self
->tp_name)->tpn_ident : "")) : (void)0)
;
2099
2100 if (self->tp_refs == -1) {
2101 self->tp_refs = 0;
2102 }
2103
2104 if (self->tp_closed || !tport_is_secondary(self))
2105 return;
2106
2107 tprb_remove(&self->tp_pri->pri_open, self);
2108 tplist_insert(&self->tp_pri->pri_closed, self);
2109
2110 self->tp_closed = 1;
2111 self->tp_send_close = 3;
2112 self->tp_recv_close = 3;
2113
2114 if (self->tp_params->tpp_sdwn_error && self->tp_pused)
2115 tport_error_report(self, -1, NULL((void*)0));
2116
2117 if (self->tp_pri->pri_vtable->vtp_shutdown)
2118 self->tp_pri->pri_vtable->vtp_shutdown(self, 2);
2119 else if (self->tp_socket != -1)
2120 shutdown(self->tp_socket, 2);
2121
2122 if (self->tp_index)
2123 su_root_deregister(self->tp_master->mr_root, self->tp_index);
2124 self->tp_index = 0;
2125#if SU_HAVE_BSDSOCK1
2126 if (self->tp_socket != -1)
2127 su_close(self->tp_socket);
2128 self->tp_socket = -1;
2129#endif
2130
2131 /* Zap the queued messages */
2132 if (self->tp_queue) {
2133 unsigned short i, N = self->tp_params->tpp_qsize;
2134 for (i = 0; i < N; i++) {
2135 if (self->tp_queue[i])
2136 msg_ref_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL((void*)0);
2137 }
2138 }
2139
2140 self->tp_index = 0;
2141 self->tp_events = 0;
2142}
2143
2144/** Shutdown a transport.
2145 *
2146 * The tport_shutdown() shuts down a full-duplex transport connection
2147 * partially or completely. If @a how is 0, the further incoming data is
2148 * shut down. If @a how is 1, further outgoing data is shut down. If @a how
2149 * is 2, both incoming and outgoing traffic is shut down.
2150 *
2151 */
2152int tport_shutdown(tport_t *self, int how)
2153{
2154 int retval;
2155 if (!tport_is_secondary(self))
2156 return -1;
2157 retval = tport_shutdown0(self, how);
2158 tport_set_secondary_timer(self);
2159 return retval;
2160}
2161
2162/** Internal shutdown function */
2163int tport_shutdown0(tport_t *self, int how)
2164{
2165 SU_DEBUG_7(("%s(%p, %d)\n", __func__, (void *)self, how))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2165, "%s(%p, %d)\n", __func__, (void *)self
, how)) : (void)0)
;
2166
2167 if (!tport_is_tcp(self) ||
2168 how < 0 || how >= 2 ||
2169 (how == 0 && self->tp_send_close) ||
2170 (how == 1 && self->tp_recv_close > 1)) {
2171 tport_close(self);
2172 return 1;
2173 }
2174
2175 if (self->tp_pri->pri_vtable->vtp_shutdown)
2176 self->tp_pri->pri_vtable->vtp_shutdown(self, how);
2177 else
2178 shutdown(self->tp_socket, how);
2179
2180 if (how == 0) {
2181 self->tp_recv_close = 2;
2182 tport_set_events(self, 0, SU_WAIT_IN(0x001));
2183 if (self->tp_params->tpp_sdwn_error && self->tp_pused)
2184 tport_error_report(self, -1, NULL((void*)0));
2185 }
2186 else if (how == 1) {
2187 self->tp_send_close = 2;
2188 tport_set_events(self, 0, SU_WAIT_OUT(0x004));
2189 if (tport_has_queued(self)) {
2190 unsigned short i, N = self->tp_params->tpp_qsize;
2191 for (i = 0; i < N; i++) {
2192 if (self->tp_queue[i]) {
2193 tport_pending_errmsg(self, self->tp_queue[i], EPIPE32);
2194 msg_ref_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL((void*)0);
2195 }
2196 }
2197 }
2198 }
2199
2200 return 0;
2201}
2202
2203static void tport_secondary_timer(su_root_magic_t *magic,
2204 su_timer_t *t,
2205 tport_t *self)
2206{
2207 su_time_t now;
2208
2209 if (tport_is_closed(self)) {
2210 if (self->tp_refs == 0)
2211 tport_zap_secondary(self);
2212 return;
2213 }
2214
2215 now = /* su_timer_expired(t); */ su_now();
2216
2217 if (self->tp_pri->pri_vtable->vtp_secondary_timer)
2218 self->tp_pri->pri_vtable->vtp_secondary_timer(self, now);
2219 else
2220 tport_base_timer(self, now);
2221}
2222
2223/** Base timer for secondary transports.
2224 *
2225 * Closes and zaps unused transports. Sets the timer again.
2226 */
2227void tport_base_timer(tport_t *self, su_time_t now)
2228{
2229 unsigned timeout = self->tp_params->tpp_idle;
2230
2231 if (timeout != UINT_MAX(2147483647 *2U +1U)) {
2232 if (self->tp_refs == 0 &&
2233 self->tp_msg == NULL((void*)0) &&
2234 !tport_has_queued(self) &&
2235 su_time_cmp(su_time_add(self->tp_rtime, timeout), now) < 0 &&
2236 su_time_cmp(su_time_add(self->tp_stime, timeout), now) < 0) {
2237 SU_DEBUG_7(("%s(%p): unused for %d ms,%s zapping\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2239, "%s(%p): unused for %d ms,%s zapping\n"
, __func__, (void *)self, timeout, tport_is_closed(self) ? ""
: " closing and")) : (void)0)
2238 __func__, (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2239, "%s(%p): unused for %d ms,%s zapping\n"
, __func__, (void *)self, timeout, tport_is_closed(self) ? ""
: " closing and")) : (void)0)
2239 timeout, tport_is_closed(self) ? "" : " closing and"))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2239, "%s(%p): unused for %d ms,%s zapping\n"
, __func__, (void *)self, timeout, tport_is_closed(self) ? ""
: " closing and")) : (void)0)
;
2240 if (!tport_is_closed(self))
2241 tport_close(self);
2242 tport_zap_secondary(self);
2243 return;
2244 }
2245 }
2246
2247 tport_set_secondary_timer(self);
2248}
2249
2250/** Set timer for a secondary transport.
2251 *
2252 * This function should be called after any network activity:
2253 * tport_base_connect(), tport_send_msg(), tport_send_queue(),
2254 * tport_recv_data(), tport_shutdown0(), tport_close(),
2255 *
2256 * @retval 0 always
2257 */
2258int tport_set_secondary_timer(tport_t *self)
2259{
2260 su_time_t const infinity = { ULONG_MAX(9223372036854775807L *2UL+1UL), 999999 };
2261 su_time_t target = infinity;
2262 char const *why = "not specified";
2263 su_timer_f timer = tport_secondary_timer;
2264
2265 if (!tport_is_secondary(self))
2266 return 0;
2267
2268 if (tport_is_closed(self)) {
2269
2270again:
2271 if (self->tp_refs == 0) {
2272 SU_DEBUG_7(("tport(%p): set timer at %u ms because %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2273, "tport(%p): set timer at %u ms because %s\n"
, (void *)self, 0, "zap")) : (void)0)
2273 (void *)self, 0, "zap"))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2273, "tport(%p): set timer at %u ms because %s\n"
, (void *)self, 0, "zap")) : (void)0)
;
2274 su_timer_set_interval(self->tp_timer, timer, self, 0);
2275 }
2276 else
2277 su_timer_reset(self->tp_timer);
2278
2279 return 0;
2280 }
2281
2282 if (self->tp_params->tpp_idle != UINT_MAX(2147483647 *2U +1U)) {
2283 if (self->tp_refs == 0 &&
2284 self->tp_msg == NULL((void*)0) && !tport_has_queued(self)) {
2285 if (su_time_cmp(self->tp_stime, self->tp_rtime) < 0) {
2286 target = su_time_add(self->tp_rtime, self->tp_params->tpp_idle);
2287 why = "idle since recv";
2288 }
2289 else {
2290 target = su_time_add(self->tp_stime, self->tp_params->tpp_idle);
2291 why = "idle since send";
2292 }
2293 }
2294 }
2295
2296 if (self->tp_pri->pri_vtable->vtp_next_secondary_timer) {
2297 if (self->tp_pri->pri_vtable->
2298 vtp_next_secondary_timer(self, &target, &why) == -1) {
2299 if (tport_is_closed(self)) {
2300 goto again;
2301 }
2302 }
2303 }
2304
2305 if (su_time_cmp(target, infinity)) {
2306 SU_DEBUG_7(("tport(%p): set timer at %ld ms because %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2307, "tport(%p): set timer at %ld ms because %s\n"
, (void *)self, su_duration(target, su_now()), why)) : (void)
0)
2307 (void *)self, su_duration(target, su_now()), why))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2307, "tport(%p): set timer at %ld ms because %s\n"
, (void *)self, su_duration(target, su_now()), why)) : (void)
0)
;
2308 su_timer_set_at(self->tp_timer, timer, self, target);
2309 }
2310 else {
2311 SU_DEBUG_9(("tport(%p): reset timer\n", (void *)self))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 2311, "tport(%p): reset timer\n", (void *)self
)) : (void)0)
;
2312 su_timer_reset(self->tp_timer);
2313 }
2314
2315 return 0;
2316}
2317
2318
2319/** Flush idle connections. */
2320int tport_flush(tport_t *tp)
2321{
2322 tport_t *tp_next;
2323 tport_primary_t *pri;
2324
2325 if (tp == NULL((void*)0))
2326 return -1;
2327
2328 pri = tp->tp_pri;
2329
2330 while (pri->pri_closed)
2331 tport_zap_secondary(pri->pri_closed);
2332
2333 /* Go through all secondary transports, zap idle ones */
2334 for (tp = tprb_first(tp->tp_pri->pri_open); tp; tp = tp_next) {
2335 tp_next = tprb_succ(tp);
2336
2337 if (tp->tp_refs != 0)
2338 continue;
2339
2340 SU_DEBUG_1(("tport_flush(%p): %szapping\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 2341, "tport_flush(%p): %szapping\n", (void
*)tp, tport_is_closed(tp) ? "" : "closing and ")) : (void)0)
2341 (void *)tp, tport_is_closed(tp) ? "" : "closing and "))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 2341, "tport_flush(%p): %szapping\n", (void
*)tp, tport_is_closed(tp) ? "" : "closing and ")) : (void)0)
;
2342
2343 tport_close(tp);
2344 tport_zap_secondary(tp);
2345 }
2346
2347 return 0;
2348}
2349
2350/**Convert sockaddr_t to a transport name.
2351 *
2352 * @retval 0 when successful
2353 * @retval -1 upon an error
2354 */
2355int tport_convert_addr(su_home_t *home,
2356 tp_name_t *tpn,
2357 char const *protoname,
2358 char const *canon,
2359 su_sockaddr_t const *su)
2360{
2361 tp_name_t name[1] = {{ NULL((void*)0) }};
2362 char const *host;
2363 char buf[TPORT_HOSTPORTSIZE(55)];
2364 char port[8];
2365 size_t canonlen = canon ? strlen(canon) : 0;
2366
2367 if (su == NULL((void*)0))
2368 host = "*";
2369 else if (!SU_SOCKADDR_INADDR_ANY(su)((su)->su_sa.sa_family == 2 ? ((su)->su_sin.sin_addr.s_addr
== ((in_addr_t) 0x00000000)) : ((su)->su_sa.sa_family == 10
? (memcmp(&(su)->su_sin6.sin6_addr, (&in6addr_any
), sizeof(*(&in6addr_any))) == 0) : 0))
)
2370 host = tport_hostport(buf, sizeof(buf), su, 0);
2371 else if (canonlen && su->su_familysu_sa.sa_family == AF_INET2 &&
2372 strspn(canon, "0123456789.") == canonlen)
2373 host = canon;
2374#if SU_HAVE_IN61
2375 else if (canonlen && su->su_familysu_sa.sa_family == AF_INET610 &&
2376 strspn(canon, "0123456789abcdefABCDEF:.") == canonlen)
2377 host = canon;
2378#endif
2379 else
2380 host = localipname(su->su_familysu_sa.sa_family, buf, sizeof(buf));
2381
2382 if (host == NULL((void*)0))
2383 return -1;
2384
2385 if (su == NULL((void*)0))
2386 strcpy(port, "*");
2387 else
2388 snprintf(port, sizeof(port), "%u", ntohs(su->su_portsu_sin.sin_port));
2389
2390 name->tpn_proto = protoname;
2391 name->tpn_host = host;
2392 name->tpn_canon = canon ? canon : host;
2393 name->tpn_port = port;
2394
2395 return tport_name_dup(home, tpn, name);
2396}
2397
2398/** Set transport object name. @internal
2399 */
2400int tport_setname(tport_t *self,
2401 char const *protoname,
2402 su_addrinfo_t const *ai,
2403 char const *canon)
2404{
2405 su_addrinfo_t *selfai = self->tp_addrinfo;
2406
2407 if (tport_convert_addr(self->tp_home, self->tp_name,
2408 protoname, canon,
2409 (su_sockaddr_t *)ai->ai_addr) < 0)
2410 return -1;
2411
2412 if (tport_is_secondary(self))
2413 self->tp_identtp_name->tpn_ident = self->tp_pri->pri_primary->tp_identtp_name->tpn_ident;
2414
2415 selfai->ai_flags = ai->ai_flags & TP_AI_MASK0xff000;
2416
2417 selfai->ai_family = ai->ai_family;
2418 selfai->ai_socktype = ai->ai_socktype;
2419 selfai->ai_protocol = ai->ai_protocol;
2420 selfai->ai_canonname = (char *)self->tp_name->tpn_canon;
2421
2422 if (ai->ai_addr) {
2423 assert(ai->ai_family)((void) sizeof ((ai->ai_family) ? 1 : 0), __extension__ ({
if (ai->ai_family) ; else __assert_fail ("ai->ai_family"
, "tport.c", 2423, __extension__ __PRETTY_FUNCTION__); }))
, assert(ai->ai_socktype)((void) sizeof ((ai->ai_socktype) ? 1 : 0), __extension__ (
{ if (ai->ai_socktype) ; else __assert_fail ("ai->ai_socktype"
, "tport.c", 2423, __extension__ __PRETTY_FUNCTION__); }))
, assert(ai->ai_protocol)((void) sizeof ((ai->ai_protocol) ? 1 : 0), __extension__ (
{ if (ai->ai_protocol) ; else __assert_fail ("ai->ai_protocol"
, "tport.c", 2423, __extension__ __PRETTY_FUNCTION__); }))
;
2424 memcpy(self->tp_addr, ai->ai_addr, selfai->ai_addrlen = ai->ai_addrlen);
2425 }
2426
2427 return 0;
2428}
2429
2430/**Resolve protocol name.
2431 *
2432 * Convert a protocol name to IP protocol number and socket type used by
2433 * su_getaddrinfo().
2434 *
2435 * @param hints hints with the protocol number and socktype [OUT]
2436 * @param proto protocol name [IN]
2437 * @param flags hint flags
2438 */
2439static
2440int getprotohints(su_addrinfo_t *hints,
2441 char const *proto,
2442 int flags)
2443{
2444 memset(hints, 0, sizeof *hints);
2445
2446 hints->ai_flags = flags;
2447 hints->ai_canonname = (char *)proto;
2448
2449#if HAVE_TLS1
2450 if (su_casematch(proto, "tls"))
2451 proto = "tcp";
2452#endif
2453
2454#if HAVE_SOFIA_NTH1
2455 if (su_casematch(proto, "ws"))
2456 proto = "tcp";
2457 if (su_casematch(proto, "wss"))
2458 proto = "tcp";
2459#endif
2460
2461#if HAVE_SCTP
2462 if (su_casematch(proto, "sctp")) {
2463 hints->ai_protocol = IPPROTO_SCTPIPPROTO_SCTP;
2464 hints->ai_socktype = SOCK_STREAMSOCK_STREAM;
2465 return 0;
2466 }
2467#endif
2468
2469 if (su_casematch(proto, "udp")) {
2470 hints->ai_protocol = IPPROTO_UDPIPPROTO_UDP;
2471 hints->ai_socktype = SOCK_DGRAMSOCK_DGRAM;
2472 return 0;
2473 }
2474
2475 if (su_casematch(proto, "tcp")) {
2476 hints->ai_protocol = IPPROTO_TCPIPPROTO_TCP;
2477 hints->ai_socktype = SOCK_STREAMSOCK_STREAM;
2478 return 0;
2479 }
2480
2481 return -1;
2482}
2483
2484/** Get local IP.
2485 *
2486 * Get primary local IP address in URI format (IPv6 address will be
2487 * []-quoted).
2488 */
2489static
2490char *localipname(int pf, char *buf, size_t bufsiz)
2491{
2492 su_localinfo_t *li = NULL((void*)0), hints[1] = {{ LI_NUMERIC | LI_CANONNAME }};
2493 size_t n;
2494 int error;
2495
2496 hints->li_family = pf;
2497
2498#if SU_HAVE_IN61
2499 if (pf == AF_INET610) {
2500 /* Link-local addresses are not usable on IPv6 */
2501 hints->li_scope = LI_SCOPE_GLOBAL | LI_SCOPE_SITE /* | LI_SCOPE_HOST */;
2502 }
2503#endif
2504
2505 if ((error = su_getlocalinfo(hints, &li))) {
2506#if SU_HAVE_IN61
2507 if (error == ELI_NOADDRESS && pf == AF_INET610) {
2508 hints->li_family = AF_INET2;
2509 error = su_getlocalinfo(hints, &li);
2510 if (error == ELI_NOADDRESS) {
2511 hints->li_family = AF_INET610; hints->li_scope |= LI_SCOPE_HOST;
2512 error = su_getlocalinfo(hints, &li);
2513 }
2514 if (error == ELI_NOADDRESS) {
2515 hints->li_family = AF_INET2;
2516 error = su_getlocalinfo(hints, &li);
2517 }
2518 }
2519#endif
2520 if (error) {
2521 SU_DEBUG_1(("tport: su_getlocalinfo: %s\n", su_gli_strerror(error)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 2521, "tport: su_getlocalinfo: %s\n", su_gli_strerror
(error))) : (void)0)
;
2522 return NULL((void*)0);
2523 }
2524 }
2525
2526 assert(li)((void) sizeof ((li) ? 1 : 0), __extension__ ({ if (li) ; else
__assert_fail ("li", "tport.c", 2526, __extension__ __PRETTY_FUNCTION__
); }))
; assert(li->li_canonname)((void) sizeof ((li->li_canonname) ? 1 : 0), __extension__
({ if (li->li_canonname) ; else __assert_fail ("li->li_canonname"
, "tport.c", 2526, __extension__ __PRETTY_FUNCTION__); }))
;
2527
2528 n = strlen(li->li_canonname);
2529
2530 if (li->li_family == AF_INET2) {
2531 if (n >= bufsiz)
2532 return NULL((void*)0);
2533
2534 memcpy(buf, li->li_canonname, n + 1);
2535 }
2536 else {
2537 if (n + 2 >= bufsiz)
2538 return NULL((void*)0);
2539
2540 memcpy(buf + 1, li->li_canonname, n);
2541 buf[0] = '['; buf[++n] = ']'; buf[++n] = '\0';
2542 }
2543
2544 su_freelocalinfo(li);
2545
2546 return buf;
2547}
2548
2549/** Process errors from transport. */
2550void tport_error_report(tport_t *self, int errcode,
2551 su_sockaddr_t const *addr)
2552{
2553 char const *errmsg;
2554
2555 if (errcode == 0)
2556 return;
2557 else if (errcode > 0)
2558 errmsg = su_strerror(errcode);
2559 else
2560 /* Should be something like ENOTCONN */
2561 errcode = 0, errmsg = "stream closed";
2562
2563 if (addr && addr->su_familysu_sa.sa_family == AF_UNSPEC0)
2564 addr = NULL((void*)0);
2565
2566 /* Mark this connection as unusable */
2567 if (errcode > 0 && tport_has_connection(self))
2568 self->tp_reusable = 0;
2569
2570 /* Report error */
2571 if (addr && tport_pending_error(self, addr, errcode))
2572 ;
2573 else if (tport_is_secondary(self) &&
2574 tport_pending_error(self, NULL((void*)0), errcode) > 0)
2575 ;
2576 else if (self->tp_master->mr_tpac->tpac_error) {
2577 char *dstname = NULL((void*)0);
2578 char hp[TPORT_HOSTPORTSIZE(55)];
2579
2580 if (addr)
2581 dstname = tport_hostport(hp, sizeof hp, addr, 1);
2582
2583 STACK_ERROR(self, errcode, dstname)(self)->tp_master->mr_tpac->tpac_error((self)->tp_master
->mr_stack, (self), (errcode), (dstname))
;
2584 }
2585 else {
2586 if (tport_is_primary(self))
2587 SU_DEBUG_3(("%s(%p): %s (with %s)\n", __func__, (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2588, "%s(%p): %s (with %s)\n", __func__, (
void *)self, errmsg, self->tp_name->tpn_proto)) : (void
)0)
2588 errmsg, self->tp_protoname))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2588, "%s(%p): %s (with %s)\n", __func__, (
void *)self, errmsg, self->tp_name->tpn_proto)) : (void
)0)
;
2589 else
2590 SU_DEBUG_3(("%s(%p): %s (with %s/%s:%s)\n", __func__, (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2591, "%s(%p): %s (with %s/%s:%s)\n", __func__
, (void *)self, errmsg, self->tp_name->tpn_proto, self->
tp_name->tpn_host, self->tp_name->tpn_port)) : (void
)0)
2591 errmsg, self->tp_protoname, self->tp_host, self->tp_port))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2591, "%s(%p): %s (with %s/%s:%s)\n", __func__
, (void *)self, errmsg, self->tp_name->tpn_proto, self->
tp_name->tpn_host, self->tp_name->tpn_port)) : (void
)0)
;
2592 }
2593
2594 /* Close connection */
2595 if (!self->tp_closed && errcode > 0 && tport_has_connection(self))
2596 tport_close(self);
2597}
2598
2599/** Accept a new connection.
2600 *
2601 * The function tport_accept() accepts a new connection and creates a
2602 * secondary transport object for the new socket.
2603 */
2604int tport_accept(tport_primary_t *pri, int events)
2605{
2606 tport_t *self;
2607 su_addrinfo_t ai[1];
2608 su_sockaddr_t su[1];
2609 socklen_t sulen = sizeof su;
2610 su_socket_t s = INVALID_SOCKET((su_socket_t)INVALID_SOCKET), l = pri->pri_primary->tp_socket;
2611 char const *reason = "accept";
2612
2613 if (events & SU_WAIT_ERR(0x008))
2614 tport_error_event(pri->pri_primary);
2615
2616 if (!(events & SU_WAIT_ACCEPT(0x001)))
2617 return 0;
2618
2619 memcpy(ai, pri->pri_primary->tp_addrinfo, sizeof ai);
2620 ai->ai_canonname = NULL((void*)0);
2621
2622 s = accept(l, &su->su_sa, &sulen);
2623
2624 if (s < 0) {
2625 tport_error_report(pri->pri_primary, su_errno(), NULL((void*)0));
2626 return 0;
2627 }
2628
2629 ai->ai_addr = &su->su_sa, ai->ai_addrlen = sulen;
2630
2631 /* Alloc a new transport object, then register socket events with it */
2632 if ((self = tport_alloc_secondary(pri, s, 1, &reason)) == NULL((void*)0)) {
2633 SU_DEBUG_3(("%s(%p): incoming secondary on "TPN_FORMAT(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2635, "%s(%p): incoming secondary on ""%s/%s:%s%s%s%s%s"
" failed. reason = %s\n", __func__, (void *)pri, (pri->pri_primary
->tp_name)->tpn_proto, (pri->pri_primary->tp_name
)->tpn_host, (pri->pri_primary->tp_name)->tpn_port
, (pri->pri_primary->tp_name)->tpn_comp ? ";comp=" :
"", (pri->pri_primary->tp_name)->tpn_comp ? (pri->
pri_primary->tp_name)->tpn_comp : "", (pri->pri_primary
->tp_name)->tpn_ident ? "/" : "", (pri->pri_primary->
tp_name)->tpn_ident ? (pri->pri_primary->tp_name)->
tpn_ident : "", reason)) : (void)0)
2634 " failed. reason = %s\n", __func__, (void *)pri,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2635, "%s(%p): incoming secondary on ""%s/%s:%s%s%s%s%s"
" failed. reason = %s\n", __func__, (void *)pri, (pri->pri_primary
->tp_name)->tpn_proto, (pri->pri_primary->tp_name
)->tpn_host, (pri->pri_primary->tp_name)->tpn_port
, (pri->pri_primary->tp_name)->tpn_comp ? ";comp=" :
"", (pri->pri_primary->tp_name)->tpn_comp ? (pri->
pri_primary->tp_name)->tpn_comp : "", (pri->pri_primary
->tp_name)->tpn_ident ? "/" : "", (pri->pri_primary->
tp_name)->tpn_ident ? (pri->pri_primary->tp_name)->
tpn_ident : "", reason)) : (void)0)
2635 TPN_ARGS(pri->pri_primary->tp_name), reason))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2635, "%s(%p): incoming secondary on ""%s/%s:%s%s%s%s%s"
" failed. reason = %s\n", __func__, (void *)pri, (pri->pri_primary
->tp_name)->tpn_proto, (pri->pri_primary->tp_name
)->tpn_host, (pri->pri_primary->tp_name)->tpn_port
, (pri->pri_primary->tp_name)->tpn_comp ? ";comp=" :
"", (pri->pri_primary->tp_name)->tpn_comp ? (pri->
pri_primary->tp_name)->tpn_comp : "", (pri->pri_primary
->tp_name)->tpn_ident ? "/" : "", (pri->pri_primary->
tp_name)->tpn_ident ? (pri->pri_primary->tp_name)->
tpn_ident : "", reason)) : (void)0)
;
2636 shutdown(s, 2);
2637 su_close(s);
2638 return 0;
2639 }
2640 else {
2641 int events = SU_WAIT_IN(0x001)|SU_WAIT_ERR(0x008)|SU_WAIT_HUP(0x010);
2642
2643 SU_CANONIZE_SOCKADDR(su)((su)->su_sa.sa_family == 10 ? su_canonize_sockaddr(su) : (
void)0)
;
2644
2645 if (/* Prevent being marked as connected if already closed */
2646 !tport_is_closed(self) &&
2647 /* Name this transport */
2648 tport_setname(self, pri->pri_protonamepri_primary->tp_name->tpn_proto, ai, NULL((void*)0)) != -1
2649 /* Register this secondary */
2650 &&
2651 tport_register_secondary(self, tport_wakeup, events) != -1) {
2652
2653 self->tp_conn_orient = 1;
2654 self->tp_is_connected = 1;
2655
2656 SU_DEBUG_5(("%s(%p): new connection from " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 2657, "%s(%p): new connection from " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)self, (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
2657 __func__, (void *)self, TPN_ARGS(self->tp_name)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 2657, "%s(%p): new connection from " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)self, (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
;
2658
2659 return 0;
2660 }
2661
2662 /* Failure: shutdown socket, */
2663 tport_close(self);
2664 tport_zap_secondary(self);
2665 self = NULL((void*)0);
2666 }
2667
2668 return 0;
2669}
2670
2671/** Allocate a new message object */
2672msg_t *tport_msg_alloc(tport_t const *self, usize_t size)
2673{
2674 if (self) {
2675 tport_master_t *mr = self->tp_master;
2676 msg_t *msg = mr->mr_tpac->tpac_alloc(mr->mr_stack, mr->mr_log,
2677 NULL((void*)0), size, self, NULL((void*)0));
2678 if (msg) {
2679 su_addrinfo_t *mai = msg_addrinfo(msg);
2680 su_addrinfo_t const *tai = self->tp_addrinfo;
2681
2682 mai->ai_family = tai->ai_family;
2683 mai->ai_protocol = tai->ai_protocol;
2684 mai->ai_socktype = tai->ai_socktype;
2685 }
2686
2687 return msg;
2688 }
2689 else {
2690 return NULL((void*)0);
2691 }
2692}
2693
2694/** Process events for socket waiting to be connected
2695 */
2696static int tport_connected(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
2697{
2698 int events = su_wait_events(w, self->tp_socket);
2699 tport_master_t *mr = self->tp_master;
2700 su_wait_t wait[1] = { SU_WAIT_INIT{ ((su_socket_t)INVALID_SOCKET), 0, 0 } };
2701 int su_wait_create_ret;
2702
2703 int error;
2704
2705 SU_DEBUG_7(("tport_connected(%p): events%s%s\n", (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2707, "tport_connected(%p): events%s%s\n", (
void *)self, events & (0x004) ? " CONNECTED" : "", events
& (0x008) ? " ERR" : "")) : (void)0)
2706 events & SU_WAIT_CONNECT ? " CONNECTED" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2707, "tport_connected(%p): events%s%s\n", (
void *)self, events & (0x004) ? " CONNECTED" : "", events
& (0x008) ? " ERR" : "")) : (void)0)
2707 events & SU_WAIT_ERR ? " ERR" : ""))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2707, "tport_connected(%p): events%s%s\n", (
void *)self, events & (0x004) ? " CONNECTED" : "", events
& (0x008) ? " ERR" : "")) : (void)0)
;
2708
2709#if HAVE_POLL1
2710 assert(w->fd == self->tp_socket)((void) sizeof ((w->fd == self->tp_socket) ? 1 : 0), __extension__
({ if (w->fd == self->tp_socket) ; else __assert_fail (
"w->fd == self->tp_socket", "tport.c", 2710, __extension__
__PRETTY_FUNCTION__); }))
;
2711#endif
2712
2713 if (events & SU_WAIT_ERR(0x008))
2714 tport_error_event(self);
2715
2716 if (!(events & SU_WAIT_CONNECT(0x004)) || self->tp_closed) {
2717 return 0;
2718 }
2719
2720 error = su_soerror(self->tp_socket);
2721 if (error) {
2722 tport_error_report(self, error, NULL((void*)0));
2723 return 0;
2724 }
2725
2726 self->tp_is_connected = 1;
2727
2728 su_root_deregister(mr->mr_root, self->tp_index);
2729 self->tp_index = -1;
2730 self->tp_events = SU_WAIT_IN(0x001) | SU_WAIT_ERR(0x008) | SU_WAIT_HUP(0x010);
2731
2732 if ((su_wait_create_ret = su_wait_create(wait, self->tp_socket, self->tp_events)) == -1 ||
2733 (self->tp_index = su_root_register(mr->mr_root,
2734 wait, tport_wakeup, self, 0))
2735 == -1) {
2736 if (su_wait_create_ret == 0) {
2737 su_wait_destroy(wait);
2738 }
2739 tport_close(self);
2740 tport_set_secondary_timer(self);
2741 return 0;
2742 }
2743
2744 if (tport_has_queued(self))
2745 tport_send_event(self);
2746 else
2747 tport_set_secondary_timer(self);
2748
2749 return 0;
2750}
2751
2752/** Process events for primary socket */
2753static int tport_wakeup_pri(su_root_magic_t *m, su_wait_t *w, tport_t *self)
2754{
2755 tport_primary_t *pri = self->tp_pri;
2756 int events = su_wait_events(w, self->tp_socket);
2757
2758#if HAVE_POLL1
2759 assert(w->fd == self->tp_socket)((void) sizeof ((w->fd == self->tp_socket) ? 1 : 0), __extension__
({ if (w->fd == self->tp_socket) ; else __assert_fail (
"w->fd == self->tp_socket", "tport.c", 2759, __extension__
__PRETTY_FUNCTION__); }))
;
2760#endif
2761
2762 SU_DEBUG_7(("%s(%p): events%s%s%s%s%s%s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
2763 "tport_wakeup_pri", (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
2764 events & SU_WAIT_IN ? " IN" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
2765 SU_WAIT_ACCEPT != SU_WAIT_IN &&(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
2766 (events & SU_WAIT_ACCEPT) ? " ACCEPT" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
2767 events & SU_WAIT_OUT ? " OUT" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
2768 events & SU_WAIT_HUP ? " HUP" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
2769 events & SU_WAIT_ERR ? " ERR" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
2770 self->tp_closed ? " (closed)" : ""))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2770, "%s(%p): events%s%s%s%s%s%s\n", "tport_wakeup_pri"
, (void *)self, events & (0x001) ? " IN" : "", (0x001) !=
(0x001) && (events & (0x001)) ? " ACCEPT" : "", events
& (0x004) ? " OUT" : "", events & (0x010) ? " HUP" :
"", events & (0x008) ? " ERR" : "", self->tp_closed ?
" (closed)" : "")) : (void)0)
;
2771
2772
2773 if (pri->pri_vtable->vtp_wakeup_pri)
2774 return pri->pri_vtable->vtp_wakeup_pri(pri, events);
2775 else
2776 return tport_base_wakeup(self, events);
2777}
2778
2779/** Process events for connected socket */
2780int tport_wakeup(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
2781{
2782 int events = su_wait_events(w, self->tp_socket);
2783 int error;
2784
2785#if HAVE_POLL1
2786 assert(w->fd == self->tp_socket)((void) sizeof ((w->fd == self->tp_socket) ? 1 : 0), __extension__
({ if (w->fd == self->tp_socket) ; else __assert_fail (
"w->fd == self->tp_socket", "tport.c", 2786, __extension__
__PRETTY_FUNCTION__); }))
;
2787#endif
2788
2789 SU_DEBUG_7(("%s(%p): events%s%s%s%s%s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2795, "%s(%p): events%s%s%s%s%s\n", "tport_wakeup"
, (void *)self, events & (0x001) ? " IN" : "", events &
(0x004) ? " OUT" : "", events & (0x010) ? " HUP" : "", events
& (0x008) ? " ERR" : "", self->tp_closed ? " (closed)"
: "")) : (void)0)
2790 "tport_wakeup", (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2795, "%s(%p): events%s%s%s%s%s\n", "tport_wakeup"
, (void *)self, events & (0x001) ? " IN" : "", events &
(0x004) ? " OUT" : "", events & (0x010) ? " HUP" : "", events
& (0x008) ? " ERR" : "", self->tp_closed ? " (closed)"
: "")) : (void)0)
2791 events & SU_WAIT_IN ? " IN" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2795, "%s(%p): events%s%s%s%s%s\n", "tport_wakeup"
, (void *)self, events & (0x001) ? " IN" : "", events &
(0x004) ? " OUT" : "", events & (0x010) ? " HUP" : "", events
& (0x008) ? " ERR" : "", self->tp_closed ? " (closed)"
: "")) : (void)0)
2792 events & SU_WAIT_OUT ? " OUT" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2795, "%s(%p): events%s%s%s%s%s\n", "tport_wakeup"
, (void *)self, events & (0x001) ? " IN" : "", events &
(0x004) ? " OUT" : "", events & (0x010) ? " HUP" : "", events
& (0x008) ? " ERR" : "", self->tp_closed ? " (closed)"
: "")) : (void)0)
2793 events & SU_WAIT_HUP ? " HUP" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2795, "%s(%p): events%s%s%s%s%s\n", "tport_wakeup"
, (void *)self, events & (0x001) ? " IN" : "", events &
(0x004) ? " OUT" : "", events & (0x010) ? " HUP" : "", events
& (0x008) ? " ERR" : "", self->tp_closed ? " (closed)"
: "")) : (void)0)
2794 events & SU_WAIT_ERR ? " ERR" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2795, "%s(%p): events%s%s%s%s%s\n", "tport_wakeup"
, (void *)self, events & (0x001) ? " IN" : "", events &
(0x004) ? " OUT" : "", events & (0x010) ? " HUP" : "", events
& (0x008) ? " ERR" : "", self->tp_closed ? " (closed)"
: "")) : (void)0)
2795 self->tp_closed ? " (closed)" : ""))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2795, "%s(%p): events%s%s%s%s%s\n", "tport_wakeup"
, (void *)self, events & (0x001) ? " IN" : "", events &
(0x004) ? " OUT" : "", events & (0x010) ? " HUP" : "", events
& (0x008) ? " ERR" : "", self->tp_closed ? " (closed)"
: "")) : (void)0)
;
2796
2797 if (self->tp_pri->pri_vtable->vtp_wakeup)
2798 error = self->tp_pri->pri_vtable->vtp_wakeup(self, events);
2799 else
2800 error = tport_base_wakeup(self, events);
2801
2802 if (tport_is_closed(self)) {
2803 SU_DEBUG_9(("%s(%p): tport is closed! Setting secondary timer!\n", "tport_wakeup", (void *)self))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 2803, "%s(%p): tport is closed! Setting secondary timer!\n"
, "tport_wakeup", (void *)self)) : (void)0)
;
2804 tport_set_secondary_timer(self);
2805 }
2806
2807 return error;
2808}
2809
2810static int tport_base_wakeup(tport_t *self, int events)
2811{
2812 int error = 0;
2813
2814 if (events & SU_WAIT_ERR(0x008))
2815 error = tport_error_event(self);
2816
2817 if ((events & SU_WAIT_OUT(0x004)) && !self->tp_closed)
2818 tport_send_event(self);
2819
2820 if ((events & SU_WAIT_IN(0x001)) && !self->tp_closed)
2821 tport_recv_event(self);
2822
2823 if ((events & SU_WAIT_HUP(0x010)) && !self->tp_closed)
2824 tport_hup_event(self);
2825
2826 if (error) {
2827 if (self->tp_closed && error == EPIPE32)
2828 return 0;
2829
2830 tport_error_report(self, error, NULL((void*)0));
2831 }
2832
2833 return 0;
2834}
2835
2836/** Stop reading from socket until tport_continue() is called. */
2837int tport_stall(tport_t *self)
2838{
2839 return tport_set_events(self, 0, SU_WAIT_IN(0x001));
2840}
2841
2842/** Continue reading from socket. */
2843int tport_continue(tport_t *self)
2844{
2845 if (self == NULL((void*)0) || self->tp_recv_close)
2846 return -1;
2847 return tport_set_events(self, SU_WAIT_IN(0x001), 0);
2848}
2849
2850/** Process "hangup" event.
2851 *
2852 */
2853void tport_hup_event(tport_t *self)
2854{
2855 SU_DEBUG_7(("%s(%p)\n", __func__, (void *)self))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2855, "%s(%p)\n", __func__, (void *)self)) :
(void)0)
;
2856
2857 if (self->tp_msg) {
2858 su_time_t now = su_now();
2859 msg_recv_commit(self->tp_msg, 0, 1);
2860 tport_parse(self, 1, now);
2861 }
2862
2863 if (!tport_is_secondary(self))
2864 return;
2865
2866 /* Shutdown completely if there are no queued messages */
2867 /* Problem reported by Arsen Chaloyan */
2868 tport_shutdown0(self, tport_has_queued(self) ? 0 : 2);
2869 tport_set_secondary_timer(self);
2870}
2871
2872/** Receive data available on the socket.
2873 *
2874 * @retval -1 error
2875 * @retval 0 end-of-stream
2876 * @retval 1 normal receive
2877 * @retval 2 incomplete recv, recv again
2878 * @retval 3 STUN keepalive, ignore
2879 */
2880su_inlinestatic inline
2881int tport_recv_data(tport_t *self)
2882{
2883 return self->tp_pri->pri_vtable->vtp_recv(self);
2884}
2885
2886/** Process "ready to receive" event.
2887 *
2888 */
2889void tport_recv_event(tport_t *self)
2890{
2891 int again;
2892
2893 SU_DEBUG_7(("%s(%p)\n", "tport_recv_event", (void *)self))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 2893, "%s(%p)\n", "tport_recv_event", (void
*)self)) : (void)0)
;
2894
2895 do {
2896 /* Receive data from socket */
2897 again = tport_recv_data(self);
2898
2899 su_time(&self->tp_rtime);
2900
2901#if HAVE_SOFIA_STUN
2902 if (again == 3) /* STUN keepalive */
2903 return;
2904#endif
2905
2906 if (again < 0) {
2907 int error = su_errno();
2908
2909 if (!su_is_blocking(error)((error) == 115 || (error) == 11 || (error) == 11 || (error) ==
4)
) {
2910 tport_error_report(self, error, NULL((void*)0));
2911 return;
2912 }
2913 else {
2914 SU_DEBUG_3(("%s: recvfrom(): %s (%d)\n", __func__,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2915, "%s: recvfrom(): %s (%d)\n", __func__
, su_strerror(11), 11)) : (void)0)
2915 su_strerror(EAGAIN), EAGAIN))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2915, "%s: recvfrom(): %s (%d)\n", __func__
, su_strerror(11), 11)) : (void)0)
;
2916 }
2917 }
2918
2919 if (again >= 0)
2920 tport_parse(self, self->tp_pre_framed ? 1 : !again, self->tp_rtime);
2921 }
2922 while (again > 1);
2923
2924 if (!tport_is_secondary(self))
2925 return;
2926
2927 if (again == 0 && !tport_is_dgram(self)) {
2928 /* End of stream */
2929 if (!self->tp_closed) {
2930 /* Don't shutdown completely if there are queued messages */
2931 tport_shutdown0(self, tport_has_queued(self) ? 0 : 2);
2932 }
2933 }
2934
2935 tport_set_secondary_timer(self);
2936}
2937
2938/*
2939 * Parse the data and feed complete messages to the stack
2940 */
2941static void tport_parse(tport_t *self, int complete, su_time_t now)
2942{
2943 msg_t *msg, *next = NULL((void*)0);
2944 int n, streaming, stall = 0;
2945
2946 for (msg = self->tp_msg; msg; msg = next) {
2947 n = msg_extract(msg); /* Parse message */
2948
2949 streaming = 0;
2950
2951 if (n == 0) {
2952 if (complete)
2953 msg_mark_as_complete(msg, MSG_FLG_ERROR), n = -1;
2954 else if (!(streaming = msg_is_streaming(msg))) {
2955 tport_sigcomp_accept_incomplete(self, msg);
2956 break;
2957 }
2958 }
2959
2960 if (msg_get_flags(msg, MSG_FLG_TOOLARGE))
2961 SU_DEBUG_3(("%s(%p): too large message from " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2962, "%s(%p): too large message from " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)self, (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
2962 __func__, (void *)self, TPN_ARGS(self->tp_name)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 2962, "%s(%p): too large message from " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)self, (self->tp_name)->tpn_proto
, (self->tp_name)->tpn_host, (self->tp_name)->tpn_port
, (self->tp_name)->tpn_comp ? ";comp=" : "", (self->
tp_name)->tpn_comp ? (self->tp_name)->tpn_comp : "",
(self->tp_name)->tpn_ident ? "/" : "", (self->tp_name
)->tpn_ident ? (self->tp_name)->tpn_ident : "")) : (
void)0)
;
2963
2964 /* Do not try to read anymore from this connection? */
2965 if (tport_is_stream(self) &&
2966 msg_get_flags(msg, MSG_FLG_TOOLARGE | MSG_FLG_ERROR))
2967 self->tp_recv_close = stall = 1;
2968
2969 if (n == -1)
2970 next = NULL((void*)0);
2971 else if (streaming)
2972 msg_ref_create(msg); /* Keep a reference */
2973 else if (tport_is_stream(self))
2974 next = msg_next(msg);
2975 else
2976 next = NULL((void*)0);
2977
2978 tport_deliver(self, msg, next, self->tp_comp, now);
2979
2980 if (streaming && next == NULL((void*)0))
2981 break;
2982 }
2983
2984 if (stall)
2985 tport_stall(self);
2986
2987 if (self->tp_rlogged != msg)
2988 self->tp_rlogged = NULL((void*)0);
2989
2990 self->tp_msg = msg;
2991}
2992
2993/** Deliver message to the protocol stack */
2994void tport_deliver(tport_t *self,
2995 msg_t *msg,
2996 msg_t *next,
2997 tport_compressor_t *sc,
2998 su_time_t now)
2999{
3000 tport_t *ref;
3001 int error;
3002 struct tport_delivery *d;
3003 char ipaddr[SU_ADDRSIZE(48) + 2];
3004
3005 assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport.c", 3005, __extension__ __PRETTY_FUNCTION__
); }))
;
3006
3007 d = self->tp_master->mr_delivery;
3008
3009 d->d_tport = self;
3010 d->d_msg = msg;
3011 *d->d_from = *self->tp_name;
3012
3013 if (tport_is_primary(self)) {
3014 su_sockaddr_t const *su = msg_addr(msg);
3015
3016#if SU_HAVE_IN61
3017 if (su->su_familysu_sa.sa_family == AF_INET610) {
3018 ipaddr[0] = '[';
3019 su_inet_ntopinet_ntop(su->su_familysu_sa.sa_family, SU_ADDR(su)((su)->su_sa.sa_family == 2 ? (void *)&(su)->su_sin
.sin_addr : ((su)->su_sa.sa_family == 10 ? (void *)&(su
)->su_sin6.sin6_addr : (void *)&(su)->su_sa.sa_data
))
, ipaddr + 1, SU_ADDRSIZE(48));
3020 strcat(ipaddr, "]");
3021 }
3022 else {
3023 su_inet_ntopinet_ntop(su->su_familysu_sa.sa_family, SU_ADDR(su)((su)->su_sa.sa_family == 2 ? (void *)&(su)->su_sin
.sin_addr : ((su)->su_sa.sa_family == 10 ? (void *)&(su
)->su_sin6.sin6_addr : (void *)&(su)->su_sa.sa_data
))
, ipaddr, sizeof(ipaddr));
3024 }
3025#else
3026 su_inet_ntopinet_ntop(su->su_familysu_sa.sa_family, SU_ADDR(su)((su)->su_sa.sa_family == 2 ? (void *)&(su)->su_sin
.sin_addr : ((su)->su_sa.sa_family == 10 ? (void *)&(su
)->su_sin6.sin6_addr : (void *)&(su)->su_sa.sa_data
))
, ipaddr, sizeof(ipaddr));
3027#endif
3028
3029 d->d_from->tpn_canon = ipaddr;
3030 d->d_from->tpn_host = ipaddr;
3031 }
3032
3033 d->d_comp = sc;
3034 if (!sc)
3035 d->d_from->tpn_comp = NULL((void*)0);
3036
3037 error = msg_has_error(msg);
3038
3039 if (error && !*msg_chain_head(msg)) {
3040 /* This is badly damaged packet */
3041 }
3042 else if (self->tp_master->mr_log && msg != self->tp_rlogged) {
3043 char const *via = "recv";
3044 tport_log_msg(self, msg, via, "from", now);
3045 self->tp_rlogged = msg;
3046 }
3047
3048 SU_DEBUG_7(("%s(%p): %smsg %p ("MOD_ZU" bytes)"(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3052, "%s(%p): %smsg %p (""%zu"" bytes)" " from "
"%s/%s:%s%s%s%s%s" " next=%p\n", __func__, (void *)self, error
? "bad " : "", (void *)msg, (size_t)msg_size(msg), (d->d_from
)->tpn_proto, (d->d_from)->tpn_host, (d->d_from)->
tpn_port, (d->d_from)->tpn_comp ? ";comp=" : "", (d->
d_from)->tpn_comp ? (d->d_from)->tpn_comp : "", (d->
d_from)->tpn_ident ? "/" : "", (d->d_from)->tpn_ident
? (d->d_from)->tpn_ident : "", (void *)next)) : (void)
0)
3049 " from " TPN_FORMAT " next=%p\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3052, "%s(%p): %smsg %p (""%zu"" bytes)" " from "
"%s/%s:%s%s%s%s%s" " next=%p\n", __func__, (void *)self, error
? "bad " : "", (void *)msg, (size_t)msg_size(msg), (d->d_from
)->tpn_proto, (d->d_from)->tpn_host, (d->d_from)->
tpn_port, (d->d_from)->tpn_comp ? ";comp=" : "", (d->
d_from)->tpn_comp ? (d->d_from)->tpn_comp : "", (d->
d_from)->tpn_ident ? "/" : "", (d->d_from)->tpn_ident
? (d->d_from)->tpn_ident : "", (void *)next)) : (void)
0)
3050 __func__, (void *)self, error ? "bad " : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3052, "%s(%p): %smsg %p (""%zu"" bytes)" " from "
"%s/%s:%s%s%s%s%s" " next=%p\n", __func__, (void *)self, error
? "bad " : "", (void *)msg, (size_t)msg_size(msg), (d->d_from
)->tpn_proto, (d->d_from)->tpn_host, (d->d_from)->
tpn_port, (d->d_from)->tpn_comp ? ";comp=" : "", (d->
d_from)->tpn_comp ? (d->d_from)->tpn_comp : "", (d->
d_from)->tpn_ident ? "/" : "", (d->d_from)->tpn_ident
? (d->d_from)->tpn_ident : "", (void *)next)) : (void)
0)
3051 (void *)msg, (size_t)msg_size(msg),(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3052, "%s(%p): %smsg %p (""%zu"" bytes)" " from "
"%s/%s:%s%s%s%s%s" " next=%p\n", __func__, (void *)self, error
? "bad " : "", (void *)msg, (size_t)msg_size(msg), (d->d_from
)->tpn_proto, (d->d_from)->tpn_host, (d->d_from)->
tpn_port, (d->d_from)->tpn_comp ? ";comp=" : "", (d->
d_from)->tpn_comp ? (d->d_from)->tpn_comp : "", (d->
d_from)->tpn_ident ? "/" : "", (d->d_from)->tpn_ident
? (d->d_from)->tpn_ident : "", (void *)next)) : (void)
0)
3052 TPN_ARGS(d->d_from), (void *)next))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3052, "%s(%p): %smsg %p (""%zu"" bytes)" " from "
"%s/%s:%s%s%s%s%s" " next=%p\n", __func__, (void *)self, error
? "bad " : "", (void *)msg, (size_t)msg_size(msg), (d->d_from
)->tpn_proto, (d->d_from)->tpn_host, (d->d_from)->
tpn_port, (d->d_from)->tpn_comp ? ";comp=" : "", (d->
d_from)->tpn_comp ? (d->d_from)->tpn_comp : "", (d->
d_from)->tpn_ident ? "/" : "", (d->d_from)->tpn_ident
? (d->d_from)->tpn_ident : "", (void *)next)) : (void)
0)
;
3053
3054 ref = tport_incref(self);
3055
3056 if (self->tp_pri->pri_vtable->vtp_deliver) {
3057 self->tp_pri->pri_vtable->vtp_deliver(self, msg, now);
3058 }
3059 else
3060 tport_base_deliver(self, msg, now);
3061
3062 memset(d->d_from, 0, sizeof d->d_from);
3063 d->d_msg = NULL((void*)0);
3064
3065 tport_decref(&ref);
3066}
3067
3068/** Pass message to the protocol stack */
3069void
3070tport_base_deliver(tport_t *self, msg_t *msg, su_time_t now)
3071{
3072 STACK_RECV(self, msg, now)(self)->tp_master->mr_tpac->tpac_recv((self)->tp_master
->mr_stack, (self), (msg), (self)->tp_magic, (now))
;
3073}
3074
3075/** Return source transport object for delivered message */
3076tport_t *tport_delivered_by(tport_t const *tp, msg_t const *msg)
3077{
3078 if (tp && msg && msg == tp->tp_master->mr_delivery->d_msg)
3079 return tp->tp_master->mr_delivery->d_tport;
3080 else
3081 return NULL((void*)0);
3082}
3083
3084
3085/** Return source transport name for delivered message */
3086int tport_delivered_from(tport_t *tp, msg_t const *msg, tp_name_t name[1])
3087{
3088 if (name == NULL((void*)0))
3089 return -1;
3090
3091 if (tp == NULL((void*)0) || msg == NULL((void*)0) || msg != tp->tp_master->mr_delivery->d_msg) {
3092 memset(name, 0, sizeof *name);
3093 return -1;
3094 }
3095 else {
3096 *name = *tp->tp_master->mr_delivery->d_from;
3097 return 0;
3098 }
3099}
3100
3101/** Return TLS Subjects provided by the source transport */
3102su_strlst_t const *tport_delivered_from_subjects(tport_t *tp, msg_t const *msg)
3103{
3104 if (tp && msg && msg == tp->tp_master->mr_delivery->d_msg) {
3105 tport_t *tp_sec = tp->tp_master->mr_delivery->d_tport;
3106 return (tp_sec) ? tp_sec->tp_subjects : NULL((void*)0);
3107 }
3108 else
3109 return NULL((void*)0);
3110}
3111
3112/** Return UDVM used to decompress the message. */
3113int
3114tport_delivered_with_comp(tport_t *tp, msg_t const *msg,
3115 tport_compressor_t **return_compressor)
3116{
3117 if (tp == NULL((void*)0) || msg == NULL((void*)0) || msg != tp->tp_master->mr_delivery->d_msg)
3118 return -1;
3119
3120 if (return_compressor)
3121 *return_compressor = tp->tp_master->mr_delivery->d_comp;
3122
3123 return 0;
3124}
3125
3126/** Search for subject in list of TLS Certificate subjects */
3127int
3128tport_subject_search(char const *subject, su_strlst_t const *lst)
3129{
3130 usize_t idx, ilen;
3131 const char *subjuri;
3132
3133 if (!subject || su_strmatch(tpn_any, subject))
3134 return 1;
3135
3136 if (!lst)
3137 return 0;
3138
3139 /* Check if subject is a URI */
3140 if (su_casenmatch(subject,"sip:",4) || su_casenmatch(subject,"sips:",5))
3141 subjuri = subject + su_strncspn(subject,5,":") + 1;
3142 else
3143 subjuri = NULL((void*)0);
3144
3145 ilen = su_strlst_len(lst);
3146
3147 for (idx = 0; idx < ilen; idx++) {
3148 const char *lsturi, *lststr;
3149
3150 lststr = su_strlst_item(lst, idx);
3151
3152 /* check if lststr is a URI (sips URI is an unacceptable cert subject) */
3153 if (su_casenmatch(lststr,"sip:",4))
3154 lsturi = lststr + su_strncspn(lststr,4,":") + 1;
3155 else
3156 lsturi = NULL((void*)0);
3157
3158
3159 /* Match two SIP Server Identities */
3160 if (host_cmp(subjuri ? subjuri : subject, lsturi ? lsturi : lststr) == 0)
3161 return 1;
3162#if 0
3163 /* XXX - IETF drafts forbid wildcard certs */
3164 if (!subjuri && !lsturi && su_strnmatch("*.", lststr, 2)) {
3165 size_t urioffset = su_strncspn(subject, 64, ".");
3166 if (urioffset) {
3167 if (su_casematch(subject + urioffset, lststr+1))
3168 return 1;
3169 }
3170 }
3171#endif
3172 }
3173
3174 return 0;
3175}
3176
3177/** Allocate message for N bytes,
3178 * return message buffer as a iovec
3179 */
3180ssize_t tport_recv_iovec(tport_t const *self,
3181 msg_t **in_out_msg,
3182 msg_iovec_t iovec[msg_n_fragments],
3183 size_t N,
3184 int exact)
3185{
3186 msg_t *msg = *in_out_msg;
3187 ssize_t i, veclen;
3188 int fresh;
3189
3190 if (N == 0)
3191 return 0;
3192
3193 fresh = !msg;
3194
3195 /*
3196 * Allocate a new message if needed
3197 */
3198 if (!msg) {
3199 if (!(*in_out_msg = msg = tport_msg_alloc(self, N))) {
3200 SU_DEBUG_7(("%s(%p): cannot allocate msg for "MOD_ZU" bytes "(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3203, "%s(%p): cannot allocate msg for ""%zu"
" bytes " "from (%s/%s:%s)\n", __func__, (void *)self, N, self
->tp_name->tpn_proto, self->tp_name->tpn_host, self
->tp_name->tpn_port)) : (void)0)
3201 "from (%s/%s:%s)\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3203, "%s(%p): cannot allocate msg for ""%zu"
" bytes " "from (%s/%s:%s)\n", __func__, (void *)self, N, self
->tp_name->tpn_proto, self->tp_name->tpn_host, self
->tp_name->tpn_port)) : (void)0)
3202 __func__, (void *)self, N,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3203, "%s(%p): cannot allocate msg for ""%zu"
" bytes " "from (%s/%s:%s)\n", __func__, (void *)self, N, self
->tp_name->tpn_proto, self->tp_name->tpn_host, self
->tp_name->tpn_port)) : (void)0)
3203 self->tp_protoname, self->tp_host, self->tp_port))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3203, "%s(%p): cannot allocate msg for ""%zu"
" bytes " "from (%s/%s:%s)\n", __func__, (void *)self, N, self
->tp_name->tpn_proto, self->tp_name->tpn_host, self
->tp_name->tpn_port)) : (void)0)
;
3204 return -1;
3205 }
3206 }
3207
3208 /*
3209 * Get enough buffer space for the incoming data
3210 */
3211 veclen = msg_recv_iovec(msg, iovec, msg_n_fragments, N, exact);
3212 if (veclen < 0) {
3213 int err = su_errno();
3214 if (fresh && err == ENOBUFS105 && msg_get_flags(msg, MSG_FLG_TOOLARGE))
3215 veclen = msg_recv_iovec(msg, iovec, msg_n_fragments, 4096, 1);
3216 }
3217 if (veclen < 0) {
3218 int err = su_errno();
3219 SU_DEBUG_7(("%s(%p): cannot get msg %p buffer for "MOD_ZU" bytes "(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3223, "%s(%p): cannot get msg %p buffer for "
"%zu"" bytes " "from (%s/%s:%s): %s\n", __func__, (void *)self
, (void *)msg, N, self->tp_name->tpn_proto, self->tp_name
->tpn_host, self->tp_name->tpn_port, su_strerror(err
))) : (void)0)
3220 "from (%s/%s:%s): %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3223, "%s(%p): cannot get msg %p buffer for "
"%zu"" bytes " "from (%s/%s:%s): %s\n", __func__, (void *)self
, (void *)msg, N, self->tp_name->tpn_proto, self->tp_name
->tpn_host, self->tp_name->tpn_port, su_strerror(err
))) : (void)0)
3221 __func__, (void *)self, (void *)msg, N,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3223, "%s(%p): cannot get msg %p buffer for "
"%zu"" bytes " "from (%s/%s:%s): %s\n", __func__, (void *)self
, (void *)msg, N, self->tp_name->tpn_proto, self->tp_name
->tpn_host, self->tp_name->tpn_port, su_strerror(err
))) : (void)0)
3222 self->tp_protoname, self->tp_host, self->tp_port,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3223, "%s(%p): cannot get msg %p buffer for "
"%zu"" bytes " "from (%s/%s:%s): %s\n", __func__, (void *)self
, (void *)msg, N, self->tp_name->tpn_proto, self->tp_name
->tpn_host, self->tp_name->tpn_port, su_strerror(err
))) : (void)0)
3223 su_strerror(err)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3223, "%s(%p): cannot get msg %p buffer for "
"%zu"" bytes " "from (%s/%s:%s): %s\n", __func__, (void *)self
, (void *)msg, N, self->tp_name->tpn_proto, self->tp_name
->tpn_host, self->tp_name->tpn_port, su_strerror(err
))) : (void)0)
;
3224 su_seterrno(err);
3225 return veclen;
3226 }
3227
3228 assert(veclen <= msg_n_fragments)((void) sizeof ((veclen <= msg_n_fragments) ? 1 : 0), __extension__
({ if (veclen <= msg_n_fragments) ; else __assert_fail ("veclen <= msg_n_fragments"
, "tport.c", 3228, __extension__ __PRETTY_FUNCTION__); }))
;
3229
3230 SU_DEBUG_7(("%s(%p) msg %p from (%s/%s:%s) has "MOD_ZU" bytes, "(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3234, "%s(%p) msg %p from (%s/%s:%s) has ""%zu"
" bytes, " "veclen = ""%zd""\n", __func__, (void *)self, (void
*)msg, self->tp_name->tpn_proto, self->tp_name->
tpn_host, self->tp_name->tpn_port, N, veclen)) : (void)
0)
3231 "veclen = "MOD_ZD"\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3234, "%s(%p) msg %p from (%s/%s:%s) has ""%zu"
" bytes, " "veclen = ""%zd""\n", __func__, (void *)self, (void
*)msg, self->tp_name->tpn_proto, self->tp_name->
tpn_host, self->tp_name->tpn_port, N, veclen)) : (void)
0)
3232 __func__, (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3234, "%s(%p) msg %p from (%s/%s:%s) has ""%zu"
" bytes, " "veclen = ""%zd""\n", __func__, (void *)self, (void
*)msg, self->tp_name->tpn_proto, self->tp_name->
tpn_host, self->tp_name->tpn_port, N, veclen)) : (void)
0)
3233 (void *)msg, self->tp_protoname, self->tp_host, self->tp_port,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3234, "%s(%p) msg %p from (%s/%s:%s) has ""%zu"
" bytes, " "veclen = ""%zd""\n", __func__, (void *)self, (void
*)msg, self->tp_name->tpn_proto, self->tp_name->
tpn_host, self->tp_name->tpn_port, N, veclen)) : (void)
0)
3234 N, veclen))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3234, "%s(%p) msg %p from (%s/%s:%s) has ""%zu"
" bytes, " "veclen = ""%zd""\n", __func__, (void *)self, (void
*)msg, self->tp_name->tpn_proto, self->tp_name->
tpn_host, self->tp_name->tpn_port, N, veclen)) : (void)
0)
;
3235
3236 for (i = 0; veclen > 1 && i < veclen; i++) {
3237 SU_DEBUG_7(("\tiovec[%lu] = %lu bytes\n", (LU)i, (LU)iovec[i].mv_len))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3237, "\tiovec[%lu] = %lu bytes\n", (LU)i, (
LU)iovec[i].siv_len)) : (void)0)
;
3238 }
3239
3240 return veclen;
3241}
3242
3243int tport_recv_error_report(tport_t *self)
3244{
3245 if (su_is_blocking(su_errno())((su_errno()) == 115 || (su_errno()) == 11 || (su_errno()) ==
11 || (su_errno()) == 4)
)
3246 return 1;
3247
3248 /* Report error */
3249 tport_error_report(self, su_errno(), NULL((void*)0));
3250
3251 return -1;
3252}
3253
3254/** Send a message.
3255 *
3256 * The function tport_tsend() sends a message using the transport @a self.
3257 *
3258 * @TAGS
3259 * TPTAG_MTU(), TPTAG_REUSE(), TPTAG_CLOSE_AFTER(), TPTAG_SDWN_AFTER(),
3260 * TPTAG_FRESH(), TPTAG_COMPARTMENT(), TPTAG_X509_SUBJECT()
3261 */
3262tport_t *tport_tsend(tport_t *self,
3263 msg_t *msg,
3264 tp_name_t const *_tpn,
3265 tag_type_t tag, tag_value_t value, ...)
3266{
3267 ta_list ta;
3268 tagi_t const *t;
3269 int reuse, sdwn_after, close_after, resolved = 0, fresh;
3270 unsigned mtu;
3271 su_addrinfo_t *ai;
3272 tport_primary_t *primary;
3273 tp_name_t tpn[1];
3274 struct sigcomp_compartment *cc;
3275
3276 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport.c", 3276, __extension__ __PRETTY_FUNCTION__
); }))
;
3277
3278 if (!self || !msg || !_tpn) {
3279 msg_set_errno(msg, EINVAL22);
3280 return NULL((void*)0);
3281 }
3282
3283 *tpn = *_tpn;
3284
3285 SU_DEBUG_7(("tport_tsend(%p) tpn = " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3286, "tport_tsend(%p) tpn = " "%s/%s:%s%s%s%s%s"
"\n", (void *)self, (tpn)->tpn_proto, (tpn)->tpn_host,
(tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
3286 (void *)self, TPN_ARGS(tpn)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3286, "tport_tsend(%p) tpn = " "%s/%s:%s%s%s%s%s"
"\n", (void *)self, (tpn)->tpn_proto, (tpn)->tpn_host,
(tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
;
3287
3288 if (tport_is_master(self)) {
3289 primary = (tport_primary_t *)tport_primary_by_name(self, tpn);
3290 if (!primary) {
3291 msg_set_errno(msg, EPROTONOSUPPORT93);
3292 return NULL((void*)0);
3293 }
3294 }
3295 else {
3296 primary = self->tp_pri;
3297 }
3298
3299 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
3300
3301 reuse = primary->pri_primary->tp_reusable && self->tp_reusable;
3302 fresh = 0;
3303 sdwn_after = 0;
3304 close_after = 0;
3305 mtu = 0;
3306 cc = NULL((void*)0);
3307
3308 /* tl_gets() is a bit too slow here... */
3309 for (t = ta_args(ta)(ta).tl; t; t = tl_next(t)) {
3310 tag_type_t tt = t->t_tag;
3311
3312 if (tptag_reuse == tt)
3313 reuse = t->t_value != 0;
3314 else if (tptag_mtu == tt)
3315 mtu = t->t_value;
3316 else if (tptag_sdwn_after == tt)
3317 sdwn_after = t->t_value != 0;
3318 else if (tptag_close_after == tt)
3319 close_after = t->t_value != 0;
3320 else if (tptag_fresh == tt)
3321 fresh = t->t_value != 0;
3322 else if (tptag_compartment == tt)
3323 cc = (struct sigcomp_compartment *)t->t_value;
3324 }
3325
3326 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
3327
3328 fresh = fresh || !reuse;
3329
3330 ai = msg_addrinfo(msg);
3331
3332 ai->ai_flags = 0;
3333
3334 tpn->tpn_comp = tport_canonize_comp(tpn->tpn_comp);
3335 if (tpn->tpn_comp) {
3336 ai->ai_flags |= TP_AI_COMPRESSED0x01000;
3337 SU_DEBUG_9(("%s: compressed msg(%p) with %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 3338, "%s: compressed msg(%p) with %s\n", __func__
, (void *)msg, tpn->tpn_comp)) : (void)0)
3338 __func__, (void *)msg, tpn->tpn_comp))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 3338, "%s: compressed msg(%p) with %s\n", __func__
, (void *)msg, tpn->tpn_comp)) : (void)0)
;
3339 }
3340
3341 if (!tpn->tpn_comp || cc == NONE((void *)-1))
3342 cc = NULL((void*)0);
3343
3344 if (sdwn_after)
3345 ai->ai_flags |= TP_AI_SHUTDOWN0x04000;
3346 if (close_after)
3347 ai->ai_flags |= TP_AI_CLOSE0x08000;
3348
3349 if (fresh) {
3350 /* Select a primary protocol, make a fresh connection */
3351 self = primary->pri_primary;
3352 }
3353 else if (tport_is_secondary(self) && tport_is_clear_to_send(self)) {
3354 /* self = self; */
3355 ;
3356 }
3357 /*
3358 * Try to find an already open connection to the destination,
3359 * or get a primary protocol
3360 */
3361 else {
3362 /* If primary, resolve the destination address, store it in the msg */
3363 if (tport_resolve(primary->pri_primary, msg, tpn) < 0) {
3364 return NULL((void*)0);
3365 }
3366 resolved = 1;
3367
3368 self = tport_by_addrinfo(primary, msg_addrinfo(msg), tpn);
3369
3370 if (!self)
3371 self = primary->pri_primary;
3372 }
3373
3374 if (tport_is_primary(self)) {
3375 /* If primary, resolve the destination address, store it in the msg */
3376 if (!resolved && tport_resolve(self, msg, tpn) < 0) {
3377 return NULL((void*)0);
3378 }
3379
3380 if (tport_is_connection_oriented(self)
3381 || self->tp_params->tpp_conn_orient) {
3382#if 0 && HAVE_UPNP0 /* We do not want to use UPnP with secondary transports! */
3383 if (upnp_register_upnp_client(1) != 0) {
3384 upnp_check_for_nat();
3385 }
3386#endif
3387
3388 tpn->tpn_proto = self->tp_protonametp_name->tpn_proto;
3389
3390 if (!cc)
3391 tpn->tpn_comp = NULL((void*)0);
3392
3393 /* Create a secondary transport which is connected to the destination */
3394 self = tport_connect(primary, msg_addrinfo(msg), tpn);
3395
3396#if 0 && HAVE_UPNP0 /* We do not want to use UPnP with secondary transports! */
3397 upnp_deregister_upnp_client(0, 0);
3398#endif
3399
3400 if (!self) {
3401 msg_set_errno(msg, su_errno());
3402 SU_DEBUG_9(("tport_socket failed in tsend\n" VA_NONE))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 3402, "tport_socket failed in tsend\n" "%s"
, "")) : (void)0)
;
3403 return NULL((void*)0);
3404 }
3405
3406 if (cc)
3407 tport_sigcomp_assign(self, cc);
3408 }
3409 }
3410 else if (tport_is_secondary(self)) {
3411 cc = tport_sigcomp_assign_if_needed(self, cc);
3412 }
3413
3414 if (cc == NULL((void*)0))
3415 tpn->tpn_comp = NULL((void*)0);
3416
3417 if (tport_is_secondary(self)) {
3418 /* Set the peer address to msg */
3419 tport_peer_address(self, msg);
3420 if (sdwn_after || close_after)
3421 self->tp_reusable = 0;
3422 }
3423
3424 if (self->tp_pri->pri_vtable->vtp_prepare
3425 ? self->tp_pri->pri_vtable->vtp_prepare(self, msg, tpn, cc, mtu) < 0
3426 : tport_prepare_and_send(self, msg, tpn, cc, mtu) < 0)
3427 return NULL((void*)0);
3428 else
3429 return self;
3430}
3431
3432int tport_prepare_and_send(tport_t *self, msg_t *msg,
3433 tp_name_t const *tpn,
3434 struct sigcomp_compartment *cc,
3435 unsigned mtu)
3436{
3437 int retval;
3438
3439 /* Prepare message for sending - i.e., encode it */
3440 if (msg_prepare(msg) < 0) {
3441 msg_set_errno(msg, errno(*__errno_location ())); /* msg parser uses plain errno. Hmph. */
3442 return -1;
3443 }
3444
3445 if (msg_size(msg) > (usize_t)(mtu ? mtu : tport_mtu(self))) {
3446 msg_set_errno(msg, EMSGSIZE90);
3447 return -1;
3448 }
3449
3450 /*
3451 * If there is already an queued message,
3452 * put this message straight in the queue
3453 */
3454 if ((self->tp_queue && self->tp_queue[self->tp_qhead]) ||
3455 /* ...or we are connecting */
3456 (self->tp_events & (SU_WAIT_CONNECT(0x004) | SU_WAIT_OUT(0x004)))) {
3457 if (tport_queue(self, msg) < 0) {
3458 SU_DEBUG_9(("tport_queue failed in tsend\n" VA_NONE))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 3458, "tport_queue failed in tsend\n" "%s",
"")) : (void)0)
;
3459 return -1;
3460 }
3461 return 0;
3462 }
3463
3464 retval = tport_send_msg(self, msg, tpn, cc);
3465
3466 tport_set_secondary_timer(self);
3467
3468 return retval;
3469}
3470
3471
3472/** Send a message.
3473 *
3474 * @retval 0 when succesful
3475 * @retval -1 upon an error
3476 */
3477int tport_send_msg(tport_t *self, msg_t *msg,
3478 tp_name_t const *tpn,
3479 struct sigcomp_compartment *cc)
3480{
3481 msg_iovec_t *iov, auto_iov[40];
3482 size_t iovlen, iovused, i, total;
3483 size_t n;
3484 ssize_t nerror;
3485 int sdwn_after, close_after;
3486 su_time_t now;
3487 su_addrinfo_t *ai;
3488
3489 assert(self->tp_queue == NULL ||((void) sizeof ((self->tp_queue == ((void*)0) || self->
tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue
[self->tp_qhead] == msg) ? 1 : 0), __extension__ ({ if (self
->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead
] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg
) ; else __assert_fail ("self->tp_queue == NULL || self->tp_queue[self->tp_qhead] == NULL || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3491, __extension__ __PRETTY_FUNCTION__); }))
3490 self->tp_queue[self->tp_qhead] == NULL ||((void) sizeof ((self->tp_queue == ((void*)0) || self->
tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue
[self->tp_qhead] == msg) ? 1 : 0), __extension__ ({ if (self
->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead
] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg
) ; else __assert_fail ("self->tp_queue == NULL || self->tp_queue[self->tp_qhead] == NULL || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3491, __extension__ __PRETTY_FUNCTION__); }))
3491 self->tp_queue[self->tp_qhead] == msg)((void) sizeof ((self->tp_queue == ((void*)0) || self->
tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue
[self->tp_qhead] == msg) ? 1 : 0), __extension__ ({ if (self
->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead
] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg
) ; else __assert_fail ("self->tp_queue == NULL || self->tp_queue[self->tp_qhead] == NULL || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3491, __extension__ __PRETTY_FUNCTION__); }))
;
3492
3493 if (self->tp_iov)
3494 /* Use the heap-allocated I/O vector */
3495 iov = self->tp_iov, iovlen = self->tp_iovlen;
3496 else
3497 /* Use the stack I/O vector */
3498 iov = auto_iov, iovlen = sizeof(auto_iov)/sizeof(auto_iov[0]);
3499
3500 /* Get a iovec for message contents */
3501 for (;;) {
3502 iovused = msg_iovec(msg, iov, iovlen);
3503 if (iovused <= iovlen)
3504 break;
3505
3506 iov = su_realloc(self->tp_home, self->tp_iov, sizeof(*iov) * iovused);
3507
3508 if (iov == NULL((void*)0)) {
3509 msg_set_errno(msg, errno(*__errno_location ()));
3510 return -1;
3511 }
3512
3513 self->tp_iov = iov, self->tp_iovlen = iovlen = iovused;
3514 }
3515
3516 assert(iovused > 0)((void) sizeof ((iovused > 0) ? 1 : 0), __extension__ ({ if
(iovused > 0) ; else __assert_fail ("iovused > 0", "tport.c"
, 3516, __extension__ __PRETTY_FUNCTION__); }))
;
3517
3518 self->tp_stime = self->tp_ktime = now = su_now();
3519
3520 nerror = tport_vsend(self, msg, tpn, iov, iovused, cc);
3521 SU_DEBUG_9(("tport_vsend returned "MOD_ZD"\n", nerror))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 3521, "tport_vsend returned ""%zd""\n", nerror
)) : (void)0)
;
3522
3523 if (nerror == -1)
3524 return -1;
3525
3526 n = (size_t)nerror;
3527
3528 self->tp_unsent = NULL((void*)0), self->tp_unsentlen = 0;
3529
3530 if (n > 0 && self->tp_master->mr_log && self->tp_slogged != msg) {
3531 tport_log_msg(self, msg, "send", "to", now);
3532 self->tp_slogged = msg;
3533 }
3534
3535 for (i = 0, total = 0; i < iovused; i++) {
3536 if (total + (size_t)iov[i].mv_lensiv_len > n) {
3537 if (tport_is_connection_oriented(self)) {
3538 iov[i].mv_lensiv_len -= (su_ioveclen_t)(n - total);
3539 iov[i].mv_basesiv_base = (char *)iov[i].mv_basesiv_base + (n - total);
3540 if (tport_queue_rest(self, msg, &iov[i], iovused - i) < 0)
3541 return tport_send_fatal(self, msg, tpn, "tport_queue_rest");
3542 else
3543 return 0;
3544 }
3545 else {
3546 char const *comp = tpn->tpn_comp;
3547
3548 SU_DEBUG_1(("%s(%p): send truncated for %s/%s:%s%s%s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 3550, "%s(%p): send truncated for %s/%s:%s%s%s\n"
, "tport_vsend", (void *)self, tpn->tpn_proto, tpn->tpn_host
, tpn->tpn_port, comp ? ";comp=" : "", comp ? comp : "")) :
(void)0)
3549 "tport_vsend", (void *)self, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 3550, "%s(%p): send truncated for %s/%s:%s%s%s\n"
, "tport_vsend", (void *)self, tpn->tpn_proto, tpn->tpn_host
, tpn->tpn_port, comp ? ";comp=" : "", comp ? comp : "")) :
(void)0)
3550 comp ? ";comp=" : "", comp ? comp : ""))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 3550, "%s(%p): send truncated for %s/%s:%s%s%s\n"
, "tport_vsend", (void *)self, tpn->tpn_proto, tpn->tpn_host
, tpn->tpn_port, comp ? ";comp=" : "", comp ? comp : "")) :
(void)0)
;
3551
3552 msg_set_errno(msg, EIO5);
3553 return /* tport_send_fatal(self, msg, tpn, "tport_send") */ -1;
3554 }
3555 }
3556
3557 total += iov[i].mv_lensiv_len;
3558 }
3559
3560 /* We have sent a complete message */
3561 tport_sent_message(self, msg, 0);
3562
3563 if (!tport_is_secondary(self))
3564 return 0;
3565
3566 ai = msg_addrinfo(msg); assert(ai)((void) sizeof ((ai) ? 1 : 0), __extension__ ({ if (ai) ; else
__assert_fail ("ai", "tport.c", 3566, __extension__ __PRETTY_FUNCTION__
); }))
;
3567 close_after = (ai->ai_flags & TP_AI_CLOSE0x08000) == TP_AI_CLOSE0x08000;
3568 sdwn_after = (ai->ai_flags & TP_AI_SHUTDOWN0x04000) == TP_AI_SHUTDOWN0x04000 ||
3569 self->tp_send_close;
3570
3571 if (close_after || sdwn_after)
3572 tport_shutdown0(self, close_after ? 2 : 1);
3573
3574 return 0;
3575}
3576
3577static
3578ssize_t tport_vsend(tport_t *self,
3579 msg_t *msg,
3580 tp_name_t const *tpn,
3581 msg_iovec_t iov[],
3582 size_t iovused,
3583 struct sigcomp_compartment *cc)
3584{
3585 ssize_t n;
3586 su_addrinfo_t *ai = msg_addrinfo(msg);
3587
3588 if (cc) {
3589 n = tport_send_comp(self, msg, iov, iovused, cc, self->tp_comp);
3590 }
3591 else {
3592 ai->ai_flags &= ~TP_AI_COMPRESSED0x01000;
3593 n = self->tp_pri->pri_vtable->vtp_send(self, msg, iov, iovused);
3594 }
3595
3596 if (n == 0)
3597 return 0;
3598
3599 if (n == -1)
3600 return tport_send_error(self, msg, tpn, "tport_vsend");
3601
3602 tport_sent_bytes(self, n, n); /* Sigcomp will decrease on_line accodingly */
3603
3604 if (n > 0 && self->tp_master->mr_dump_file)
3605 tport_dump_iovec(self, msg, n, iov, iovused, "sent", "to");
3606
3607 if (n > 0 && self->tp_master->mr_capt_sock)
3608 tport_capt_msg(self, msg, n, iov, iovused, "sent");
3609
3610
3611 if (tport_log->log_level >= 7) {
3612 size_t i, m = 0;
3613
3614 for (i = 0; i < iovused; i++)
3615 m += iov[i].mv_lensiv_len;
3616
3617 if (tpn == NULL((void*)0) || tport_is_connection_oriented(self))
3618 tpn = self->tp_name;
3619
3620 SU_DEBUG_7(("%s(%p): "MOD_ZU" bytes of "MOD_ZU" to %s/%s:%s%s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3623, "%s(%p): ""%zu"" bytes of ""%zu"" to %s/%s:%s%s\n"
, "tport_vsend", (void *)self, n, m, self->tp_name->tpn_proto
, tpn->tpn_host, tpn->tpn_port, (ai->ai_flags & 0x01000
) ? ";comp=sigcomp" : "")) : (void)0)
3621 "tport_vsend", (void *)self, n, m,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3623, "%s(%p): ""%zu"" bytes of ""%zu"" to %s/%s:%s%s\n"
, "tport_vsend", (void *)self, n, m, self->tp_name->tpn_proto
, tpn->tpn_host, tpn->tpn_port, (ai->ai_flags & 0x01000
) ? ";comp=sigcomp" : "")) : (void)0)
3622 self->tp_name->tpn_proto, tpn->tpn_host, tpn->tpn_port,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3623, "%s(%p): ""%zu"" bytes of ""%zu"" to %s/%s:%s%s\n"
, "tport_vsend", (void *)self, n, m, self->tp_name->tpn_proto
, tpn->tpn_host, tpn->tpn_port, (ai->ai_flags & 0x01000
) ? ";comp=sigcomp" : "")) : (void)0)
3623 (ai->ai_flags & TP_AI_COMPRESSED) ? ";comp=sigcomp" : ""))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3623, "%s(%p): ""%zu"" bytes of ""%zu"" to %s/%s:%s%s\n"
, "tport_vsend", (void *)self, n, m, self->tp_name->tpn_proto
, tpn->tpn_host, tpn->tpn_port, (ai->ai_flags & 0x01000
) ? ";comp=sigcomp" : "")) : (void)0)
;
3624 }
3625
3626 return n;
3627}
3628
3629static
3630int tport_send_error(tport_t *self, msg_t *msg, tp_name_t const *tpn,
3631 char const *who)
3632{
3633 int error = su_errno();
3634
3635 if (error == EPIPE32) {
3636 /*Xyzzy*/
3637 }
3638
3639 if (su_is_blocking(error)((error) == 115 || (error) == 11 || (error) == 11 || (error) ==
4)
) {
3640 su_addrinfo_t *ai = msg_addrinfo(msg);
3641 char const *comp = (ai->ai_flags & TP_AI_COMPRESSED0x01000) ? ";comp=sigcomp" : "";
3642 SU_DEBUG_5(("%s(%p): %s with (s=%d %s/%s:%s%s)\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 3644, "%s(%p): %s with (s=%d %s/%s:%s%s)\n"
, who, (void *)self, "EAGAIN", (int)self->tp_socket, tpn->
tpn_proto, tpn->tpn_host, tpn->tpn_port, comp)) : (void
)0)
3643 who, (void *)self, "EAGAIN", (int)self->tp_socket,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 3644, "%s(%p): %s with (s=%d %s/%s:%s%s)\n"
, who, (void *)self, "EAGAIN", (int)self->tp_socket, tpn->
tpn_proto, tpn->tpn_host, tpn->tpn_port, comp)) : (void
)0)
3644 tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 5 ? (_su_llog(tport_log, 5, "tport.c", (const
char *)__func__, 3644, "%s(%p): %s with (s=%d %s/%s:%s%s)\n"
, who, (void *)self, "EAGAIN", (int)self->tp_socket, tpn->
tpn_proto, tpn->tpn_host, tpn->tpn_port, comp)) : (void
)0)
;
3645 return 0;
3646 }
3647
3648 msg_set_errno(msg, error);
3649
3650 return tport_send_fatal(self, msg, tpn, who);
3651}
3652
3653static
3654int tport_send_fatal(tport_t *self, msg_t *msg, tp_name_t const *tpn,
3655 char const *who)
3656{
3657 su_addrinfo_t *ai = msg_addrinfo(msg);
3658 char const *comp = (ai->ai_flags & TP_AI_COMPRESSED0x01000) ? ";comp=sigcomp" : "";
3659
3660 int error = msg_errno(msg);
3661
3662 if (self->tp_addrinfo->ai_family == AF_INET2) {
3663 SU_DEBUG_3(("%s(%p): %s with (s=%d %s/%s:%s%s)\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3665, "%s(%p): %s with (s=%d %s/%s:%s%s)\n"
, who, (void *)self, su_strerror(error), (int)self->tp_socket
, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp
)) : (void)0)
3664 who, (void *)self, su_strerror(error), (int)self->tp_socket,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3665, "%s(%p): %s with (s=%d %s/%s:%s%s)\n"
, who, (void *)self, su_strerror(error), (int)self->tp_socket
, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp
)) : (void)0)
3665 tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3665, "%s(%p): %s with (s=%d %s/%s:%s%s)\n"
, who, (void *)self, su_strerror(error), (int)self->tp_socket
, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp
)) : (void)0)
;
3666 }
3667#if SU_HAVE_IN61
3668 else if (self->tp_addrinfo->ai_family == AF_INET610) {
3669 su_sockaddr_t const *su = (su_sockaddr_t const *)ai->ai_addr;
3670 SU_DEBUG_3(("%s(%p): %s with (s=%d, IP6=%s/%s:%s%s"(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3674, "%s(%p): %s with (s=%d, IP6=%s/%s:%s%s"
" (scope=%i) addrlen=%u)\n", who, (void *)self, su_strerror(
error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host
, tpn->tpn_port, comp, su->su_array32[6], (unsigned)ai->
ai_addrlen)) : (void)0)
3671 " (scope=%i) addrlen=%u)\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3674, "%s(%p): %s with (s=%d, IP6=%s/%s:%s%s"
" (scope=%i) addrlen=%u)\n", who, (void *)self, su_strerror(
error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host
, tpn->tpn_port, comp, su->su_array32[6], (unsigned)ai->
ai_addrlen)) : (void)0)
3672 who, (void *)self, su_strerror(error), (int)self->tp_socket,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3674, "%s(%p): %s with (s=%d, IP6=%s/%s:%s%s"
" (scope=%i) addrlen=%u)\n", who, (void *)self, su_strerror(
error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host
, tpn->tpn_port, comp, su->su_array32[6], (unsigned)ai->
ai_addrlen)) : (void)0)
3673 tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3674, "%s(%p): %s with (s=%d, IP6=%s/%s:%s%s"
" (scope=%i) addrlen=%u)\n", who, (void *)self, su_strerror(
error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host
, tpn->tpn_port, comp, su->su_array32[6], (unsigned)ai->
ai_addrlen)) : (void)0)
3674 su->su_scope_id, (unsigned)ai->ai_addrlen))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3674, "%s(%p): %s with (s=%d, IP6=%s/%s:%s%s"
" (scope=%i) addrlen=%u)\n", who, (void *)self, su_strerror(
error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host
, tpn->tpn_port, comp, su->su_array32[6], (unsigned)ai->
ai_addrlen)) : (void)0)
;
3675 }
3676#endif
3677 else {
3678 SU_DEBUG_3(("%s(%p): %s with (s=%d, AF=%u addrlen=%u)%s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3680, "%s(%p): %s with (s=%d, AF=%u addrlen=%u)%s\n"
, who, (void *)self, su_strerror(error), (int)self->tp_socket
, ai->ai_family, (unsigned)ai->ai_addrlen, comp)) : (void
)0)
3679 who, (void *)self, su_strerror(error),(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3680, "%s(%p): %s with (s=%d, AF=%u addrlen=%u)%s\n"
, who, (void *)self, su_strerror(error), (int)self->tp_socket
, ai->ai_family, (unsigned)ai->ai_addrlen, comp)) : (void
)0)
3680 (int)self->tp_socket, ai->ai_family, (unsigned)ai->ai_addrlen, comp))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3680, "%s(%p): %s with (s=%d, AF=%u addrlen=%u)%s\n"
, who, (void *)self, su_strerror(error), (int)self->tp_socket
, ai->ai_family, (unsigned)ai->ai_addrlen, comp)) : (void
)0)
;
3681 }
3682
3683#if 0
3684 int i;
3685 for (i = 0; i < iovused; i++)
3686 SU_DEBUG_7(("\t\tiov[%d] = { %d bytes @ %p }\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3687, "\t\tiov[%d] = { %d bytes @ %p }\n", i
, iov[i].siv_len, (void *)iov[i].siv_base)) : (void)0)
3687 i, iov[i].siv_len, (void *)iov[i].siv_base))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3687, "\t\tiov[%d] = { %d bytes @ %p }\n", i
, iov[i].siv_len, (void *)iov[i].siv_base)) : (void)0)
;
3688#endif
3689
3690 if (tport_is_connection_oriented(self)) {
3691 tport_error_report(self, error, NULL((void*)0));
3692 if (tport_has_connection(self))
3693 tport_close(self);
3694 }
3695
3696 return -1;
3697}
3698
3699
3700static
3701int tport_queue_rest(tport_t *self,
3702 msg_t *msg,
3703 msg_iovec_t iov[],
3704 size_t iovused)
3705{
3706 size_t iovlen = self->tp_iovlen;
3707
3708 assert(tport_is_connection_oriented(self))((void) sizeof ((tport_is_connection_oriented(self)) ? 1 : 0)
, __extension__ ({ if (tport_is_connection_oriented(self)) ; else
__assert_fail ("tport_is_connection_oriented(self)", "tport.c"
, 3708, __extension__ __PRETTY_FUNCTION__); }))
;
3709 assert(self->tp_queue == NULL ||((void) sizeof ((self->tp_queue == ((void*)0) || self->
tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue
[self->tp_qhead] == msg) ? 1 : 0), __extension__ ({ if (self
->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead
] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg
) ; else __assert_fail ("self->tp_queue == NULL || self->tp_queue[self->tp_qhead] == NULL || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3711, __extension__ __PRETTY_FUNCTION__); }))
3710 self->tp_queue[self->tp_qhead] == NULL ||((void) sizeof ((self->tp_queue == ((void*)0) || self->
tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue
[self->tp_qhead] == msg) ? 1 : 0), __extension__ ({ if (self
->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead
] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg
) ; else __assert_fail ("self->tp_queue == NULL || self->tp_queue[self->tp_qhead] == NULL || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3711, __extension__ __PRETTY_FUNCTION__); }))
3711 self->tp_queue[self->tp_qhead] == msg)((void) sizeof ((self->tp_queue == ((void*)0) || self->
tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue
[self->tp_qhead] == msg) ? 1 : 0), __extension__ ({ if (self
->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead
] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg
) ; else __assert_fail ("self->tp_queue == NULL || self->tp_queue[self->tp_qhead] == NULL || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3711, __extension__ __PRETTY_FUNCTION__); }))
;
3712
3713 if (tport_queue(self, msg) < 0)
3714 return -1;
3715
3716 assert(self->tp_queue[self->tp_qhead] == msg)((void) sizeof ((self->tp_queue[self->tp_qhead] == msg)
? 1 : 0), __extension__ ({ if (self->tp_queue[self->tp_qhead
] == msg) ; else __assert_fail ("self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3716, __extension__ __PRETTY_FUNCTION__); }))
;
3717
3718 if (self->tp_iov == NULL((void*)0)) {
3719 if (iovlen < 40) iovlen = 40;
3720 if (iovlen < iovused) iovlen = iovused;
3721 self->tp_iov = su_alloc(self->tp_home, iovlen * sizeof(iov[0]));
3722 self->tp_iovlen = iovlen;
3723
3724 if (!self->tp_iov) {
3725 msg_set_errno(msg, errno(*__errno_location ()));
3726 return -1;
3727 }
3728
3729 memcpy(self->tp_iov, iov, iovused * sizeof(iov[0]));
3730
3731 iov = self->tp_iov;
3732 }
3733
3734 self->tp_unsent = iov;
3735 self->tp_unsentlen = iovused;
3736
3737 /* the POLLOUT event is far too unreliable with SCTP */
3738 if (self->tp_addrinfo->ai_protocol == IPPROTO_SCTPIPPROTO_SCTP)
3739 return 0;
3740
3741 /* Ask for a send event */
3742 tport_set_events(self, SU_WAIT_OUT(0x004), 0);
3743
3744 return 0;
3745}
3746
3747/** Queue a message to transport.
3748 *
3749 * The tport_tqueue() function queues a message in the send queue. It is
3750 * used by an (server) application that is required to send (response)
3751 * messages in certain order. For example, a HTTP server or proxy may
3752 * receive multiple requests from a single TCP connection. The server is
3753 * required to answer to the requests in same order as they are received.
3754 * The responses are, however, sometimes generated asynchronously, that is,
3755 * a response to a later request may be ready earlier. For that purpose, the
3756 * HTTP protocol stack queues an empty response message immediately upon
3757 * receiving a request. Other messages cannot be sent before the queued one.
3758 *
3759 * The function tport_tqsend() is used to send the completed response message.
3760 *
3761 * @param self pointer to transport object
3762 * @param msg message to be inserted into queue
3763 * @param tag,value,... tagged argument list
3764 *
3765 * @TAGS
3766 * @par Currently none.
3767 *
3768 * @retval 0 when successful
3769 * @retval -1 upon an error
3770
3771 * @ERRORS
3772 * @ERROR EINVAL Invalid argument(s).
3773 * @ERROR ENOMEM Memory was exhausted.
3774 * @ERROR ENOBUFS The transport object queue was full.
3775 *
3776 * @deprecated Alternative interface will be provided in near future.
3777 *
3778 * @sa tport_tqsend()
3779 */
3780int tport_tqueue(tport_t *self, msg_t *msg,
3781 tag_type_t tag, tag_value_t value, ...)
3782{
3783 msg_unprepare(msg);
3784
3785 return tport_queue(self, msg);
3786}
3787
3788/** Return number of queued messages. */
3789isize_t tport_queuelen(tport_t const *self)
3790{
3791 isize_t retval = 0;
3792
3793 if (self && self->tp_queue) {
3794 unsigned short i, N = self->tp_params->tpp_qsize;
3795
3796 for (i = self->tp_qhead; self->tp_queue[i] && retval < N; i = (i + 1) % N)
3797 retval++;
3798 }
3799
3800 return retval;
3801}
3802
3803static
3804int tport_queue(tport_t *self, msg_t *msg)
3805{
3806 unsigned short qhead = self->tp_qhead;
3807 unsigned short N = self->tp_params->tpp_qsize;
3808
3809 SU_DEBUG_7(("tport_queue(%p): queueing %p for %s/%s:%s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3811, "tport_queue(%p): queueing %p for %s/%s:%s\n"
, (void *)self, (void *)msg, self->tp_name->tpn_proto, self
->tp_name->tpn_host, self->tp_name->tpn_port)) : (
void)0)
3810 (void *)self, (void *)msg,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3811, "tport_queue(%p): queueing %p for %s/%s:%s\n"
, (void *)self, (void *)msg, self->tp_name->tpn_proto, self
->tp_name->tpn_host, self->tp_name->tpn_port)) : (
void)0)
3811 self->tp_protoname, self->tp_host, self->tp_port))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3811, "tport_queue(%p): queueing %p for %s/%s:%s\n"
, (void *)self, (void *)msg, self->tp_name->tpn_proto, self
->tp_name->tpn_host, self->tp_name->tpn_port)) : (
void)0)
;
3812
3813 if (self->tp_queue == NULL((void*)0)) {
3814 assert(N > 0)((void) sizeof ((N > 0) ? 1 : 0), __extension__ ({ if (N >
0) ; else __assert_fail ("N > 0", "tport.c", 3814, __extension__
__PRETTY_FUNCTION__); }))
;
3815 assert(qhead == 0)((void) sizeof ((qhead == 0) ? 1 : 0), __extension__ ({ if (qhead
== 0) ; else __assert_fail ("qhead == 0", "tport.c", 3815, __extension__
__PRETTY_FUNCTION__); }))
;
3816 self->tp_queue = su_zalloc(self->tp_home, N * sizeof(msg));
3817 if (!self->tp_queue) {
3818 msg_set_errno(msg, errno(*__errno_location ()));
3819 return -1;
3820 }
3821 }
3822
3823 if (self->tp_queue[qhead] == msg)
3824 return 0;
3825
3826 while (self->tp_queue[qhead]) {
3827 qhead = (qhead + 1) % N;
3828 if (qhead == self->tp_qhead) {
3829 msg_set_errno(msg, ENOBUFS105);
3830 return -1;
3831 }
3832 }
3833
3834 self->tp_queue[qhead] = msg_ref_create(msg);
3835
3836 return 0;
3837}
3838
3839/** Send a queued message (and queue another, if required).
3840 *
3841 * The function tport_tqsend() sends a message to the transport.
3842 *
3843 * @deprecated Alternative interface will be provided in near future.
3844 */
3845int tport_tqsend(tport_t *self, msg_t *msg, msg_t *next,
3846 tag_type_t tag, tag_value_t value, ...)
3847{
3848 unsigned short qhead;
3849 ta_list ta;
3850 int reuse, sdwn_after, close_after;
3851 unsigned short N;
3852 su_addrinfo_t *ai;
3853
3854 if (self == NULL((void*)0))
3855 return -1;
3856
3857 qhead = self->tp_qhead;
3858 N = self->tp_params->tpp_qsize;
3859 reuse = self->tp_reusable;
3860 sdwn_after = 0;
3861 close_after = 0;
3862
3863 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
3864
3865 tl_gets(ta_args(ta)(ta).tl,
3866 TPTAG_REUSE_REF(reuse)tptag_reuse_ref, tag_bool_vr(&(reuse)),
3867 TPTAG_SDWN_AFTER_REF(sdwn_after)tptag_sdwn_after_ref, tag_bool_vr(&(sdwn_after)),
3868 TPTAG_CLOSE_AFTER_REF(close_after)tptag_close_after_ref, tag_bool_vr(&(close_after)),
3869 TAG_END()(tag_type_t)0, (tag_value_t)0);
3870
3871 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
3872
3873 /* If "next", make sure we can queue it */
3874 if (next && self->tp_queue[qhead == 0 ? N - 1 : qhead - 1]) {
3875 msg_set_errno(next, ENOBUFS105);
3876 return -1;
3877 }
3878
3879 /* Prepare message for sending - i.e., encode it */
3880 if (msg_prepare(msg) < 0) {
3881 msg_set_errno(msg, errno(*__errno_location ()));
3882 return -1;
3883 }
3884
3885 tport_peer_address(self, msg); /* Set addrinfo */
3886 if (next == NULL((void*)0)) {
3887 ai = msg_addrinfo(msg);
3888
3889 if (sdwn_after)
3890 ai->ai_flags |= TP_AI_SHUTDOWN0x04000;
3891 if (close_after)
3892 ai->ai_flags |= TP_AI_CLOSE0x08000;
3893
3894 if (self->tp_queue[qhead] == msg) {
3895 tport_send_queue(self);
3896 tport_set_secondary_timer(self);
3897 }
3898 return 0;
3899 }
3900
3901 ai = msg_addrinfo(next);
3902
3903 if (sdwn_after)
3904 ai->ai_flags |= TP_AI_SHUTDOWN0x04000;
3905 if (close_after)
3906 ai->ai_flags |= TP_AI_CLOSE0x08000;
3907
3908 if (self->tp_queue[qhead] == msg) {
3909 /* XXX - what about errors? */
3910 tport_send_msg(self, msg, self->tp_name, NULL((void*)0));
3911 tport_set_secondary_timer(self);
3912 if (!self->tp_unsent) {
3913 msg_destroy(self->tp_queue[qhead]);
3914 if ((self->tp_queue[qhead] = msg_ref_create(next)))
3915 msg_unprepare(next);
3916 return 0;
3917 }
3918 }
3919
3920 while (self->tp_queue[qhead] && self->tp_queue[qhead] != msg) {
3921 qhead = (qhead + 1) % N;
3922 if (qhead == self->tp_qhead)
3923 break;
3924 }
3925
3926 if (self->tp_queue[qhead] != msg) {
3927 msg_set_errno(next, EINVAL22);
3928 return -1;
3929 }
3930
3931 msg = msg_ref_create(next);
3932
3933 do {
3934 qhead = (qhead + 1) % N;
3935 next = self->tp_queue[qhead]; self->tp_queue[qhead] = msg; msg = next;
3936 /* Above we made sure that there is an empty slot */
3937 assert(!next || qhead != self->tp_qhead)((void) sizeof ((!next || qhead != self->tp_qhead) ? 1 : 0
), __extension__ ({ if (!next || qhead != self->tp_qhead) ;
else __assert_fail ("!next || qhead != self->tp_qhead", "tport.c"
, 3937, __extension__ __PRETTY_FUNCTION__); }))
;
3938 } while (next);
3939
3940 return 0;
3941}
3942
3943/** Send event.
3944 *
3945 * Process SU_WAIT_OUT event.
3946 */
3947void tport_send_event(tport_t *self)
3948{
3949 assert(tport_is_connection_oriented(self))((void) sizeof ((tport_is_connection_oriented(self)) ? 1 : 0)
, __extension__ ({ if (tport_is_connection_oriented(self)) ; else
__assert_fail ("tport_is_connection_oriented(self)", "tport.c"
, 3949, __extension__ __PRETTY_FUNCTION__); }))
;
3950
3951 SU_DEBUG_7(("tport_send_event(%p) - ready to send to (%s/%s:%s)\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3952, "tport_send_event(%p) - ready to send to (%s/%s:%s)\n"
, (void *)self, self->tp_name->tpn_proto, self->tp_name
->tpn_host, self->tp_name->tpn_port)) : (void)0)
3952 (void *)self, self->tp_protoname, self->tp_host, self->tp_port))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 3952, "tport_send_event(%p) - ready to send to (%s/%s:%s)\n"
, (void *)self, self->tp_name->tpn_proto, self->tp_name
->tpn_host, self->tp_name->tpn_port)) : (void)0)
;
3953 tport_send_queue(self);
3954 tport_set_secondary_timer(self);
3955}
3956
3957/** Send queued messages */
3958void tport_send_queue(tport_t *self)
3959{
3960 msg_t *msg;
3961 msg_iovec_t *iov;
3962 size_t i, iovused, n, total;
3963 unsigned short qhead = self->tp_qhead, N = self->tp_params->tpp_qsize;
3964
3965 assert(self->tp_queue && self->tp_queue[qhead])((void) sizeof ((self->tp_queue && self->tp_queue
[qhead]) ? 1 : 0), __extension__ ({ if (self->tp_queue &&
self->tp_queue[qhead]) ; else __assert_fail ("self->tp_queue && self->tp_queue[qhead]"
, "tport.c", 3965, __extension__ __PRETTY_FUNCTION__); }))
;
3966
3967 msg = self->tp_queue[qhead];
3968
3969 iov = self->tp_unsent, self->tp_unsent = NULL((void*)0);
3970 iovused = self->tp_unsentlen, self->tp_unsentlen = 0;
3971
3972 if (iov && iovused) {
3973 ssize_t e;
3974
3975 self->tp_stime = self->tp_ktime = su_now();
3976
3977 e = tport_vsend(self, msg, self->tp_name, iov, iovused, NULL((void*)0));
3978
3979 if (e == -1) /* XXX */
3980 return;
3981
3982 n = (size_t)e;
3983
3984 if (n > 0 && self->tp_master->mr_log && self->tp_slogged != msg) {
3985 tport_log_msg(self, msg, "send", "to", self->tp_stime);
3986 self->tp_slogged = msg;
3987 }
3988
3989 for (i = 0, total = 0; i < iovused; i++) {
3990 if (total + (size_t)iov[i].mv_lensiv_len > n) {
3991 iov[i].mv_lensiv_len -= (su_ioveclen_t)(n - total);
3992 iov[i].mv_basesiv_base = (char *)iov[i].mv_basesiv_base + (n - total);
3993
3994 self->tp_unsent = iov + i;
3995 self->tp_unsentlen = iovused - i;
3996
3997 return;
3998 }
3999 total += iov[i].mv_lensiv_len;
4000 }
4001 assert(total == n)((void) sizeof ((total == n) ? 1 : 0), __extension__ ({ if (total
== n) ; else __assert_fail ("total == n", "tport.c", 4001, __extension__
__PRETTY_FUNCTION__); }))
;
4002
4003 /* We have sent a complete message */
4004
4005 self->tp_queue[qhead] = NULL((void*)0);
4006 tport_sent_message(self, msg, 0);
4007 msg_destroy(msg);
4008
4009 qhead = (qhead + 1) % N;
4010 }
4011
4012 while (msg_is_prepared(msg = self->tp_queue[self->tp_qhead = qhead])) {
4013 /* XXX - what about errors? */
4014 tport_send_msg(self, msg, self->tp_name, NULL((void*)0));
4015 if (self->tp_unsent)
4016 return;
4017
4018 msg = self->tp_queue[qhead]; /* tport_send_msg() may flush queue! */
4019 self->tp_queue[qhead] = NULL((void*)0);
4020 msg_destroy(msg);
4021 qhead = (qhead + 1) % N;
4022 }
4023
4024 /* No more send event(s)? */
4025 tport_set_events(self, 0, SU_WAIT_OUT(0x004));
4026}
4027
4028static int msg_select_addrinfo(msg_t *msg, su_addrinfo_t *res);
4029
4030static int
4031tport_resolve(tport_t *self, msg_t *msg, tp_name_t const *tpn)
4032{
4033 int error;
4034 char ipaddr[TPORT_HOSTPORTSIZE(55)];
4035 su_addrinfo_t *res, hints[1] = {{ 0 }};
4036 char const *host;
4037 su_sockaddr_t *su;
4038
4039 hints->ai_socktype = self->tp_addrinfo->ai_socktype;
4040 hints->ai_protocol = self->tp_addrinfo->ai_protocol;
4041
4042 if (host_is_ip6_reference(tpn->tpn_host)) {
4043 /* Remove [] around IPv6 address */
4044 size_t len = strlen(tpn->tpn_host);
4045 assert(len < sizeof ipaddr)((void) sizeof ((len < sizeof ipaddr) ? 1 : 0), __extension__
({ if (len < sizeof ipaddr) ; else __assert_fail ("len < sizeof ipaddr"
, "tport.c", 4045, __extension__ __PRETTY_FUNCTION__); }))
;
4046 host = memcpy(ipaddr, tpn->tpn_host + 1, len - 2);
4047 ipaddr[len - 2] = '\0';
4048 hints->ai_flags |= AI_NUMERICHOST0x0004;
4049 }
4050 else {
4051#if HAVE_OPEN_C
4052 if (host_is_ip_address(tpn->tpn_host))
4053 hints->ai_flags |= AI_NUMERICHOST0x0004;
4054#endif
4055 host = tpn->tpn_host;
4056 }
4057
4058 if ((error = su_getaddrinfo(host, tpn->tpn_port, hints, &res))) {
4059 SU_DEBUG_3(("tport_resolve: getaddrinfo(\"%s\":%s): %s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 4061, "tport_resolve: getaddrinfo(\"%s\":%s): %s\n"
, tpn->tpn_host, tpn->tpn_port, su_gai_strerror(error))
) : (void)0)
4060 tpn->tpn_host, tpn->tpn_port,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 4061, "tport_resolve: getaddrinfo(\"%s\":%s): %s\n"
, tpn->tpn_host, tpn->tpn_port, su_gai_strerror(error))
) : (void)0)
4061 su_gai_strerror(error)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 4061, "tport_resolve: getaddrinfo(\"%s\":%s): %s\n"
, tpn->tpn_host, tpn->tpn_port, su_gai_strerror(error))
) : (void)0)
;
4062 msg_set_errno(msg, ENXIO6);
4063 return -1;
4064 }
4065
4066 error = msg_select_addrinfo(msg, res);
4067
4068 su = (su_sockaddr_t *) msg_addrinfo(msg)->ai_addr;
4069
4070#if SU_HAVE_IN61
4071 SU_DEBUG_9(("tport_resolve addrinfo = %s%s%s:%d\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4075, "tport_resolve addrinfo = %s%s%s:%d\n"
, su->su_sa.sa_family == 10 ? "[" : "", inet_ntop(su->su_sa
.sa_family, ((su)->su_sa.sa_family == 2 ? (void *)&(su
)->su_sin.sin_addr : ((su)->su_sa.sa_family == 10 ? (void
*)&(su)->su_sin6.sin6_addr : (void *)&(su)->su_sa
.sa_data)), ipaddr, sizeof(ipaddr)), su->su_sa.sa_family ==
10 ? "]" : "", htons(su->su_sin.sin_port))) : (void)0)
4072 su->su_family == AF_INET6 ? "[" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4075, "tport_resolve addrinfo = %s%s%s:%d\n"
, su->su_sa.sa_family == 10 ? "[" : "", inet_ntop(su->su_sa
.sa_family, ((su)->su_sa.sa_family == 2 ? (void *)&(su
)->su_sin.sin_addr : ((su)->su_sa.sa_family == 10 ? (void
*)&(su)->su_sin6.sin6_addr : (void *)&(su)->su_sa
.sa_data)), ipaddr, sizeof(ipaddr)), su->su_sa.sa_family ==
10 ? "]" : "", htons(su->su_sin.sin_port))) : (void)0)
4073 su_inet_ntop(su->su_family, SU_ADDR(su), ipaddr, sizeof(ipaddr)),(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4075, "tport_resolve addrinfo = %s%s%s:%d\n"
, su->su_sa.sa_family == 10 ? "[" : "", inet_ntop(su->su_sa
.sa_family, ((su)->su_sa.sa_family == 2 ? (void *)&(su
)->su_sin.sin_addr : ((su)->su_sa.sa_family == 10 ? (void
*)&(su)->su_sin6.sin6_addr : (void *)&(su)->su_sa
.sa_data)), ipaddr, sizeof(ipaddr)), su->su_sa.sa_family ==
10 ? "]" : "", htons(su->su_sin.sin_port))) : (void)0)
4074 su->su_family == AF_INET6 ? "]" : "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4075, "tport_resolve addrinfo = %s%s%s:%d\n"
, su->su_sa.sa_family == 10 ? "[" : "", inet_ntop(su->su_sa
.sa_family, ((su)->su_sa.sa_family == 2 ? (void *)&(su
)->su_sin.sin_addr : ((su)->su_sa.sa_family == 10 ? (void
*)&(su)->su_sin6.sin6_addr : (void *)&(su)->su_sa
.sa_data)), ipaddr, sizeof(ipaddr)), su->su_sa.sa_family ==
10 ? "]" : "", htons(su->su_sin.sin_port))) : (void)0)
4075 htons(su->su_port)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4075, "tport_resolve addrinfo = %s%s%s:%d\n"
, su->su_sa.sa_family == 10 ? "[" : "", inet_ntop(su->su_sa
.sa_family, ((su)->su_sa.sa_family == 2 ? (void *)&(su
)->su_sin.sin_addr : ((su)->su_sa.sa_family == 10 ? (void
*)&(su)->su_sin6.sin6_addr : (void *)&(su)->su_sa
.sa_data)), ipaddr, sizeof(ipaddr)), su->su_sa.sa_family ==
10 ? "]" : "", htons(su->su_sin.sin_port))) : (void)0)
;
4076#else
4077 SU_DEBUG_9(("tport_resolve addrinfo = %s%s%s:%d\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4081, "tport_resolve addrinfo = %s%s%s:%d\n"
, "", inet_ntop(su->su_sa.sa_family, ((su)->su_sa.sa_family
== 2 ? (void *)&(su)->su_sin.sin_addr : ((su)->su_sa
.sa_family == 10 ? (void *)&(su)->su_sin6.sin6_addr : (
void *)&(su)->su_sa.sa_data)), ipaddr, sizeof(ipaddr))
, "", htons(su->su_sin.sin_port))) : (void)0)
4078 "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4081, "tport_resolve addrinfo = %s%s%s:%d\n"
, "", inet_ntop(su->su_sa.sa_family, ((su)->su_sa.sa_family
== 2 ? (void *)&(su)->su_sin.sin_addr : ((su)->su_sa
.sa_family == 10 ? (void *)&(su)->su_sin6.sin6_addr : (
void *)&(su)->su_sa.sa_data)), ipaddr, sizeof(ipaddr))
, "", htons(su->su_sin.sin_port))) : (void)0)
4079 su_inet_ntop(su->su_family, SU_ADDR(su), ipaddr, sizeof(ipaddr)),(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4081, "tport_resolve addrinfo = %s%s%s:%d\n"
, "", inet_ntop(su->su_sa.sa_family, ((su)->su_sa.sa_family
== 2 ? (void *)&(su)->su_sin.sin_addr : ((su)->su_sa
.sa_family == 10 ? (void *)&(su)->su_sin6.sin6_addr : (
void *)&(su)->su_sa.sa_data)), ipaddr, sizeof(ipaddr))
, "", htons(su->su_sin.sin_port))) : (void)0)
4080 "",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4081, "tport_resolve addrinfo = %s%s%s:%d\n"
, "", inet_ntop(su->su_sa.sa_family, ((su)->su_sa.sa_family
== 2 ? (void *)&(su)->su_sin.sin_addr : ((su)->su_sa
.sa_family == 10 ? (void *)&(su)->su_sin6.sin6_addr : (
void *)&(su)->su_sa.sa_data)), ipaddr, sizeof(ipaddr))
, "", htons(su->su_sin.sin_port))) : (void)0)
4081 htons(su->su_port)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 9 ? (_su_llog(tport_log, 9, "tport.c", (const
char *)__func__, 4081, "tport_resolve addrinfo = %s%s%s:%d\n"
, "", inet_ntop(su->su_sa.sa_family, ((su)->su_sa.sa_family
== 2 ? (void *)&(su)->su_sin.sin_addr : ((su)->su_sa
.sa_family == 10 ? (void *)&(su)->su_sin6.sin6_addr : (
void *)&(su)->su_sa.sa_data)), ipaddr, sizeof(ipaddr))
, "", htons(su->su_sin.sin_port))) : (void)0)
;
4082#endif
4083
4084 su_freeaddrinfo(res);
4085
4086 return error;
4087}
4088
4089static int
4090msg_select_addrinfo(msg_t *msg, su_addrinfo_t *res)
4091{
4092 su_addrinfo_t *ai, *mai = msg_addrinfo(msg);
4093 su_sockaddr_t *su = (su_sockaddr_t *)mai->ai_addr;
4094
4095 for (ai = res; ai; ai = ai->ai_next) {
4096#if SU_HAVE_IN61
4097 if (ai->ai_family != AF_INET2 && ai->ai_family != AF_INET610)
4098 continue;
4099#else
4100 if (ai->ai_family != AF_INET2)
4101 continue;
4102#endif
4103
4104 if (ai->ai_protocol == 0)
4105 continue;
4106 if (ai->ai_addrlen > sizeof(su_sockaddr_t))
4107 continue;
4108
4109 mai->ai_family = ai->ai_family;
4110 mai->ai_socktype = ai->ai_socktype;
4111 mai->ai_protocol = ai->ai_protocol;
4112
4113 if (ai->ai_addrlen < sizeof(su_sockaddr_t))
4114 memset(su, 0, sizeof(su_sockaddr_t));
4115 memcpy(su, ai->ai_addr, ai->ai_addrlen);
4116 if (su_sockaddr_size(su)((socklen_t)((su)->su_sa.sa_family == 2 ? sizeof((su)->
su_sin) : ((su)->su_sa.sa_family == 10 ? sizeof((su)->su_sin6
) : sizeof(*su))))
)
4117 mai->ai_addrlen = su_sockaddr_size(su)((socklen_t)((su)->su_sa.sa_family == 2 ? sizeof((su)->
su_sin) : ((su)->su_sa.sa_family == 10 ? sizeof((su)->su_sin6
) : sizeof(*su))))
;
4118 else
4119 mai->ai_addrlen = ai->ai_addrlen;
4120 return 0;
4121 }
4122
4123 msg_set_errno(msg, EAFNOSUPPORT97);
4124
4125 return -1;
4126}
4127
4128/** Copy peer address to msg */
4129void
4130tport_peer_address(tport_t *self, msg_t *msg)
4131{
4132 su_addrinfo_t *mai = msg_addrinfo(msg);
4133 su_addrinfo_t const *tai = self->tp_addrinfo;
4134 void *maddr = mai->ai_addr;
4135 int flags = mai->ai_flags;
4136
4137 memcpy(mai, tai, sizeof *mai);
4138 mai->ai_addr = memcpy(maddr, tai->ai_addr, tai->ai_addrlen);
4139 mai->ai_flags = flags;
4140}
4141
4142/** Process error event.
4143 *
4144 * Return events that can be processed afterwards.
4145 */
4146int tport_error_event(tport_t *self)
4147{
4148 int errcode;
4149 su_sockaddr_t name[1] = {{ 0 }};
4150
4151 name->su_familysu_sa.sa_family = AF_UNSPEC0; /* 0 */
4152
4153 if (tport_is_udp(self)) {
4154 errcode = tport_udp_error(self, name);
4155 }
4156 else {
4157 /* Process error event for basic transport. */
4158 errcode = su_soerror(self->tp_socket);
4159 }
4160
4161 if (errcode == 0 || errcode == EPIPE32)
4162 return errcode;
4163
4164 tport_error_report(self, errcode, name);
4165
4166 return 0;
4167}
4168
4169/** Mark message as waiting for a response.
4170 *
4171 * @return Positive integer, or -1 upon an error.
4172 */
4173int tport_pend(tport_t *self,
4174 msg_t *msg,
4175 tport_pending_error_f *callback,
4176 tp_client_t *client)
4177{
4178 tport_pending_t *pending;
4179
4180 if (self == NULL((void*)0) || callback == NULL((void*)0))
4181 return -1;
4182
4183 if (msg == NULL((void*)0) && tport_is_primary(self))
4184 return -1;
4185
4186 SU_DEBUG_7(("tport_pend(%p): pending %p for %s/%s:%s (already %u)\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4189, "tport_pend(%p): pending %p for %s/%s:%s (already %u)\n"
, (void *)self, (void *)msg, self->tp_name->tpn_proto, self
->tp_name->tpn_host, self->tp_name->tpn_port, self
->tp_pused)) : (void)0)
4187 (void *)self, (void *)msg,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4189, "tport_pend(%p): pending %p for %s/%s:%s (already %u)\n"
, (void *)self, (void *)msg, self->tp_name->tpn_proto, self
->tp_name->tpn_host, self->tp_name->tpn_port, self
->tp_pused)) : (void)0)
4188 self->tp_protoname, self->tp_host, self->tp_port,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4189, "tport_pend(%p): pending %p for %s/%s:%s (already %u)\n"
, (void *)self, (void *)msg, self->tp_name->tpn_proto, self
->tp_name->tpn_host, self->tp_name->tpn_port, self
->tp_pused)) : (void)0)
4189 self->tp_pused))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4189, "tport_pend(%p): pending %p for %s/%s:%s (already %u)\n"
, (void *)self, (void *)msg, self->tp_name->tpn_proto, self
->tp_name->tpn_host, self->tp_name->tpn_port, self
->tp_pused)) : (void)0)
;
4190
4191 if (self->tp_released == NULL((void*)0)) {
4192 unsigned i, len = 8;
4193 if (self->tp_plen)
4194 len = 2 * self->tp_plen;
4195 pending = su_realloc(self->tp_home,
4196 self->tp_pending, len * sizeof(*pending));
4197 if (!pending) {
4198 msg_set_errno(msg, errno(*__errno_location ()));
4199 return -1;
4200 }
4201
4202 memset(pending + self->tp_plen, 0, (len - self->tp_plen) * sizeof(*pending));
4203
4204 for (i = self->tp_plen; i + 1 < len; i++)
4205 pending[i].p_client = pending + i + 1;
4206
4207 self->tp_released = pending + self->tp_plen;
4208 self->tp_pending = pending;
4209 self->tp_plen = len;
4210 }
4211
4212 pending = self->tp_released;
4213 self->tp_released = pending->p_client;
4214
4215 pending->p_callback = callback;
4216 pending->p_client = client;
4217 pending->p_msg = msg;
4218 pending->p_reported = self->tp_reported;
4219
4220 self->tp_pused++;
4221
4222 return (pending - self->tp_pending) + 1;
4223}
4224
4225/** Mark message as no more pending */
4226int tport_release(tport_t *self,
4227 int pendd,
4228 msg_t *msg,
4229 msg_t *reply,
4230 tp_client_t *client,
4231 int still_pending)
4232{
4233 tport_pending_t *pending;
4234
4235 if (self == NULL((void*)0) || pendd <= 0 || pendd > (int)self->tp_plen)
4236 return su_seterrno(EINVAL22), -1;
4237
4238 pending = self->tp_pending + (pendd - 1);
4239
4240 if (pending->p_client != client ||
4241 pending->p_msg != msg) {
4242 SU_DEBUG_1(("%s(%p): %u %p by %p not pending\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 4244, "%s(%p): %u %p by %p not pending\n", __func__
, (void *)self, pendd, (void *)msg, (void *)client)) : (void)
0)
4243 __func__, (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 4244, "%s(%p): %u %p by %p not pending\n", __func__
, (void *)self, pendd, (void *)msg, (void *)client)) : (void)
0)
4244 pendd, (void *)msg, (void *)client))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 1 ? (_su_llog(tport_log, 1, "tport.c", (const
char *)__func__, 4244, "%s(%p): %u %p by %p not pending\n", __func__
, (void *)self, pendd, (void *)msg, (void *)client)) : (void)
0)
;
4245 return su_seterrno(EINVAL22), -1;
4246 }
4247
4248 SU_DEBUG_7(("%s(%p): %p by %p with %p%s\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4251, "%s(%p): %p by %p with %p%s\n", __func__
, (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending
? " (preliminary)" : "")) : (void)0)
4249 __func__, (void *)self,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4251, "%s(%p): %p by %p with %p%s\n", __func__
, (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending
? " (preliminary)" : "")) : (void)0)
4250 (void *)msg, (void *)client, (void *)reply,(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4251, "%s(%p): %p by %p with %p%s\n", __func__
, (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending
? " (preliminary)" : "")) : (void)0)
4251 still_pending ? " (preliminary)" : ""))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4251, "%s(%p): %p by %p with %p%s\n", __func__
, (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending
? " (preliminary)" : "")) : (void)0)
;
4252
4253 /* sigcomp can here associate request (msg) with response (reply) */
4254
4255 if (still_pending)
4256 return 0;
4257
4258 /* Just to make sure nobody uses stale data */
4259 memset(pending, 0, sizeof(*pending));
4260 pending->p_client = self->tp_released;
4261 self->tp_released = pending;
4262 self->tp_pused--;
4263 return 0;
4264}
4265
4266/** Report error to pending messages with destination */
4267int
4268tport_pending_error(tport_t *self, su_sockaddr_t const *dst, int error)
4269{
4270 unsigned i, reported, callbacks;
4271 tport_pending_t *pending;
4272 msg_t *msg;
4273 su_addrinfo_t const *ai;
4274
4275 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport.c", 4275, __extension__ __PRETTY_FUNCTION__
); }))
;
4276
4277 callbacks = 0;
4278 reported = ++self->tp_reported;
4279
4280 if (self->tp_pused == 0)
4281 return 0;
4282
4283 for (i = 0; i < self->tp_plen; i++) {
4284 pending = self->tp_pending + i;
4285
4286 if (!pending->p_callback)
4287 continue;
4288
4289 if (pending->p_reported == reported)
4290 continue;
4291
4292 msg = pending->p_msg;
4293
4294 if (dst && msg) {
4295 ai = msg_addrinfo(msg);
4296
4297 if (su_cmp_sockaddr(dst, (su_sockaddr_t *)ai->ai_addr) != 0)
4298 continue;
4299 }
4300
4301 msg_set_errno(msg, error);
4302
4303 pending->p_reported = reported;
4304
4305 pending->p_callback(self->TP_STACKtp_master->mr_stack, pending->p_client, self, msg, error);
4306
4307 callbacks++;
4308 }
4309
4310 return callbacks;
4311}
4312
4313
4314/** Report error via pending message */
4315int
4316tport_pending_errmsg(tport_t *self, msg_t *msg, int error)
4317{
4318 unsigned i, reported, callbacks;
4319 tport_pending_t *pending;
4320
4321 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport.c", 4321, __extension__ __PRETTY_FUNCTION__
); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport.c", 4321, __extension__ __PRETTY_FUNCTION__
); }))
;
4322
4323 callbacks = 0;
4324 reported = ++self->tp_reported;
4325
4326 msg_set_errno(msg, error);
4327
4328 if (self->tp_pused == 0)
4329 return 0;
4330
4331 for (i = 0; i < self->tp_plen; i++) {
4332 pending = self->tp_pending + i;
4333
4334 if (!pending->p_client ||
4335 pending->p_msg != msg ||
4336 pending->p_reported == reported)
4337 continue;
4338
4339 pending->p_reported = reported;
4340
4341 pending->p_callback(self->TP_STACKtp_master->mr_stack, pending->p_client, self, msg, error);
4342
4343 callbacks++;
4344 }
4345
4346 return callbacks;
4347}
4348
4349
4350/** Set transport magic. */
4351void tport_set_magic(tport_t *self, tp_magic_t *magic)
4352{
4353 self->tp_magic = magic;
4354}
4355
4356/** Get transport magic. */
4357tp_magic_t *tport_magic(tport_t const *self)
4358{
4359 return self ? self->tp_magic : NULL((void*)0);
4360}
4361
4362/** Get primary transport (or self, if primary) */
4363tport_t *tport_parent(tport_t const *self)
4364{
4365 return self ? self->tp_pri->pri_primary : NULL((void*)0);
4366}
4367
4368/** Get list of primary transports */
4369tport_t *tport_primaries(tport_t const *self)
4370{
4371 if (self)
4372 return self->tp_master->mr_primaries->pri_primary;
4373 else
4374 return NULL((void*)0);
4375}
4376
4377/** Get next transport */
4378tport_t *tport_next(tport_t const *self)
4379{
4380 if (self == NULL((void*)0))
4381 return NULL((void*)0);
4382 else if (tport_is_master(self))
4383 return ((tport_master_t *)self)->mr_primaries->pri_primary;
4384
4385 else if (tport_is_primary(self))
4386 return ((tport_primary_t *)self)->pri_next->pri_primary;
4387 else
4388 return tprb_succ(self);
4389}
4390
4391/** Get secondary transports. */
4392tport_t *tport_secondary(tport_t const *self)
4393{
4394 if (tport_is_primary(self))
4395 return self->tp_pri->pri_open;
4396 else
4397 return NULL((void*)0);
4398}
4399
4400#if 0
4401void tport_hints(tport_t const *self, su_addrinfo_t *hints)
4402{
4403 hints->ai_protocol = self->tp_addrinfo->ai_protocol;
4404 hints->ai_socktype = self->tp_addrinfo->ai_socktype;
4405}
4406#endif
4407
4408/** Get transport address list. */
4409su_addrinfo_t const *tport_get_address(tport_t const *self)
4410{
4411 return self ? self->tp_addrinfo : NULL((void*)0);
4412}
4413
4414/** Get transport name. */
4415tp_name_t const *tport_name(tport_t const *self)
4416{
4417 return self->tp_name;
4418}
4419
4420/** Get transport identifier. */
4421char const *tport_ident(tport_t const *self)
4422{
4423 return self ? self->tp_identtp_name->tpn_ident : NULL((void*)0);
4424}
4425
4426/** Get transport by protocol name. */
4427tport_t *tport_by_protocol(tport_t const *self, char const *proto)
4428{
4429 if (proto && strcmp(proto, tpn_any) != 0) {
4430 for (; self; self = tport_next(self))
4431 if (su_casematch(proto, self->tp_protonametp_name->tpn_proto))
4432 break;
4433 }
4434
4435 return (tport_t *)self;
4436}
4437
4438/** Get transport by protocol name. */
4439tport_t *tport_primary_by_name(tport_t const *tp, tp_name_t const *tpn)
4440{
4441 char const *ident = tpn->tpn_ident;
4442 char const *proto = tpn->tpn_proto;
4443 char const *comp = tpn->tpn_comp;
4444 int family = 0;
4445
4446 tport_primary_t const *self, *nocomp = NULL((void*)0);
4447
4448 self = tp ? tp->tp_master->mr_primaries : NULL((void*)0);
4449
4450 if (ident && strcmp(ident, tpn_any) == 0)
4451 ident = NULL((void*)0);
4452
4453 if (tpn->tpn_host == NULL((void*)0))
4454 family = 0;
4455#if SU_HAVE_IN61
4456 else if (host_is_ip6_address(tpn->tpn_host))
4457 family = AF_INET610;
4458#endif
4459 else if (host_is_ip4_address(tpn->tpn_host))
4460 family = AF_INET2;
4461 else
4462 family = 0;
4463
4464 if (proto && strcmp(proto, tpn_any) == 0)
4465 proto = NULL((void*)0);
4466
4467 if (!ident && !proto && !family && !comp)
4468 return (tport_t *)self; /* Anything goes */
4469
4470 comp = tport_canonize_comp(comp);
4471
4472 for (; self; self = self->pri_next) {
4473 tp = self->pri_primary;
4474
4475 if (ident && strcmp(ident, tp->tp_identtp_name->tpn_ident))
4476 continue;
4477 if (family) {
4478 if (family == AF_INET2 && !tport_has_ip4(tp))
4479 continue;
4480#if SU_HAVE_IN61
4481 if (family == AF_INET610 && !tport_has_ip6(tp))
4482 continue;
4483#endif
4484 }
4485 if (proto && !su_casematch(proto, tp->tp_protonametp_name->tpn_proto))
4486 continue;
4487
4488 if (comp && comp != tp->tp_name->tpn_comp) {
4489 if (tp->tp_name->tpn_comp == NULL((void*)0) && nocomp == NULL((void*)0))
4490 nocomp = self;
4491 continue;
4492 }
4493
4494 break;
4495 }
4496
4497 if (self)
4498 return (tport_t *)self;
4499 else
4500 return (tport_t *)nocomp;
4501}
4502
4503
4504/** Get transport by name. */
4505tport_t *tport_by_name(tport_t const *self, tp_name_t const *tpn)
4506{
4507 tport_t const *sub, *next;
4508 char const *canon, *host, *port, *comp;
4509#if SU_HAVE_IN61
4510 char *end, ipaddr[TPORT_HOSTPORTSIZE(55)];
4511#endif
4512
4513 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport.c", 4513, __extension__ __PRETTY_FUNCTION__
); }))
; assert(tpn)((void) sizeof ((tpn) ? 1 : 0), __extension__ ({ if (tpn) ; else
__assert_fail ("tpn", "tport.c", 4513, __extension__ __PRETTY_FUNCTION__
); }))
;
4514
4515 assert(tpn->tpn_proto)((void) sizeof ((tpn->tpn_proto) ? 1 : 0), __extension__ (
{ if (tpn->tpn_proto) ; else __assert_fail ("tpn->tpn_proto"
, "tport.c", 4515, __extension__ __PRETTY_FUNCTION__); }))
; assert(tpn->tpn_host)((void) sizeof ((tpn->tpn_host) ? 1 : 0), __extension__ ({
if (tpn->tpn_host) ; else __assert_fail ("tpn->tpn_host"
, "tport.c", 4515, __extension__ __PRETTY_FUNCTION__); }))
; assert(tpn->tpn_port)((void) sizeof ((tpn->tpn_port) ? 1 : 0), __extension__ ({
if (tpn->tpn_port) ; else __assert_fail ("tpn->tpn_port"
, "tport.c", 4515, __extension__ __PRETTY_FUNCTION__); }))
;
4516 assert(tpn->tpn_canon)((void) sizeof ((tpn->tpn_canon) ? 1 : 0), __extension__ (
{ if (tpn->tpn_canon) ; else __assert_fail ("tpn->tpn_canon"
, "tport.c", 4516, __extension__ __PRETTY_FUNCTION__); }))
;
4517
4518 if (!tport_is_primary(self))
4519 self = tport_primary_by_name(self, tpn);
4520
4521 host = strcmp(tpn->tpn_host, tpn_any) ? tpn->tpn_host : NULL((void*)0);
4522 port = strcmp(tpn->tpn_port, tpn_any) ? tpn->tpn_port : NULL((void*)0);
4523 canon = tpn->tpn_canon;
4524 comp = tport_canonize_comp(tpn->tpn_comp);
4525
4526 if (self && host && port) {
4527 int resolved = 0, cmp;
4528 socklen_t sulen;
4529 su_sockaddr_t su[1];
4530
4531 sub = self->tp_pri->pri_open;
4532
4533 memset(su, 0, sizeof su);
4534
4535#if SU_HAVE_IN61
4536 if (host_is_ip6_reference(host)) {
4537 /* Remove [] around IPv6 address */
4538 host = strncpy(ipaddr, host + 1, sizeof(ipaddr) - 1);
4539 ipaddr[sizeof(ipaddr) - 1] = '\0';
4540 if ((end = strchr(host, ']')))
4541 *end = 0;
4542 su->su_lensu_array[0] = sulen = (socklen_t) sizeof (struct sockaddr_in6);
4543 su->su_familysu_sa.sa_family = AF_INET610;
4544 }
4545 else if (host_is_ip6_address(host)) {
4546 su->su_lensu_array[0] = sulen = (socklen_t) sizeof (struct sockaddr_in6);
4547 su->su_familysu_sa.sa_family = AF_INET610;
4548 }
4549 else
4550#endif
4551 {
4552 su->su_lensu_array[0] = sulen = (socklen_t) sizeof (struct sockaddr_in);
4553 su->su_familysu_sa.sa_family = AF_INET2;
4554 }
4555
4556 su->su_portsu_sin.sin_port = htons(strtoul(port, NULL((void*)0), 10));
4557
4558 if (su_inet_ptoninet_pton(su->su_familysu_sa.sa_family, host, SU_ADDR(su)((su)->su_sa.sa_family == 2 ? (void *)&(su)->su_sin
.sin_addr : ((su)->su_sa.sa_family == 10 ? (void *)&(su
)->su_sin6.sin6_addr : (void *)&(su)->su_sa.sa_data
))
) > 0) {
4559 resolved = 1;
4560 next = NULL((void*)0);
4561
4562 /* Depth-first search */
4563 while (sub) {
4564 cmp = (int)((size_t)sub->tp_addrlentp_addrinfo->ai_addrlen - (size_t)sulen);
4565
4566 if (cmp == 0)
4567 cmp = memcmp(sub->tp_addr, su, sulen);
4568
4569 if (cmp == 0) {
4570 if (sub->tp_left) {
4571 next = sub;
4572 sub = sub->tp_left;
4573 continue;
4574 }
4575 break;
4576 }
4577 else if (next) {
4578 sub = next;
4579 break;
4580 }
4581 else if (cmp > 0) {
4582 sub = sub->tp_left;
4583 continue;
4584 }
4585 else /* if (cmp < 0) */ {
4586 sub = sub->tp_right;
4587 continue;
4588 }
4589 }
4590 }
4591 else {
4592 SU_DEBUG_7(("tport(%p): EXPENSIVE unresolved " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4593, "tport(%p): EXPENSIVE unresolved " "%s/%s:%s%s%s%s%s"
"\n", (void *)self, (tpn)->tpn_proto, (tpn)->tpn_host,
(tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
4593 (void *)self, TPN_ARGS(tpn)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4593, "tport(%p): EXPENSIVE unresolved " "%s/%s:%s%s%s%s%s"
"\n", (void *)self, (tpn)->tpn_proto, (tpn)->tpn_host,
(tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
;
4594
4595 sub = tprb_first(sub);
4596 }
4597
4598 for (; sub; sub = tprb_succ(sub)) {
4599 if (!sub->tp_reusable)
4600 continue;
4601 if (!tport_is_registered(sub))
4602 continue;
4603 if (tport_is_shutdown(sub))
4604 continue;
4605
4606 if (comp != sub->tp_name->tpn_comp)
4607 continue;
4608
4609 if (resolved) {
4610 if ((socklen_t)sub->tp_addrlentp_addrinfo->ai_addrlen != sulen ||
4611 memcmp(sub->tp_addr, su, sulen)) {
4612 SU_DEBUG_7(("tport(%p): not found by name " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4613, "tport(%p): not found by name " "%s/%s:%s%s%s%s%s"
"\n", (void *)self, (tpn)->tpn_proto, (tpn)->tpn_host,
(tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
4613 (void *)self, TPN_ARGS(tpn)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4613, "tport(%p): not found by name " "%s/%s:%s%s%s%s%s"
"\n", (void *)self, (tpn)->tpn_proto, (tpn)->tpn_host,
(tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" : "", (tpn
)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->tpn_ident
? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident : ""))
: (void)0)
;
4614 break;
4615 }
4616 SU_DEBUG_7(("tport(%p): found %p by name " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4617, "tport(%p): found %p by name " "%s/%s:%s%s%s%s%s"
"\n", (void *)self, (void *)sub, (tpn)->tpn_proto, (tpn)->
tpn_host, (tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" :
"", (tpn)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->
tpn_ident ? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident
: "")) : (void)0)
4617 (void *)self, (void *)sub, TPN_ARGS(tpn)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4617, "tport(%p): found %p by name " "%s/%s:%s%s%s%s%s"
"\n", (void *)self, (void *)sub, (tpn)->tpn_proto, (tpn)->
tpn_host, (tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" :
"", (tpn)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->
tpn_ident ? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident
: "")) : (void)0)
;
4618 }
4619 else if (!su_casematch(port, sub->tp_porttp_name->tpn_port))
4620 continue;
4621 else if (!su_casematch(canon, sub->tp_canontp_name->tpn_canon) &&
4622 !su_casematch(host, sub->tp_hosttp_name->tpn_host))
4623 continue;
4624
4625 return (tport_t *)sub;
4626 }
4627 }
4628
4629 return (tport_t *)self;
4630}
4631
4632/** Get transport from primary by addrinfo. */
4633tport_t *tport_by_addrinfo(tport_primary_t const *pri,
4634 su_addrinfo_t const *ai,
4635 tp_name_t const *tpn)
4636{
4637 tport_t const *sub, *maybe;
4638 struct sockaddr const *sa;
4639 int cmp;
4640 char const *comp;
4641
4642 assert(pri)((void) sizeof ((pri) ? 1 : 0), __extension__ ({ if (pri) ; else
__assert_fail ("pri", "tport.c", 4642, __extension__ __PRETTY_FUNCTION__
); }))
; assert(ai)((void) sizeof ((ai) ? 1 : 0), __extension__ ({ if (ai) ; else
__assert_fail ("ai", "tport.c", 4642, __extension__ __PRETTY_FUNCTION__
); }))
;
4643
4644 sa = ai->ai_addr;
4645
4646 sub = pri->pri_open, maybe = NULL((void*)0);
4647
4648 comp = tport_canonize_comp(tpn->tpn_comp);
4649
4650 /* Find leftmost (prevmost) matching tport */
4651 while (sub) {
4652 cmp = (int)(sub->tp_addrlentp_addrinfo->ai_addrlen - ai->ai_addrlen);
4653 if (cmp == 0)
4654 cmp = memcmp(sub->tp_addr, sa, ai->ai_addrlen);
4655
4656 if (cmp == 0) {
4657 if (sub->tp_left) {
4658 maybe = sub;
4659 sub = sub->tp_left;
4660 continue;
4661 }
4662 break;
4663 }
4664 else if (maybe) {
4665 sub = maybe;
4666 break;
4667 }
4668 else if (cmp > 0) {
4669 sub = sub->tp_left;
4670 continue;
4671 }
4672 else /* if (cmp < 0) */ {
4673 sub = sub->tp_right;
4674 continue;
4675 }
4676 }
4677
4678 for (; sub; sub = tprb_succ(sub)) {
4679 if (!sub->tp_reusable)
4680 continue;
4681 if (!tport_is_registered(sub))
4682 continue;
4683 if (tport_is_shutdown(sub))
4684 continue;
4685
4686 if (tport_has_tls(sub) && !su_casematch(tpn->tpn_canon, sub->tp_name->tpn_canon)) {
4687 if (!tport_is_verified(sub))
4688 continue;
4689 if (!tport_subject_search(tpn->tpn_canon, sub->tp_subjects))
4690 continue;
4691 }
4692
4693 if (comp != sub->tp_name->tpn_comp)
4694 continue;
4695
4696 if (sub->tp_addrlentp_addrinfo->ai_addrlen != ai->ai_addrlen
4697 || memcmp(sub->tp_addr, sa, ai->ai_addrlen)) {
4698 sub = NULL((void*)0);
4699 break;
4700 }
4701 break;
4702 }
4703
4704 if (sub)
4705 SU_DEBUG_7(("%s(%p): found %p by name " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4706, "%s(%p): found %p by name " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)pri, (void *)sub, (tpn)->tpn_proto
, (tpn)->tpn_host, (tpn)->tpn_port, (tpn)->tpn_comp ?
";comp=" : "", (tpn)->tpn_comp ? (tpn)->tpn_comp : "",
(tpn)->tpn_ident ? "/" : "", (tpn)->tpn_ident ? (tpn)->
tpn_ident : "")) : (void)0)
4706 __func__, (void *)pri, (void *)sub, TPN_ARGS(tpn)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4706, "%s(%p): found %p by name " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)pri, (void *)sub, (tpn)->tpn_proto
, (tpn)->tpn_host, (tpn)->tpn_port, (tpn)->tpn_comp ?
";comp=" : "", (tpn)->tpn_comp ? (tpn)->tpn_comp : "",
(tpn)->tpn_ident ? "/" : "", (tpn)->tpn_ident ? (tpn)->
tpn_ident : "")) : (void)0)
;
4707 else
4708 SU_DEBUG_7(("%s(%p): not found by name " TPN_FORMAT "\n",(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4709, "%s(%p): not found by name " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)pri, (tpn)->tpn_proto, (tpn)->
tpn_host, (tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" :
"", (tpn)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->
tpn_ident ? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident
: "")) : (void)0)
4709 __func__, (void *)pri, TPN_ARGS(tpn)))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport.c", (const
char *)__func__, 4709, "%s(%p): not found by name " "%s/%s:%s%s%s%s%s"
"\n", __func__, (void *)pri, (tpn)->tpn_proto, (tpn)->
tpn_host, (tpn)->tpn_port, (tpn)->tpn_comp ? ";comp=" :
"", (tpn)->tpn_comp ? (tpn)->tpn_comp : "", (tpn)->
tpn_ident ? "/" : "", (tpn)->tpn_ident ? (tpn)->tpn_ident
: "")) : (void)0)
;
4710
4711 return (tport_t *)sub;
4712}
4713
4714
4715/** Get transport name from URL. */
4716int tport_name_by_url(su_home_t *home,
4717 tp_name_t *tpn,
4718 url_string_t const *us)
4719{
4720 size_t n;
4721 url_t url[1];
4722 char *b;
4723
4724 n = url_xtra(us->us_url);
4725 b = su_alloc(home, n);
4726
4727 if (b == NULL((void*)0) || url_dup(b, n, url, us->us_url) < 0) {
4728 su_free(home, b);
4729 return -1;
4730 }
4731
4732 tpn->tpn_proto = url_tport_default((enum url_type_e)url->url_type);
4733 tpn->tpn_canon = url->url_host;
4734 tpn->tpn_host = url->url_host;
4735 tpn->tpn_port = url_port(url);
4736
4737 if (tpn->tpn_host == NULL((void*)0) || tpn->tpn_host[0] == '\0' ||
4738 tpn->tpn_port == NULL((void*)0) || tpn->tpn_port[0] == '\0') {
4739 su_free(home, b);
4740 return -1;
4741 }
4742
4743 if (url->url_params) {
4744 for (b = (char *)url->url_params; b[0]; b += n) {
4745 n = strcspn(b, ";");
4746
4747 if (n > 10 && su_casenmatch(b, "transport=", 10))
4748 tpn->tpn_proto = b + 10;
4749 else if (n > 6 && su_casenmatch(b, "maddr=", 6))
4750 tpn->tpn_host = b + 6;
4751
4752 if (b[n])
4753 b[n++] = '\0';
4754 }
4755 }
4756
4757 return 0;
4758}
4759
4760/** Check if transport named is already resolved */
4761int tport_name_is_resolved(tp_name_t const *tpn)
4762{
4763 if (!tpn->tpn_host)
4764 return 0;
4765
4766 return host_is_ip_address(tpn->tpn_host);
4767}
4768
4769/** Duplicate name.
4770 *
4771 * The tport_name_dup() function copies strings belonging to the transport
4772 * name. It returns the copied strings via the @a dst transport name
4773 * structure. The memory block required for copies is allocated from the
4774 * memory @a home. Please note that only one memory block is allocated, so
4775 * the memory can be reclainmed only by deinitializing the memory home
4776 * itself.
4777 *
4778 * @retval 0 when successful
4779 * @retval -1 upon an error
4780 */
4781int tport_name_dup(su_home_t *home,
4782 tp_name_t *dst,
4783 tp_name_t const *src)
4784{
4785 size_t n_proto, n_host, n_port, n_canon, n_comp = 0;
4786 char *s;
4787
4788 if (!src->tpn_proto || !src->tpn_host || !src->tpn_port || !src->tpn_canon)
4789 return -1;
4790
4791 if (strcmp(src->tpn_proto, tpn_any))
4792 n_proto = strlen(src->tpn_proto) + 1;
4793 else
4794 n_proto = 0;
4795
4796 n_host = strlen(src->tpn_host) + 1;
4797
4798 n_port = strlen(src->tpn_port) + 1;
4799
4800 if (src->tpn_comp != NULL((void*)0))
4801 n_comp = strlen(src->tpn_comp) + 1;
4802
4803 if (src->tpn_canon != src->tpn_host &&
4804 strcmp(src->tpn_canon, src->tpn_host))
4805 n_canon = strlen(src->tpn_canon) + 1;
4806 else
4807 n_canon = 0;
4808
4809 s = su_alloc(home, n_proto + n_canon + n_host + n_port + n_comp);
4810 if (s == NULL((void*)0))
4811 return -1;
4812
4813 if (n_proto)
4814 dst->tpn_proto = memcpy(s, src->tpn_proto, n_proto), s += n_proto;
4815 else
4816 dst->tpn_proto = tpn_any;
4817
4818 dst->tpn_host = memcpy(s, src->tpn_host, n_host), s += n_host;
4819 dst->tpn_port = memcpy(s, src->tpn_port, n_port), s += n_port;
4820
4821 if (n_canon)
4822 dst->tpn_canon = memcpy(s, src->tpn_canon, n_canon), s += n_canon;
4823 else
4824 dst->tpn_canon = dst->tpn_host;
4825
4826 if (n_comp)
4827 dst->tpn_comp = memcpy(s, src->tpn_comp, n_comp), s += n_comp;
Although the value stored to 's' is used in the enclosing expression, the value is never actually read from 's'
4828 else
4829 dst->tpn_comp = NULL((void*)0);
4830
4831 return 0;
4832}
4833
4834/** Convert a sockaddr structure into printable form. */
4835char *tport_hostport(char buf[], isize_t bufsize,
4836 su_sockaddr_t const *su,
4837 int with_port_and_brackets)
4838{
4839 char *b = buf;
4840 size_t n;
4841
4842#if SU_HAVE_IN61
4843 if (with_port_and_brackets > 1 || su->su_familysu_sa.sa_family == AF_INET610) {
4844 *b++ = '['; bufsize--;
4845 }
4846#endif
4847
4848 if (su_inet_ntopinet_ntop(su->su_familysu_sa.sa_family, SU_ADDR(su)((su)->su_sa.sa_family == 2 ? (void *)&(su)->su_sin
.sin_addr : ((su)->su_sa.sa_family == 10 ? (void *)&(su
)->su_sin6.sin6_addr : (void *)&(su)->su_sa.sa_data
))
, b, bufsize) == NULL((void*)0))
4849 return NULL((void*)0);
4850 n = strlen(b);
4851 if (bufsize < n + 2)
4852 return NULL((void*)0);
4853
4854 bufsize -= n; b += n;
4855
4856#if SU_HAVE_IN61
4857 if (with_port_and_brackets > 1 || su->su_familysu_sa.sa_family == AF_INET610) {
4858 *b++ = ']'; bufsize--;
4859 }
4860 if (with_port_and_brackets) {
4861 unsigned short port = ntohs(su->su_portsu_sin.sin_port);
4862 if (port != 0) {
4863 n = snprintf(b, bufsize, ":%u", port);
4864 if (n <= 0)
4865 return NULL((void*)0);
4866 b += n;
4867 if (bufsize > n)
4868 bufsize -= n;
4869 else
4870 bufsize = 0;
4871 }
4872 }
4873#endif
4874
4875 if (bufsize)
4876 *b++ = 0;
4877
4878 return buf;
4879}
4880
4881/** @internal Update receive statistics. */
4882void tport_recv_bytes(tport_t *self, ssize_t bytes, ssize_t on_line)
4883{
4884 self->tp_stats.recv_bytes += bytes;
4885 self->tp_stats.recv_on_line += on_line;
4886
4887 if (self != self->tp_pri->pri_primary) {
4888 self = self->tp_pri->pri_primary;
4889 self->tp_stats.recv_bytes += bytes;
4890 self->tp_stats.recv_on_line += on_line;
4891 }
4892 self = self->tp_master->mr_master;
4893 self->tp_stats.recv_bytes += bytes;
4894 self->tp_stats.recv_on_line += on_line;
4895}
4896
4897/** @internal Update message-based receive statistics. */
4898void tport_recv_message(tport_t *self, msg_t *msg, int error)
4899{
4900 error = error != 0;
4901
4902 self->tp_stats.recv_msgs++;
4903 self->tp_stats.recv_errors += error;
4904
4905 if (self != self->tp_pri->pri_primary) {
4906 self = self->tp_pri->pri_primary;
4907 self->tp_stats.recv_msgs++;
4908 self->tp_stats.recv_errors += error;
4909 }
4910
4911 self = self->tp_master->mr_master;
4912
4913 self->tp_stats.recv_msgs++;
4914 self->tp_stats.recv_errors += error;
4915}
4916
4917/** @internal Update send statistics. */
4918void tport_sent_bytes(tport_t *self, ssize_t bytes, ssize_t on_line)
4919{
4920 self->tp_stats.sent_bytes += bytes;
4921 self->tp_stats.sent_on_line += on_line;
4922
4923 if (self != self->tp_pri->pri_primary) {
4924 self = self->tp_pri->pri_primary;
4925 self->tp_stats.sent_bytes += bytes;
4926 self->tp_stats.sent_on_line += on_line;
4927 }
4928
4929 self = self->tp_master->mr_master;
4930 self->tp_stats.sent_bytes += bytes;
4931 self->tp_stats.sent_on_line += on_line;
4932}
4933
4934/** @internal Update message-based send statistics. */
4935void tport_sent_message(tport_t *self, msg_t *msg, int error)
4936{
4937 self->tp_slogged = NULL((void*)0);
4938
4939 error = error != 0;
4940
4941 self->tp_stats.sent_msgs++;
4942 self->tp_stats.sent_errors += error;
4943
4944 if (self != self->tp_pri->pri_primary) {
4945 self = self->tp_pri->pri_primary;
4946 self->tp_stats.sent_msgs++;
4947 self->tp_stats.sent_errors += error;
4948 }
4949
4950 self = self->tp_master->mr_master;
4951
4952 self->tp_stats.sent_msgs++;
4953 self->tp_stats.sent_errors += error;
4954
4955}