Bug Summary

File:tport/tport.c
Warning:line 2643, column 5
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -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-eagerly-assume -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 -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/lib/llvm-7/lib/clang/7.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-7/lib/clang/7.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 -fmessage-length 0 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -o /drone/src/scan-build/2021-08-26-202507-364-1 -x c tport.c -faddrsig
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))
1
Assuming the condition is false
2
Taking false branch
2614 tport_error_event(pri->pri_primary);
2615
2616 if (!(events & SU_WAIT_ACCEPT(0x001)))
3
Assuming the condition is false
4
Taking false branch
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) {
5
Assuming 's' is >= 0
6
Taking false branch
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)) {
7
Taking false branch
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)
;
8
Within the expansion of the macro 'SU_CANONIZE_SOCKADDR':
a
The left operand of '==' is a garbage value
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;
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}