Bug Summary

File:libs/sofia-sip/libsofia-sip-ua/tport/tport.c
Location:line 1658, column 26
Description:Access to field 'ai_addr' results in a dereference of a null pointer (loaded from variable 'res')

Annotated Source Code

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);
((c) ? (void) (0) : __assert_fail ("c", "tport.c", 128, __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 ((((dad)->tp_right) == x) ? (void) (0) : __assert_fail
("((dad)->tp_right) == x", "tport.c", 128, __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); ((c) ? (void) (0) :
__assert_fail ("c", "tport.c", 128, __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
((((dad)->tp_left) == x) ? (void) (0) : __assert_fail ("((dad)->tp_left) == x"
, "tport.c", 128, __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); ((granddad
) ? (void) (0) : __assert_fail ("granddad", "tport.c", 128, __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); ((dad) ? (void) (0) : __assert_fail
("dad", "tport.c", 128, __PRETTY_FUNCTION__)); granddad = ((
dad)->tp_dad); ((granddad) ? (void) (0) : __assert_fail ("granddad"
, "tport.c", 128, __PRETTY_FUNCTION__)); } ((dad)->tp_black
= 1); ((granddad)->tp_black = 0); tprb_right_rotate(top, granddad
); } } else { ((dad == ((granddad)->tp_right)) ? (void) (0
) : __assert_fail ("dad == ((granddad)->tp_right)", "tport.c"
, 128, __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); ((dad) ? (void) (0) : __assert_fail ("dad", "tport.c"
, 128, __PRETTY_FUNCTION__)); granddad = ((dad)->tp_dad); (
(granddad) ? (void) (0) : __assert_fail ("granddad", "tport.c"
, 128, __PRETTY_FUNCTION__)); } ((dad)->tp_black = 1); ((granddad
)->tp_black = 0); tprb_left_rotate(top, granddad); } } } (
(*top) ? (void) (0) : __assert_fail ("*top", "tport.c", 128, __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; } (((!(brother) || (brother)->tp_black == 1)) ?
(void) (0) : __assert_fail ("(!(brother) || (brother)->tp_black == 1)"
, "tport.c", 128, __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 { (
(node == ((dad)->tp_right)) ? (void) (0) : __assert_fail (
"node == ((dad)->tp_right)", "tport.c", 128, __PRETTY_FUNCTION__
)); brother = ((dad)->tp_left); if (!brother) { node = dad
; continue; } (((!(brother) || (brother)->tp_black == 1)) ?
(void) (0) : __assert_fail ("(!(brother) || (brother)->tp_black == 1)"
, "tport.c", 128, __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 ((
((((node)->tp_dad))->tp_right) == old) ? (void) (0) : __assert_fail
("((((node)->tp_dad))->tp_right) == old", "tport.c", 128
, __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 ((((((dad)->tp_dad))->tp_right) == dad) ? (void)
(0) : __assert_fail ("((((dad)->tp_dad))->tp_right) == dad"
, "tport.c", 128, __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 ((((((dad)->tp_dad))->tp_right) == node) ? (
void) (0) : __assert_fail ("((((dad)->tp_dad))->tp_right) == node"
, "tport.c", 128, __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);
((c) ? (void) (0) : __assert_fail ("c", "tport.c", 128, __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 ((((dad)->tp_right) == x) ? (void) (0) : __assert_fail
("((dad)->tp_right) == x", "tport.c", 128, __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); ((c) ? (void) (0) :
__assert_fail ("c", "tport.c", 128, __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
((((dad)->tp_left) == x) ? (void) (0) : __assert_fail ("((dad)->tp_left) == x"
, "tport.c", 128, __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); ((granddad
) ? (void) (0) : __assert_fail ("granddad", "tport.c", 128, __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); ((dad) ? (void) (0) : __assert_fail
("dad", "tport.c", 128, __PRETTY_FUNCTION__)); granddad = ((
dad)->tp_dad); ((granddad) ? (void) (0) : __assert_fail ("granddad"
, "tport.c", 128, __PRETTY_FUNCTION__)); } ((dad)->tp_black
= 1); ((granddad)->tp_black = 0); tprb_right_rotate(top, granddad
); } } else { ((dad == ((granddad)->tp_right)) ? (void) (0
) : __assert_fail ("dad == ((granddad)->tp_right)", "tport.c"
, 128, __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); ((dad) ? (void) (0) : __assert_fail ("dad", "tport.c"
, 128, __PRETTY_FUNCTION__)); granddad = ((dad)->tp_dad); (
(granddad) ? (void) (0) : __assert_fail ("granddad", "tport.c"
, 128, __PRETTY_FUNCTION__)); } ((dad)->tp_black = 1); ((granddad
)->tp_black = 0); tprb_left_rotate(top, granddad); } } } (
(*top) ? (void) (0) : __assert_fail ("*top", "tport.c", 128, __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; } (((!(brother) || (brother)->tp_black == 1)) ?
(void) (0) : __assert_fail ("(!(brother) || (brother)->tp_black == 1)"
, "tport.c", 128, __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 { (
(node == ((dad)->tp_right)) ? (void) (0) : __assert_fail (
"node == ((dad)->tp_right)", "tport.c", 128, __PRETTY_FUNCTION__
)); brother = ((dad)->tp_left); if (!brother) { node = dad
; continue; } (((!(brother) || (brother)->tp_black == 1)) ?
(void) (0) : __assert_fail ("(!(brother) || (brother)->tp_black == 1)"
, "tport.c", 128, __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 ((
((((node)->tp_dad))->tp_right) == old) ? (void) (0) : __assert_fail
("((((node)->tp_dad))->tp_right) == old", "tport.c", 128
, __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 ((((((dad)->tp_dad))->tp_right) == dad) ? (void)
(0) : __assert_fail ("((((dad)->tp_dad))->tp_right) == dad"
, "tport.c", 128, __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 ((((((dad)->tp_dad))->tp_right) == node) ? (
void) (0) : __assert_fail ("((((dad)->tp_dad))->tp_right) == node"
, "tport.c", 128, __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);
((c) ? (void) (0) : __assert_fail ("c", "tport.c", 128, __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 ((((dad)->tp_right) == x) ? (void) (0) : __assert_fail
("((dad)->tp_right) == x", "tport.c", 128, __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); ((c) ? (void) (0) :
__assert_fail ("c", "tport.c", 128, __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
((((dad)->tp_left) == x) ? (void) (0) : __assert_fail ("((dad)->tp_left) == x"
, "tport.c", 128, __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); ((granddad
) ? (void) (0) : __assert_fail ("granddad", "tport.c", 128, __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); ((dad) ? (void) (0) : __assert_fail
("dad", "tport.c", 128, __PRETTY_FUNCTION__)); granddad = ((
dad)->tp_dad); ((granddad) ? (void) (0) : __assert_fail ("granddad"
, "tport.c", 128, __PRETTY_FUNCTION__)); } ((dad)->tp_black
= 1); ((granddad)->tp_black = 0); tprb_right_rotate(top, granddad
); } } else { ((dad == ((granddad)->tp_right)) ? (void) (0
) : __assert_fail ("dad == ((granddad)->tp_right)", "tport.c"
, 128, __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); ((dad) ? (void) (0) : __assert_fail ("dad", "tport.c"
, 128, __PRETTY_FUNCTION__)); granddad = ((dad)->tp_dad); (
(granddad) ? (void) (0) : __assert_fail ("granddad", "tport.c"
, 128, __PRETTY_FUNCTION__)); } ((dad)->tp_black = 1); ((granddad
)->tp_black = 0); tprb_left_rotate(top, granddad); } } } (
(*top) ? (void) (0) : __assert_fail ("*top", "tport.c", 128, __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; } (((!(brother) || (brother)->tp_black == 1)) ?
(void) (0) : __assert_fail ("(!(brother) || (brother)->tp_black == 1)"
, "tport.c", 128, __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 { (
(node == ((dad)->tp_right)) ? (void) (0) : __assert_fail (
"node == ((dad)->tp_right)", "tport.c", 128, __PRETTY_FUNCTION__
)); brother = ((dad)->tp_left); if (!brother) { node = dad
; continue; } (((!(brother) || (brother)->tp_black == 1)) ?
(void) (0) : __assert_fail ("(!(brother) || (brother)->tp_black == 1)"
, "tport.c", 128, __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 ((
((((node)->tp_dad))->tp_right) == old) ? (void) (0) : __assert_fail
("((((node)->tp_dad))->tp_right) == old", "tport.c", 128
, __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 ((((((dad)->tp_dad))->tp_right) == dad) ? (void)
(0) : __assert_fail ("((((dad)->tp_dad))->tp_right) == dad"
, "tport.c", 128, __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 ((((((dad)->tp_dad))->tp_right) == node) ? (
void) (0) : __assert_fail ("((((dad)->tp_dad))->tp_right) == node"
, "tport.c", 128, __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);
((c) ? (void) (0) : __assert_fail ("c", "tport.c", 128, __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 ((((dad)->tp_right) == x) ? (void) (0) : __assert_fail
("((dad)->tp_right) == x", "tport.c", 128, __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); ((c) ? (void) (0) :
__assert_fail ("c", "tport.c", 128, __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
((((dad)->tp_left) == x) ? (void) (0) : __assert_fail ("((dad)->tp_left) == x"
, "tport.c", 128, __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); ((granddad
) ? (void) (0) : __assert_fail ("granddad", "tport.c", 128, __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); ((dad) ? (void) (0) : __assert_fail
("dad", "tport.c", 128, __PRETTY_FUNCTION__)); granddad = ((
dad)->tp_dad); ((granddad) ? (void) (0) : __assert_fail ("granddad"
, "tport.c", 128, __PRETTY_FUNCTION__)); } ((dad)->tp_black
= 1); ((granddad)->tp_black = 0); tprb_right_rotate(top, granddad
); } } else { ((dad == ((granddad)->tp_right)) ? (void) (0
) : __assert_fail ("dad == ((granddad)->tp_right)", "tport.c"
, 128, __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); ((dad) ? (void) (0) : __assert_fail ("dad", "tport.c"
, 128, __PRETTY_FUNCTION__)); granddad = ((dad)->tp_dad); (
(granddad) ? (void) (0) : __assert_fail ("granddad", "tport.c"
, 128, __PRETTY_FUNCTION__)); } ((dad)->tp_black = 1); ((granddad
)->tp_black = 0); tprb_left_rotate(top, granddad); } } } (
(*top) ? (void) (0) : __assert_fail ("*top", "tport.c", 128, __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; } (((!(brother) || (brother)->tp_black == 1)) ?
(void) (0) : __assert_fail ("(!(brother) || (brother)->tp_black == 1)"
, "tport.c", 128, __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 { (
(node == ((dad)->tp_right)) ? (void) (0) : __assert_fail (
"node == ((dad)->tp_right)", "tport.c", 128, __PRETTY_FUNCTION__
)); brother = ((dad)->tp_left); if (!brother) { node = dad
; continue; } (((!(brother) || (brother)->tp_black == 1)) ?
(void) (0) : __assert_fail ("(!(brother) || (brother)->tp_black == 1)"
, "tport.c", 128, __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 ((
((((node)->tp_dad))->tp_right) == old) ? (void) (0) : __assert_fail
("((((node)->tp_dad))->tp_right) == old", "tport.c", 128
, __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 ((((((dad)->tp_dad))->tp_right) == dad) ? (void)
(0) : __assert_fail ("((((dad)->tp_dad))->tp_right) == dad"
, "tport.c", 128, __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 ((((((dad)->tp_dad))->tp_right) == node) ? (
void) (0) : __assert_fail ("((((dad)->tp_dad))->tp_right) == node"
, "tport.c", 128, __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)((tp->tp_left == ((void*)0) || tp == tp->tp_left->tp_right
) ? (void) (0) : __assert_fail ("tp->tp_left == ((void*)0) || tp == tp->tp_left->tp_right"
, "tport.c", 142, __PRETTY_FUNCTION__))
;
143 assert(tp->tp_right == NULL || tp == tp->tp_right->tp_left)((tp->tp_right == ((void*)0) || tp == tp->tp_right->
tp_left) ? (void) (0) : __assert_fail ("tp->tp_right == ((void*)0) || tp == tp->tp_right->tp_left"
, "tport.c", 143, __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)((tp->tp_left == ((void*)0)) ? (void) (0) : __assert_fail (
"tp->tp_left == ((void*)0)", "tport.c", 150, __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))((tport_is_master(self)) ? (void) (0) : __assert_fail ("tport_is_master(self)"
, "tport.c", 560, __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)((vtable->vtp_pri_size >= sizeof *pri) ? (void) (0) : __assert_fail
("vtable->vtp_pri_size >= sizeof *pri", "tport.c", 600
, __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))((tport_is_primary(pri->pri_primary)) ? (void) (0) : __assert_fail
("tport_is_primary(pri->pri_primary)", "tport.c", 659, __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)((*prip) ? (void) (0) : __assert_fail ("*prip", "tport.c", 673
, __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] == (__extension__ ({ unsigned
int __v, __x = (0xffff); if (__builtin_constant_p (__x)) __v
= ((((__x) & 0xff000000) >> 24) | (((__x) & 0x00ff0000
) >> 8) | (((__x) & 0x0000ff00) << 8) | (((__x
) & 0x000000ff) << 24)); else __asm__ ("bswap %0" :
"=r" (__v) : "0" (__x)); __v; })); }))
||
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 && (__extension__
({ unsigned int __v, __x = (__a->__in6_u.__u6_addr32[3]);
if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; })) > 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 self->tp_index = i;
1060 self->tp_events = events;
1061
1062 tprb_append(&self->tp_pri->pri_open, self);
1063 return 0;
1064 }
1065
1066 su_wait_destroy(wait);
1067 return -1;
1068}
1069
1070/** Destroy a secondary transport. @internal */
1071void tport_zap_secondary(tport_t *self)
1072{
1073 tport_master_t *mr;
1074
1075 if (self == NULL((void*)0))
1076 return;
1077
1078 /* Remove from rbtree */
1079 if (!tport_is_closed(self))
1080 tprb_remove(&self->tp_pri->pri_open, self);
1081 else
1082 tplist_remove(&self->tp_pri->pri_closed, self);
1083
1084 if (self->tp_timer)
1085 su_timer_destroy(self->tp_timer), self->tp_timer = NULL((void*)0);
1086
1087 /* Do not deinit primary as secondary! */
1088 if (tport_is_secondary(self) &&
1089 self->tp_pri->pri_vtable->vtp_deinit_secondary)
1090 self->tp_pri->pri_vtable->vtp_deinit_secondary(self);
1091
1092 if (self->tp_msg) {
1093 msg_destroy(self->tp_msg), self->tp_msg = NULL((void*)0);
1094 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__, 1095, "%s(%p): zapped partially received message\n"
, __func__, (void *)self)) : (void)0)
1095 __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__, 1095, "%s(%p): zapped partially received message\n"
, __func__, (void *)self)) : (void)0)
;
1096 }
1097
1098 if (tport_has_queued(self)) {
1099 size_t n = 0, i, N = self->tp_params->tpp_qsize;
1100 for (i = self->tp_qhead; self->tp_queue[i]; i = (i + 1) % N) {
1101 msg_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL((void*)0);
1102 n++;
1103 }
1104 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__, 1105, "%s(%p): zapped %lu queued messages\n"
, __func__, (void *)self, (LU)n)) : (void)0)
1105 __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__, 1105, "%s(%p): zapped %lu queued messages\n"
, __func__, (void *)self, (LU)n)) : (void)0)
;
1106 }
1107
1108 if (self->tp_pused) {
1109 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__, 1110, "%s(%p): zapped while pending\n", __func__
, (void *)self)) : (void)0)
1110 __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__, 1110, "%s(%p): zapped while pending\n", __func__
, (void *)self)) : (void)0)
;
1111 }
1112
1113 mr = self->tp_master;
1114
1115#if HAVE_SOFIA_STUN
1116 tport_stun_server_remove_socket(self);
1117#endif
1118
1119 if (self->tp_index)
1120 su_root_deregister(mr->mr_root, self->tp_index);
1121 self->tp_index = 0;
1122 if (self->tp_socket != INVALID_SOCKET((su_socket_t)INVALID_SOCKET))
1123 su_close(self->tp_socket);
1124 self->tp_socket = INVALID_SOCKET((su_socket_t)INVALID_SOCKET);
1125
1126 su_home_zap(self->tp_home)su_home_unref((self->tp_home));
1127}
1128
1129/** Create a new reference to a transport object. */
1130tport_t *tport_ref(tport_t *tp)
1131{
1132 if (tp) {
1133 if (tp->tp_refs >= 0)
1134 tp->tp_refs++;
1135 else if (tp->tp_refs == -1)
1136 tp->tp_refs = 1;
1137 }
1138 return tp;
1139}
1140
1141/** Destroy reference to a transport object. */
1142void tport_unref(tport_t *tp)
1143{
1144 if (tp == NULL((void*)0) || tp->tp_refs <= 0)
1145 return;
1146 if (--tp->tp_refs > 0)
1147 return;
1148
1149 if (!tport_is_secondary(tp))
1150 return;
1151
1152 if (tp->tp_params->tpp_idle == 0)
1153 tport_close(tp);
1154
1155 tport_set_secondary_timer(tp);
1156}
1157
1158/** Create a new reference to transport object. */
1159tport_t *tport_incref(tport_t *tp)
1160{
1161 return tport_ref(tp);
1162}
1163
1164/** Destroy a transport reference. */
1165void tport_decref(tport_t **ttp)
1166{
1167 assert(ttp)((ttp) ? (void) (0) : __assert_fail ("ttp", "tport.c", 1167, __PRETTY_FUNCTION__
))
;
1168
1169 if (*ttp) {
1170 tport_unref(*ttp);
1171 *ttp = NULL((void*)0);
1172 }
1173}
1174
1175/** Get transport parameters.
1176 *
1177 * @param self pointer to a transport object
1178 * @param tag,value,... list of tags
1179 *
1180 * @TAGS
1181 * TPTAG_MTU_REF(), TPTAG_QUEUESIZE_REF(), TPTAG_IDLE_REF(),
1182 * TPTAG_TIMEOUT_REF(), TPTAG_KEEPALIVE_REF(), TPTAG_PINGPONG_REF(),
1183 * TPTAG_PONG2PING_REF(), TPTAG_DEBUG_DROP_REF(), TPTAG_THRPSIZE_REF(),
1184 * TPTAG_THRPRQSIZE_REF(), TPTAG_SIGCOMP_LIFETIME_REF(),
1185 * TPTAG_CONNECT_REF(), TPTAG_SDWN_ERROR_REF(), TPTAG_REUSE_REF(),
1186 * TPTAG_STUN_SERVER_REF(), TPTAG_PUBLIC_REF() and TPTAG_TOS_REF().
1187 */
1188int tport_get_params(tport_t const *self,
1189 tag_type_t tag, tag_value_t value, ...)
1190{
1191 ta_list ta;
1192 int n;
1193 tport_params_t const *tpp;
1194 int connect;
1195 tport_master_t *mr = self->tp_master;
1196
1197 if (self == NULL((void*)0))
1198 return su_seterrno(EINVAL22);
1199
1200 tpp = self->tp_params;
1201 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)
;
1202
1203 connect = tpp->tpp_conn_orient
1204 /* Only dgram primary is *not* connection-oriented */
1205 || !tport_is_primary(self) || !tport_is_dgram(self);
1206
1207 n = tl_tgets(ta_args(ta)(ta).tl,
1208 TPTAG_MTU((usize_t)tpp->tpp_mtu)tptag_mtu, tag_usize_v(((usize_t)tpp->tpp_mtu)),
1209 TPTAG_REUSE(self->tp_reusable)tptag_reuse, tag_bool_v((self->tp_reusable)),
1210 TPTAG_CONNECT(connect)tptag_connect, tag_bool_v((connect)),
1211 TPTAG_QUEUESIZE(tpp->tpp_qsize)tptag_queuesize, tag_uint_v((tpp->tpp_qsize)),
1212 TPTAG_IDLE(tpp->tpp_idle)tptag_idle, tag_uint_v((tpp->tpp_idle)),
1213 TPTAG_TIMEOUT(tpp->tpp_timeout)tptag_timeout, tag_uint_v((tpp->tpp_timeout)),
1214 TPTAG_SOCKET_KEEPALIVE(tpp->tpp_socket_keepalive)tptag_socket_keepalive, tag_uint_v((tpp->tpp_socket_keepalive
))
,
1215 TPTAG_KEEPALIVE(tpp->tpp_keepalive)tptag_keepalive, tag_uint_v((tpp->tpp_keepalive)),
1216 TPTAG_PINGPONG(tpp->tpp_pingpong)tptag_pingpong, tag_uint_v((tpp->tpp_pingpong)),
1217 TPTAG_PONG2PING(tpp->tpp_pong2ping)tptag_pong2ping, tag_bool_v((tpp->tpp_pong2ping)),
1218 TPTAG_SDWN_ERROR(tpp->tpp_sdwn_error)tptag_sdwn_error, tag_bool_v((tpp->tpp_sdwn_error)),
1219 TPTAG_DEBUG_DROP(tpp->tpp_drop)tptag_debug_drop, tag_uint_v((tpp->tpp_drop)),
1220 TPTAG_THRPSIZE(tpp->tpp_thrpsize)tptag_thrpsize, tag_uint_v((tpp->tpp_thrpsize)),
1221 TPTAG_THRPRQSIZE(tpp->tpp_thrprqsize)tptag_thrprqsize, tag_uint_v((tpp->tpp_thrprqsize)),
1222 TPTAG_SIGCOMP_LIFETIME(tpp->tpp_sigcomp_lifetime)tptag_sigcomp_lifetime, tag_uint_v((tpp->tpp_sigcomp_lifetime
))
,
1223 TPTAG_STUN_SERVER(tpp->tpp_stun_server)tptag_stun_server, tag_bool_v((tpp->tpp_stun_server)),
1224 TAG_IF(self->tp_pri,!(self->tp_pri) ? tag_skip : tptag_public, tag_int_v((self
->tp_pri ? self->tp_pri->pri_public : 0))
1225 TPTAG_PUBLIC(self->tp_pri ?!(self->tp_pri) ? tag_skip : tptag_public, tag_int_v((self
->tp_pri ? self->tp_pri->pri_public : 0))
1226 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))
,
1227 TPTAG_TOS(tpp->tpp_tos)tptag_tos, tag_int_v((tpp->tpp_tos)),
1228 TAG_IF((void *)self == (void *)mr,!((void *)self == (void *)mr) ? tag_skip : tptag_log, tag_bool_v
((mr->mr_log != 0))
1229 TPTAG_LOG(mr->mr_log != 0))!((void *)self == (void *)mr) ? tag_skip : tptag_log, tag_bool_v
((mr->mr_log != 0))
,
1230 TAG_IF((void *)self == (void *)mr,!((void *)self == (void *)mr) ? tag_skip : tptag_dump, tag_str_v
((mr->mr_dump))
1231 TPTAG_DUMP(mr->mr_dump))!((void *)self == (void *)mr) ? tag_skip : tptag_dump, tag_str_v
((mr->mr_dump))
,
1232 TAG_END()(tag_type_t)0, (tag_value_t)0);
1233
1234 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))
;
1235
1236 return n;
1237}
1238
1239/** Set transport parameters.
1240 *
1241 * @param self pointer to a transport object
1242 * @param tag,value,... list of tags
1243 *
1244 * @TAGS
1245 * TPTAG_MTU(), TPTAG_QUEUESIZE(), TPTAG_IDLE(), TPTAG_TIMEOUT(),
1246 * TPTAG_KEEPALIVE(), TPTAG_PINGPONG(), TPTAG_PONG2PING(),
1247 * TPTAG_DEBUG_DROP(), TPTAG_THRPSIZE(), TPTAG_THRPRQSIZE(),
1248 * TPTAG_SIGCOMP_LIFETIME(), TPTAG_CONNECT(), TPTAG_SDWN_ERROR(),
1249 * TPTAG_REUSE(), TPTAG_STUN_SERVER(), and TPTAG_TOS().
1250 */
1251int tport_set_params(tport_t *self,
1252 tag_type_t tag, tag_value_t value, ...)
1253{
1254 ta_list ta;
1255 int n, m = 0;
1256 tport_params_t tpp[1], *tpp0;
1257
1258 usize_t mtu;
1259 int connect, sdwn_error, reusable, stun_server, pong2ping;
1260
1261 if (self == NULL((void*)0))
1262 return su_seterrno(EINVAL22);
1263
1264 memcpy(tpp, tpp0 = self->tp_params, sizeof tpp);
1265
1266 mtu = tpp->tpp_mtu;
1267 connect = tpp->tpp_conn_orient;
1268 sdwn_error = tpp->tpp_sdwn_error;
1269 reusable = self->tp_reusable;
1270 stun_server = tpp->tpp_stun_server;
1271 pong2ping = tpp->tpp_pong2ping;
1272
1273 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)
;
1274
1275 n = tl_gets(ta_args(ta)(ta).tl,
1276 TPTAG_MTU_REF(mtu)tptag_mtu_ref, tag_usize_vr(&(mtu)),
1277 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))
,
1278 TPTAG_IDLE_REF(tpp->tpp_idle)tptag_idle_ref, tag_uint_vr(&(tpp->tpp_idle)),
1279 TPTAG_TIMEOUT_REF(tpp->tpp_timeout)tptag_timeout_ref, tag_uint_vr(&(tpp->tpp_timeout)),
1280 TPTAG_SOCKET_KEEPALIVE_REF(tpp->tpp_socket_keepalive)tptag_socket_keepalive_ref, tag_uint_vr(&(tpp->tpp_socket_keepalive
))
,
1281 TPTAG_KEEPALIVE_REF(tpp->tpp_keepalive)tptag_keepalive_ref, tag_uint_vr(&(tpp->tpp_keepalive)
)
,
1282 TPTAG_PINGPONG_REF(tpp->tpp_pingpong)tptag_pingpong_ref, tag_uint_vr(&(tpp->tpp_pingpong)),
1283 TPTAG_PONG2PING_REF(pong2ping)tptag_pong2ping_ref, tag_bool_vr(&(pong2ping)),
1284 TPTAG_DEBUG_DROP_REF(tpp->tpp_drop)tptag_debug_drop_ref, tag_uint_vr(&(tpp->tpp_drop)),
1285 TPTAG_THRPSIZE_REF(tpp->tpp_thrpsize)tptag_thrpsize_ref, tag_uint_vr(&(tpp->tpp_thrpsize)),
1286 TPTAG_THRPRQSIZE_REF(tpp->tpp_thrprqsize)tptag_thrprqsize_ref, tag_uint_vr(&(tpp->tpp_thrprqsize
))
,
1287 TPTAG_SIGCOMP_LIFETIME_REF(tpp->tpp_sigcomp_lifetime)tptag_sigcomp_lifetime_ref, tag_uint_vr(&(tpp->tpp_sigcomp_lifetime
))
,
1288 TPTAG_CONNECT_REF(connect)tptag_connect_ref, tag_bool_vr(&(connect)),
1289 TPTAG_SDWN_ERROR_REF(sdwn_error)tptag_sdwn_error_ref, tag_bool_vr(&(sdwn_error)),
1290 TPTAG_REUSE_REF(reusable)tptag_reuse_ref, tag_bool_vr(&(reusable)),
1291 TPTAG_STUN_SERVER_REF(stun_server)tptag_stun_server_ref, tag_bool_vr(&(stun_server)),
1292 TPTAG_TOS_REF(tpp->tpp_tos)tptag_tos_ref, tag_int_vr(&(tpp->tpp_tos)),
1293 TAG_END()(tag_type_t)0, (tag_value_t)0);
1294
1295 if (self == (tport_t *)self->tp_master)
1296 m = tport_open_log(self->tp_master, ta_args(ta)(ta).tl);
1297
1298 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))
;
1299
1300 if (n == 0)
1301 return m;
1302
1303 if (tpp->tpp_idle > 0 && tpp->tpp_idle < 100)
1304 tpp->tpp_idle = 100;
1305 if (tpp->tpp_timeout < 100)
1306 tpp->tpp_timeout = 100;
1307 if (tpp->tpp_drop > 1000)
1308 tpp->tpp_drop = 1000;
1309 if (tpp->tpp_thrprqsize > 0)
1310 tpp->tpp_thrprqsize = tpp0->tpp_thrprqsize;
1311 if (tpp->tpp_sigcomp_lifetime != 0 && tpp->tpp_sigcomp_lifetime < 30)
1312 tpp->tpp_sigcomp_lifetime = 30;
1313 if (tpp->tpp_qsize >= 1000)
1314 tpp->tpp_qsize = 1000;
1315
1316 if (mtu > UINT_MAX(2147483647 *2U +1U))
1317 mtu = UINT_MAX(2147483647 *2U +1U);
1318 tpp->tpp_mtu = (unsigned)mtu;
1319 /* Currently only primary UDP transport can *not* be connection oriented */
1320 tpp->tpp_conn_orient = connect;
1321 tpp->tpp_sdwn_error = sdwn_error;
1322 self->tp_reusable = reusable;
1323 tpp->tpp_stun_server = stun_server;
1324 tpp->tpp_pong2ping = pong2ping;
1325
1326 if (memcmp(tpp0, tpp, sizeof tpp) == 0)
1327 return n + m;
1328
1329 if (tport_is_secondary(self) &&
1330 self->tp_params == self->tp_pri->pri_primary->tp_params) {
1331 tpp0 = su_zalloc(self->tp_home, sizeof *tpp0); if (!tpp0) return -1;
1332 self->tp_params = tpp0;
1333 }
1334
1335 memcpy(tpp0, tpp, sizeof tpp);
1336
1337 if (tport_is_secondary(self))
1338 tport_set_secondary_timer(self);
1339
1340 return n + m;
1341}
1342
1343extern tport_vtable_t const tport_udp_vtable;
1344extern tport_vtable_t const tport_tcp_vtable;
1345extern tport_vtable_t const tport_tls_vtable;
1346extern tport_vtable_t const tport_ws_vtable;
1347extern tport_vtable_t const tport_wss_vtable;
1348extern tport_vtable_t const tport_sctp_vtable;
1349extern tport_vtable_t const tport_udp_client_vtable;
1350extern tport_vtable_t const tport_tcp_client_vtable;
1351extern tport_vtable_t const tport_sctp_client_vtable;
1352extern tport_vtable_t const tport_ws_client_vtable;
1353extern tport_vtable_t const tport_wss_client_vtable;
1354extern tport_vtable_t const tport_tls_client_vtable;
1355extern tport_vtable_t const tport_http_connect_vtable;
1356extern tport_vtable_t const tport_threadpool_vtable;
1357
1358#define TPORT_NUMBER_OF_TYPES64 64
1359
1360tport_vtable_t const *tport_vtables[TPORT_NUMBER_OF_TYPES64 + 1] =
1361{
1362#if HAVE_SOFIA_NTH1
1363 &tport_http_connect_vtable,
1364 &tport_ws_client_vtable,
1365 &tport_ws_vtable,
1366 &tport_wss_client_vtable,
1367 &tport_wss_vtable,
1368#endif
1369#if HAVE_TLS1
1370 &tport_tls_client_vtable,
1371 &tport_tls_vtable,
1372#endif
1373#if HAVE_SCTP /* SCTP is broken */
1374 &tport_sctp_client_vtable,
1375 &tport_sctp_vtable,
1376#endif
1377 &tport_tcp_client_vtable,
1378 &tport_tcp_vtable,
1379 &tport_udp_client_vtable,
1380 &tport_udp_vtable,
1381#if 0
1382 &tport_threadpool_vtable,
1383#endif
1384#if HAVE_SOFIA_STUN
1385 &tport_stun_vtable,
1386#endif
1387};
1388
1389/** Register new transport vtable */
1390int tport_register_type(tport_vtable_t const *vtp)
1391{
1392 int i;
1393
1394 for (i = TPORT_NUMBER_OF_TYPES64; i >= 0; i--) {
1395 if (tport_vtables[i] == NULL((void*)0)) {
1396 tport_vtables[i] = vtp;
1397 return 0;
1398 }
1399 }
1400
1401 su_seterrno(ENOMEM12);
1402 return -1;
1403}
1404
1405/**Get a vtable for given protocol */
1406tport_vtable_t const *tport_vtable_by_name(char const *protoname,
1407 enum tport_via public)
1408{
1409 int i;
1410
1411 for (i = TPORT_NUMBER_OF_TYPES64; i >= 0; i--) {
1412 tport_vtable_t const *vtable = tport_vtables[i];
1413
1414 if (vtable == NULL((void*)0))
1415 continue;
1416 if (vtable->vtp_public != public)
1417 continue;
1418 if (!su_casematch(protoname, vtable->vtp_name))
1419 continue;
1420
1421 assert(vtable->vtp_pri_size >= sizeof (tport_primary_t))((vtable->vtp_pri_size >= sizeof (tport_primary_t)) ? (
void) (0) : __assert_fail ("vtable->vtp_pri_size >= sizeof (tport_primary_t)"
, "tport.c", 1421, __PRETTY_FUNCTION__))
;
1422 assert(vtable->vtp_secondary_size >= sizeof (tport_t))((vtable->vtp_secondary_size >= sizeof (tport_t)) ? (void
) (0) : __assert_fail ("vtable->vtp_secondary_size >= sizeof (tport_t)"
, "tport.c", 1422, __PRETTY_FUNCTION__))
;
1423
1424 return vtable;
1425 }
1426
1427 return NULL((void*)0);
1428}
1429
1430#if 0
1431tport_set_f const *tport_set_methods[TPORT_NUMBER_OF_TYPES64 + 1] =
1432 {
1433 tport_server_bind_set,
1434 tport_client_bind_set,
1435 tport_threadpool_set,
1436#if HAVE_SOFIA_NTH1
1437 tport_http_connect_set,
1438#endif
1439#if HAVE_TLS1
1440 tport_tls_set,
1441#endif
1442 NULL((void*)0)
1443 };
1444
1445int tport_bind_set(tport_master_t *mr,
1446 tp_name_t const *tpn,
1447 char const * const transports[],
1448 tagi_t const *taglist,
1449 tport_set_t **return_set,
1450 int set_size)
1451{
1452 int i;
1453
1454 for (i = TPORT_NUMBER_OF_TYPES64; i >= 0; i--) {
1455 tport_set_f const *perhaps = tport_vtables[i];
1456 int result;
1457
1458 if (perhaps == NULL((void*)0))
1459 continue;
1460
1461 result = perhaps(mr, tpn, transports, taglist, return_set, set_size);
1462 if (result != 0)
1463 return result;
1464 }
1465
1466 return 0;
1467}
1468#endif
1469
1470/** Bind transport objects.
1471 *
1472 * @param self pointer to a transport object
1473 * @param tpn desired transport address
1474 * @param transports list of protocol names supported by stack
1475 * @param tag,value,... tagged argument list
1476 *
1477 * @TAGS
1478 * TPTAG_SERVER(), TPTAG_PUBLIC(), TPTAG_IDENT(), TPTAG_HTTP_CONNECT(),
1479 * TPTAG_CERTIFICATE(), TPTAG_TLS_VERSION(), TPTAG_TLS_VERIFY_POLICY, and
1480 * tags used with tport_set_params(), especially TPTAG_QUEUESIZE().
1481 */
1482int tport_tbind(tport_t *self,
1483 tp_name_t const *tpn,
1484 char const * const transports[],
1485 tag_type_t tag, tag_value_t value, ...)
1486{
1487 ta_list ta;
1488 int server = 1, retval, public = 0;
1489 tp_name_t mytpn[1];
1490 tport_master_t *mr;
1491 char const *http_connect = NULL((void*)0);
1492
1493 if (self == NULL((void*)0) || tport_is_secondary(self) ||
1494 tpn == NULL((void*)0) || transports == NULL((void*)0)) {
1495 su_seterrno(EINVAL22);
1496 return -1;
1497 }
1498
1499 *mytpn = *tpn;
1500
1501 if (mytpn->tpn_ident == NULL((void*)0))
1502 mytpn->tpn_ident = self->tp_identtp_name->tpn_ident;
1503
1504 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)
;
1505
1506 tl_gets(ta_args(ta)(ta).tl,
1507 TPTAG_SERVER_REF(server)tptag_server_ref, tag_bool_vr(&(server)),
1508 TPTAG_PUBLIC_REF(public)tptag_public_ref, tag_int_vr(&(public)),
1509 TPTAG_IDENT_REF(mytpn->tpn_ident)tptag_ident_ref, tag_str_vr(&(mytpn->tpn_ident)),
1510 TPTAG_HTTP_CONNECT_REF(http_connect)tptag_http_connect_ref, tag_str_vr(&(http_connect)),
1511 TAG_END()(tag_type_t)0, (tag_value_t)0);
1512
1513 mr = self->tp_master; assert(mr)((mr) ? (void) (0) : __assert_fail ("mr", "tport.c", 1513, __PRETTY_FUNCTION__
))
;
1514
1515 if (http_connect && public == 0)
1516 public = tport_type_connect;
1517
1518 if (public && public != tport_type_stun)
1519 server = 0;
1520
1521 if (server)
1522 retval = tport_bind_server(mr, mytpn, transports, (enum tport_via)public, ta_args(ta)(ta).tl);
1523 else
1524 retval = tport_bind_client(mr, mytpn, transports, (enum tport_via)public, ta_args(ta)(ta).tl);
1525
1526 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))
;
1527
1528 return retval;
1529}
1530
1531
1532/** Bind primary transport objects used by a client-only application.
1533 * @internal
1534 */
1535int tport_bind_client(tport_master_t *mr,
1536 tp_name_t const *tpn,
1537 char const * const transports[],
1538 enum tport_via public,
1539 tagi_t *tags)
1540{
1541 int i;
1542 tport_primary_t *pri = NULL((void*)0), **tbf;
1543 tp_name_t tpn0[1] = {{ "*", "*", "*", "*", NULL((void*)0), NULL((void*)0) }};
1544 char const *why = "unknown";
1545
1546 tport_vtable_t const *vtable;
1547
1548 if (public == tport_type_local)
1549 public = tport_type_client;
1550
1551 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__, 1552, "%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)
1552 __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__, 1552, "%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)
;
1553
1554 memset(tpn0, 0, sizeof(tpn0));
1555
1556 for (tbf = &mr->mr_primaries; *tbf; tbf = &(*tbf)->pri_next)
1557 ;
1558
1559 for (i = 0; transports[i]; i++) {
1560 su_addrinfo_t hints[1];
1561 char const *proto = transports[i];
1562
1563 if (strcmp(proto, tpn->tpn_proto)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(proto) && __builtin_constant_p (tpn->tpn_proto) &&
(__s1_len = __builtin_strlen (proto), __s2_len = __builtin_strlen
(tpn->tpn_proto), (!((size_t)(const void *)((proto) + 1) -
(size_t)(const void *)(proto) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((tpn->tpn_proto) + 1) - (size_t
)(const void *)(tpn->tpn_proto) == 1) || __s2_len >= 4)
) ? __builtin_strcmp (proto, tpn->tpn_proto) : (__builtin_constant_p
(proto) && ((size_t)(const void *)((proto) + 1) - (size_t
)(const void *)(proto) == 1) && (__s1_len = __builtin_strlen
(proto), __s1_len < 4) ? (__builtin_constant_p (tpn->tpn_proto
) && ((size_t)(const void *)((tpn->tpn_proto) + 1)
- (size_t)(const void *)(tpn->tpn_proto) == 1) ? __builtin_strcmp
(proto, tpn->tpn_proto) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (tpn->
tpn_proto); int __result = (((const unsigned char *) (const char
*) (proto))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
proto))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
proto))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (proto
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
tpn->tpn_proto) && ((size_t)(const void *)((tpn->
tpn_proto) + 1) - (size_t)(const void *)(tpn->tpn_proto) ==
1) && (__s2_len = __builtin_strlen (tpn->tpn_proto
), __s2_len < 4) ? (__builtin_constant_p (proto) &&
((size_t)(const void *)((proto) + 1) - (size_t)(const void *
)(proto) == 1) ? __builtin_strcmp (proto, tpn->tpn_proto) :
(- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (proto); int __result = (((const unsigned
char *) (const char *) (tpn->tpn_proto))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (tpn->tpn_proto))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (tpn->tpn_proto
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (tpn->
tpn_proto))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(proto, tpn->tpn_proto)))); })
!= 0 &&
1564 strcmp(tpn->tpn_proto, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tpn->tpn_proto) && __builtin_constant_p (tpn_any
) && (__s1_len = __builtin_strlen (tpn->tpn_proto)
, __s2_len = __builtin_strlen (tpn_any), (!((size_t)(const void
*)((tpn->tpn_proto) + 1) - (size_t)(const void *)(tpn->
tpn_proto) == 1) || __s1_len >= 4) && (!((size_t)(
const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (tpn->tpn_proto
, tpn_any) : (__builtin_constant_p (tpn->tpn_proto) &&
((size_t)(const void *)((tpn->tpn_proto) + 1) - (size_t)(
const void *)(tpn->tpn_proto) == 1) && (__s1_len =
__builtin_strlen (tpn->tpn_proto), __s1_len < 4) ? (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) ? __builtin_strcmp (tpn
->tpn_proto, tpn_any) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn_any); int
__result = (((const unsigned char *) (const char *) (tpn->
tpn_proto))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn->tpn_proto))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (tpn->tpn_proto))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (tpn->tpn_proto))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (tpn_any) && ((size_t)
(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) && (__s2_len = __builtin_strlen (tpn_any), __s2_len
< 4) ? (__builtin_constant_p (tpn->tpn_proto) &&
((size_t)(const void *)((tpn->tpn_proto) + 1) - (size_t)(
const void *)(tpn->tpn_proto) == 1) ? __builtin_strcmp (tpn
->tpn_proto, tpn_any) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (tpn->
tpn_proto); int __result = (((const unsigned char *) (const char
*) (tpn_any))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn_any))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn_any))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (tpn_any
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (tpn
->tpn_proto, tpn_any)))); })
!= 0)
1565 continue;
1566
1567 vtable = tport_vtable_by_name(proto, public);
1568 if (!vtable)
1569 continue;
1570
1571 /* Resolve protocol, skip unknown transport protocols */
1572 if (getprotohints(hints, proto, AI_PASSIVE0x0001) < 0)
1573 continue;
1574
1575 tpn0->tpn_proto = proto;
1576 tpn0->tpn_comp = tpn->tpn_comp;
1577 tpn0->tpn_ident = tpn->tpn_ident;
1578
1579 hints->ai_canonname = "*";
1580
1581 if (!(pri = tport_alloc_primary(mr, vtable, tpn0, hints, tags, &why)))
1582 break;
1583
1584 pri->pri_public = tport_type_client; /* XXX */
1585 }
1586
1587 if (!pri) {
1588 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__, 1588, "tport_alloc_primary: %s failed\n", why
)) : (void)0)
;
1589 tport_zap_primary(*tbf);
1590 }
1591
1592 return pri ? 0 : -1;
1593}
1594
1595/** Bind primary transport objects used by a server application. */
1596int tport_bind_server(tport_master_t *mr,
1597 tp_name_t const *tpn,
1598 char const * const transports[],
1599 enum tport_via public,
1600 tagi_t *tags)
1601{
1602 char hostname[TPORT_HOSTPORTSIZE(55)];
1603 char const *canon = NULL((void*)0), *host, *service;
1604 int error = 0, family = 0;
1605 tport_primary_t *pri = NULL((void*)0), **tbf;
1606 su_addrinfo_t *ai, *res = NULL((void*)0);
1607 unsigned port, port0, port1, old;
1608 unsigned short step = 0;
1609
1610 bind6only_check(mr);
1611
1612 (void)hostname;
1613
1614 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__, 1615, "%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)
1615 __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__, 1615, "%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)
;
1616
1617 if (tpn->tpn_host == NULL((void*)0) || strcmp(tpn->tpn_host, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tpn->tpn_host) && __builtin_constant_p (tpn_any)
&& (__s1_len = __builtin_strlen (tpn->tpn_host), __s2_len
= __builtin_strlen (tpn_any), (!((size_t)(const void *)((tpn
->tpn_host) + 1) - (size_t)(const void *)(tpn->tpn_host
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)((tpn_any) + 1) - (size_t)(const void *)(tpn_any) == 1) ||
__s2_len >= 4)) ? __builtin_strcmp (tpn->tpn_host, tpn_any
) : (__builtin_constant_p (tpn->tpn_host) && ((size_t
)(const void *)((tpn->tpn_host) + 1) - (size_t)(const void
*)(tpn->tpn_host) == 1) && (__s1_len = __builtin_strlen
(tpn->tpn_host), __s1_len < 4) ? (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) ? __builtin_strcmp (tpn
->tpn_host, tpn_any) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn_any); int
__result = (((const unsigned char *) (const char *) (tpn->
tpn_host))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn->tpn_host))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (tpn->tpn_host))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (tpn->tpn_host))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (tpn_any) && ((size_t)
(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) && (__s2_len = __builtin_strlen (tpn_any), __s2_len
< 4) ? (__builtin_constant_p (tpn->tpn_host) &&
((size_t)(const void *)((tpn->tpn_host) + 1) - (size_t)(const
void *)(tpn->tpn_host) == 1) ? __builtin_strcmp (tpn->
tpn_host, tpn_any) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn->tpn_host
); int __result = (((const unsigned char *) (const char *) (tpn_any
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tpn_any
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tpn_any
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (tpn_any
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (tpn
->tpn_host, tpn_any)))); })
== 0) {
1
Taking false branch
1618 /* Use a local IP address */
1619 host = NULL((void*)0);
1620 }
1621#ifdef SU_HAVE_IN61
1622 else if (host_is_ip6_reference(tpn->tpn_host)) {
2
Taking false branch
1623 /* Remove [] around IPv6 addresses. */
1624 size_t len = strlen(tpn->tpn_host);
1625 assert(len < sizeof hostname)((len < sizeof hostname) ? (void) (0) : __assert_fail ("len < sizeof hostname"
, "tport.c", 1625, __PRETTY_FUNCTION__))
;
1626 host = memcpy(hostname, tpn->tpn_host + 1, len - 2);
1627 hostname[len - 2] = '\0';
1628 }
1629#endif
1630 else
1631 host = tpn->tpn_host;
1632
1633 if (tpn->tpn_port != NULL((void*)0) && strlen(tpn->tpn_port) > 0 &&
1634 strcmp(tpn->tpn_port, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tpn->tpn_port) && __builtin_constant_p (tpn_any)
&& (__s1_len = __builtin_strlen (tpn->tpn_port), __s2_len
= __builtin_strlen (tpn_any), (!((size_t)(const void *)((tpn
->tpn_port) + 1) - (size_t)(const void *)(tpn->tpn_port
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)((tpn_any) + 1) - (size_t)(const void *)(tpn_any) == 1) ||
__s2_len >= 4)) ? __builtin_strcmp (tpn->tpn_port, tpn_any
) : (__builtin_constant_p (tpn->tpn_port) && ((size_t
)(const void *)((tpn->tpn_port) + 1) - (size_t)(const void
*)(tpn->tpn_port) == 1) && (__s1_len = __builtin_strlen
(tpn->tpn_port), __s1_len < 4) ? (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) ? __builtin_strcmp (tpn
->tpn_port, tpn_any) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn_any); int
__result = (((const unsigned char *) (const char *) (tpn->
tpn_port))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn->tpn_port))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (tpn->tpn_port))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (tpn->tpn_port))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (tpn_any) && ((size_t)
(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) && (__s2_len = __builtin_strlen (tpn_any), __s2_len
< 4) ? (__builtin_constant_p (tpn->tpn_port) &&
((size_t)(const void *)((tpn->tpn_port) + 1) - (size_t)(const
void *)(tpn->tpn_port) == 1) ? __builtin_strcmp (tpn->
tpn_port, tpn_any) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn->tpn_port
); int __result = (((const unsigned char *) (const char *) (tpn_any
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tpn_any
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tpn_any
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (tpn_any
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (tpn
->tpn_port, tpn_any)))); })
!= 0)
1635 service = tpn->tpn_port;
1636 else
1637 service = "";
1638
1639 if (host && (strcmp(host, "0.0.0.0")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(host) && __builtin_constant_p ("0.0.0.0") &&
(__s1_len = __builtin_strlen (host), __s2_len = __builtin_strlen
("0.0.0.0"), (!((size_t)(const void *)((host) + 1) - (size_t
)(const void *)(host) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)(("0.0.0.0") + 1) - (size_t)(const void
*)("0.0.0.0") == 1) || __s2_len >= 4)) ? __builtin_strcmp
(host, "0.0.0.0") : (__builtin_constant_p (host) && (
(size_t)(const void *)((host) + 1) - (size_t)(const void *)(host
) == 1) && (__s1_len = __builtin_strlen (host), __s1_len
< 4) ? (__builtin_constant_p ("0.0.0.0") && ((size_t
)(const void *)(("0.0.0.0") + 1) - (size_t)(const void *)("0.0.0.0"
) == 1) ? __builtin_strcmp (host, "0.0.0.0") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ("0.0.0.0"); int __result = (((const unsigned char *
) (const char *) (host))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (host))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (host))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (host))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("0.0.0.0") && ((size_t)(const void *)(("0.0.0.0") +
1) - (size_t)(const void *)("0.0.0.0") == 1) && (__s2_len
= __builtin_strlen ("0.0.0.0"), __s2_len < 4) ? (__builtin_constant_p
(host) && ((size_t)(const void *)((host) + 1) - (size_t
)(const void *)(host) == 1) ? __builtin_strcmp (host, "0.0.0.0"
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (host); int __result = (((const unsigned
char *) (const char *) ("0.0.0.0"))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("0.0.0.0"))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("0.0.0.0"))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ("0.0.0.0"))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (host, "0.0.0.0")))); })
== 0 || strcmp(host, "0")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(host) && __builtin_constant_p ("0") && (__s1_len
= __builtin_strlen (host), __s2_len = __builtin_strlen ("0")
, (!((size_t)(const void *)((host) + 1) - (size_t)(const void
*)(host) == 1) || __s1_len >= 4) && (!((size_t)(const
void *)(("0") + 1) - (size_t)(const void *)("0") == 1) || __s2_len
>= 4)) ? __builtin_strcmp (host, "0") : (__builtin_constant_p
(host) && ((size_t)(const void *)((host) + 1) - (size_t
)(const void *)(host) == 1) && (__s1_len = __builtin_strlen
(host), __s1_len < 4) ? (__builtin_constant_p ("0") &&
((size_t)(const void *)(("0") + 1) - (size_t)(const void *)(
"0") == 1) ? __builtin_strcmp (host, "0") : (__extension__ ({
const unsigned char *__s2 = (const unsigned char *) (const char
*) ("0"); int __result = (((const unsigned char *) (const char
*) (host))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
host))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
host))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (host
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
"0") && ((size_t)(const void *)(("0") + 1) - (size_t)
(const void *)("0") == 1) && (__s2_len = __builtin_strlen
("0"), __s2_len < 4) ? (__builtin_constant_p (host) &&
((size_t)(const void *)((host) + 1) - (size_t)(const void *)
(host) == 1) ? __builtin_strcmp (host, "0") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (host); int __result = (((const unsigned char *) (const
char *) ("0"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("0"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("0"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("0"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(host, "0")))); })
== 0))
3
Taking false branch
1640 host = NULL((void*)0), family = AF_INET2;
1641#if SU_HAVE_IN61
1642 else if (host && strcmp(host, "::")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(host) && __builtin_constant_p ("::") && (__s1_len
= __builtin_strlen (host), __s2_len = __builtin_strlen ("::"
), (!((size_t)(const void *)((host) + 1) - (size_t)(const void
*)(host) == 1) || __s1_len >= 4) && (!((size_t)(const
void *)(("::") + 1) - (size_t)(const void *)("::") == 1) || __s2_len
>= 4)) ? __builtin_strcmp (host, "::") : (__builtin_constant_p
(host) && ((size_t)(const void *)((host) + 1) - (size_t
)(const void *)(host) == 1) && (__s1_len = __builtin_strlen
(host), __s1_len < 4) ? (__builtin_constant_p ("::") &&
((size_t)(const void *)(("::") + 1) - (size_t)(const void *)
("::") == 1) ? __builtin_strcmp (host, "::") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ("::"); int __result = (((const unsigned char *) (const
char *) (host))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (host))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (host))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (host))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("::") && ((size_t)(const void *)(("::") + 1) - (size_t
)(const void *)("::") == 1) && (__s2_len = __builtin_strlen
("::"), __s2_len < 4) ? (__builtin_constant_p (host) &&
((size_t)(const void *)((host) + 1) - (size_t)(const void *)
(host) == 1) ? __builtin_strcmp (host, "::") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (host); int __result = (((const unsigned char *) (const
char *) ("::"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("::"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("::"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("::"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(host, "::")))); })
== 0)
4
Taking false branch
1643 host = NULL((void*)0), family = AF_INET610;
1644#endif
1645
1646 if (tpn->tpn_canon && strcmp(tpn->tpn_canon, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tpn->tpn_canon) && __builtin_constant_p (tpn_any
) && (__s1_len = __builtin_strlen (tpn->tpn_canon)
, __s2_len = __builtin_strlen (tpn_any), (!((size_t)(const void
*)((tpn->tpn_canon) + 1) - (size_t)(const void *)(tpn->
tpn_canon) == 1) || __s1_len >= 4) && (!((size_t)(
const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (tpn->tpn_canon
, tpn_any) : (__builtin_constant_p (tpn->tpn_canon) &&
((size_t)(const void *)((tpn->tpn_canon) + 1) - (size_t)(
const void *)(tpn->tpn_canon) == 1) && (__s1_len =
__builtin_strlen (tpn->tpn_canon), __s1_len < 4) ? (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) ? __builtin_strcmp (tpn
->tpn_canon, tpn_any) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn_any); int
__result = (((const unsigned char *) (const char *) (tpn->
tpn_canon))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn->tpn_canon))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (tpn->tpn_canon))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (tpn->tpn_canon))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (tpn_any) && ((size_t)
(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) && (__s2_len = __builtin_strlen (tpn_any), __s2_len
< 4) ? (__builtin_constant_p (tpn->tpn_canon) &&
((size_t)(const void *)((tpn->tpn_canon) + 1) - (size_t)(
const void *)(tpn->tpn_canon) == 1) ? __builtin_strcmp (tpn
->tpn_canon, tpn_any) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (tpn->
tpn_canon); int __result = (((const unsigned char *) (const char
*) (tpn_any))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn_any))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn_any))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (tpn_any
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (tpn
->tpn_canon, tpn_any)))); })
&&
1647 (host || tpn->tpn_canon != tpn->tpn_host))
1648 canon = tpn->tpn_canon;
1649
1650 if (tport_server_addrinfo(mr, canon, family,
5
Calling 'tport_server_addrinfo'
8
Returning from 'tport_server_addrinfo'
9
Taking false branch
1651 host, service, tpn->tpn_proto,
1652 transports, &res) < 0)
1653 return -1;
1654
1655 for (tbf = &mr->mr_primaries; *tbf; tbf = &(*tbf)->pri_next)
10
Loop condition is false. Execution continues on line 1658
1656 ;
1657
1658 port = port0 = port1 = ntohs(((su_sockaddr_t *)res->ai_addr)->su_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (((su_sockaddr_t *)res->ai_addr)->su_sin.sin_port
); if (__builtin_constant_p (__x)) __v = ((unsigned short int
) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) <<
8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) :
"cc"); __v; }))
;
11
Within the expansion of the macro 'ntohs':
a
Access to field 'ai_addr' results in a dereference of a null pointer (loaded from variable 'res')
1659 error = EPROTONOSUPPORT93;
1660
1661 /*
1662 * Loop until we can bind all the transports requested
1663 * by the transport user to the same port.
1664 */
1665 for (;;) {
1666 for (ai = res; ai; ai = ai->ai_next) {
1667 tp_name_t tpname[1];
1668 su_addrinfo_t ainfo[1];
1669 su_sockaddr_t su[1];
1670 tport_vtable_t const *vtable;
1671
1672 vtable = tport_vtable_by_name(ai->ai_canonname, public);
1673 if (!vtable)
1674 continue;
1675
1676 tport_addrinfo_copy(ainfo, su, sizeof su, ai);
1677 ainfo->ai_canonname = (char *)canon;
1678 su->su_portsu_sin.sin_port = htons(port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (port); if (__builtin_constant_p (__x)) __v = ((unsigned
short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff
) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0"
(__x) : "cc"); __v; }))
;
1679
1680 memcpy(tpname, tpn, sizeof tpname);
1681 tpname->tpn_canon = canon;
1682 tpname->tpn_host = host;
1683
1684 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__, 1685, "%s(%p): calling tport_listen for %s\n"
, __func__, (void *)mr, ai->ai_canonname)) : (void)0)
1685 __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__, 1685, "%s(%p): calling tport_listen for %s\n"
, __func__, (void *)mr, ai->ai_canonname)) : (void)0)
;
1686
1687 pri = tport_listen(mr, vtable, tpname, ainfo, tags);
1688 if (!pri) {
1689 switch (error = su_errno()) {
1690 case EADDRNOTAVAIL99: /* Not our address */
1691 case ENOPROTOOPT92: /* Protocol not supported */
1692 case ESOCKTNOSUPPORT94: /* Socket type not supported */
1693 continue;
1694 default:
1695 break;
1696 }
1697 break;
1698 }
1699
1700 if (port0 == 0 && port == 0) {
1701 port = port1 = ntohs(su->su_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (su->su_sin.sin_port); if (__builtin_constant_p (__x
)) __v = ((unsigned short int) ((((__x) >> 8) & 0xff
) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; }))
;
1702 assert(public != tport_type_server || port != 0)((public != tport_type_server || port != 0) ? (void) (0) : __assert_fail
("public != tport_type_server || port != 0", "tport.c", 1702
, __PRETTY_FUNCTION__))
;
1703 }
1704 }
1705
1706 if (ai == NULL((void*)0))
1707 break;
1708
1709 while (*tbf)
1710 tport_zap_primary(*tbf);
1711
1712 if (error != EADDRINUSE98 || port0 != 0 || port == 0)
1713 break;
1714
1715 while (step == 0) {
1716 /* step should be relative prime to 65536 - 1024 */
1717 /* 65536 - 1024 = 7 * 3 * 3 * 1024 */
1718 step = su_randint(1, 65535 - 1024 - 1) | 1;
1719 if (step % 3 == 0)
1720 step = (step + 2) % (65536 - 1024);
1721 if (step % 7 == 0)
1722 step = (step + 2) % (65536 - 1024);
1723 }
1724 old = port; port += step; if (port >= 65536) port -= (65536 - 1024);
1725
1726 if (port == port1) /* All ports in use! */
1727 break;
1728
1729 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__, 1730, "%s(%p): cannot bind all transports to port %u, trying %u\n"
, __func__, (void *)mr, old, port)) : (void)0)
1730 __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__, 1730, "%s(%p): cannot bind all transports to port %u, trying %u\n"
, __func__, (void *)mr, old, port)) : (void)0)
;
1731 }
1732
1733 tport_freeaddrinfo(res);
1734
1735 if (!*tbf) {
1736 su_seterrno(error);
1737 return -1;
1738 }
1739
1740 return 0;
1741}
1742
1743
1744/** Check if we can bind to IPv6 separately from IPv4 bind */
1745static
1746int bind6only_check(tport_master_t *mr)
1747{
1748 int retval = 0;
1749#if SU_HAVE_IN61
1750 su_sockaddr_t su[1], su4[1];
1751 socklen_t sulen, su4len;
1752 int s6, s4;
1753
1754 if (mr->mr_boundserver)
1755 return 0;
1756
1757 s4 = su_socket(AF_INET2, SOCK_DGRAMSOCK_DGRAM, IPPROTO_UDPIPPROTO_UDP);
1758 s6 = su_socket(AF_INET610, SOCK_DGRAMSOCK_DGRAM, IPPROTO_UDPIPPROTO_UDP);
1759
1760 memset(su, 0, sizeof *su);
1761 su->su_lensu_array[0] = sulen = (sizeof su->su_sin6);
1762 su->su_familysu_sa.sa_family = AF_INET610;
1763
1764 memset(su4, 0, sizeof *su4);
1765 su4->su_lensu_array[0] = su4len = (sizeof su->su_sin);
1766 su4->su_familysu_sa.sa_family = AF_INET2;
1767
1768 if (bind(s6, &su->su_sa, sulen) < 0)
1769 ;
1770 else if (getsockname(s6, &su->su_sa, &sulen) < 0)
1771 ;
1772 else if ((su4->su_portsu_sin.sin_port = su->su_portsu_sin.sin_port) != 0 &&
1773 bind(s4, &su4->su_sa, su4len) == 0)
1774 retval = 1;
1775
1776 su_close(s6), su_close(s4);
1777
1778 mr->mr_bindv6only = retval;
1779 mr->mr_boundserver = 1;
1780#endif
1781
1782 return retval;
1783}
1784
1785/* Number of supported transports */
1786#define TPORT_N(8) (8)
1787
1788/** Return list of addrinfo structures matching to
1789 * canon/host/service/protocol
1790 */
1791static
1792int tport_server_addrinfo(tport_master_t *mr,
1793 char const *canon,
1794 int family,
1795 char const *host,
1796 char const *service,
1797 char const *protocol,
1798 char const * const transports[],
1799 su_addrinfo_t **return_addrinfo)
1800{
1801 int i, N;
1802 su_addrinfo_t hints[TPORT_N(8) + 1];
1803
1804 *return_addrinfo = NULL((void*)0);
6
Null pointer value stored to 'res'
1805
1806 /*
1807 * Resolve all the transports requested by the protocol
1808 */
1809 for (i = 0, N = 0; transports[i] && N < TPORT_N(8); i++) {
1810 su_addrinfo_t *ai = &hints[N];
1811
1812 if (!su_casematch(protocol, transports[i]) && !su_strmatch(protocol, "*"))
1813 continue;
1814
1815 /* Resolve protocol, skip unknown transport protocols. */
1816 if (getprotohints(ai, transports[i], AI_PASSIVE0x0001) < 0)
1817 continue;
1818
1819 ai->ai_family = family;
1820 ai->ai_next = &hints[++N];
1821 }
1822
1823 if (N == 0)
7
Taking true branch
1824 return su_seterrno(EPROTONOSUPPORT93);
1825 if (transports[i] /* Too many protocols */)
1826 return su_seterrno(ENOMEM12);
1827
1828 hints[N - 1].ai_next = NULL((void*)0);
1829
1830 if (host) {
1831 int error = tport_getaddrinfo(host, service, hints, return_addrinfo);
1832 if (error || !*return_addrinfo) {
1833 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__, 1836, "%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, (void *)mr, host ? host : "\"\"", service, protocol
, su_gai_strerror(error))) : (void)0)
1834 __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__, 1836, "%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, (void *)mr, host ? host : "\"\"", service, protocol
, su_gai_strerror(error))) : (void)0)
1835 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__, 1836, "%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, (void *)mr, host ? host : "\"\"", service, protocol
, su_gai_strerror(error))) : (void)0)
1836 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__, 1836, "%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, (void *)mr, host ? host : "\"\"", service, protocol
, su_gai_strerror(error))) : (void)0)
;
1837 return su_seterrno(error != EAI_MEMORY-10 ? ENOENT2 : ENOMEM12);
1838 }
1839 return 0;
1840 }
1841
1842 return tport_get_local_addrinfo(mr, service, hints, return_addrinfo);
1843}
1844
1845/** Convert localinfo into addrinfo */
1846static
1847int
1848tport_get_local_addrinfo(tport_master_t *mr,
1849 char const *port,
1850 su_addrinfo_t const *hints,
1851 su_addrinfo_t **return_ai)
1852{
1853 int error, family;
1854 su_localinfo_t lihints[1] = {{ 0 }};
1855 su_localinfo_t *li, *li_result;
1856 su_addrinfo_t const *h;
1857 su_addrinfo_t *ai, **prev;
1858 su_sockaddr_t *su;
1859 unsigned long lport = 0;
1860 char *rest;
1861
1862 prev = return_ai, *prev = NULL((void*)0);
1863
1864 if (port) {
1865 lport = strtoul(port, &rest, 10);
1866 if (lport >= 65536) {
1867 su_seterrno(EINVAL22);
1868 return -1;
1869 }
1870 }
1871
1872 family = hints->ai_family;
1873
1874 for (h = hints->ai_next; h && family; h = h->ai_next)
1875 if (h->ai_family != family)
1876 family = 0;
1877
1878 lihints->li_flags = 0;
1879 lihints->li_family = family;
1880 lihints->li_scope = LI_SCOPE_GLOBAL | LI_SCOPE_SITE | LI_SCOPE_HOST;
1881
1882 error = su_getlocalinfo(lihints, &li_result);
1883 if (error) {
1884#if SU_HAVE_IN61
1885 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__, 1889, "%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)
1886 __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__, 1889, "%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)
1887 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__, 1889, "%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)
1888 : 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__, 1889, "%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)
1889 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__, 1889, "%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)
;
1890#else
1891 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__, 1894, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 2 ? "ip4" : "ip", su_gli_strerror
(error))) : (void)0)
1892 __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__, 1894, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 2 ? "ip4" : "ip", su_gli_strerror
(error))) : (void)0)
1893 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__, 1894, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 2 ? "ip4" : "ip", su_gli_strerror
(error))) : (void)0)
1894 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__, 1894, "%s(%p): su_getlocalinfo() for %s address: %s\n"
, __func__, (void *)mr, family == 2 ? "ip4" : "ip", su_gli_strerror
(error))) : (void)0)
;
1895#endif
1896 su_seterrno(ENOENT2);
1897 return -1;
1898 }
1899
1900 for (li = li_result; li; li = li->li_next) {
1901 for (h = hints; h; h = h->ai_next) {
1902 if (h->ai_family && h->ai_family != li->li_family)
1903 continue;
1904
1905 ai = calloc(1, sizeof *ai + li->li_addrlen);
1906 if (ai == NULL((void*)0))
1907 break;
1908
1909 *prev = ai, prev = &ai->ai_next;
1910
1911 ai->ai_flags = AI_PASSIVE0x0001 | TP_AI_ANY0x80000;
1912 ai->ai_family = li->li_family;
1913 ai->ai_socktype = h->ai_socktype;
1914 ai->ai_protocol = h->ai_protocol;
1915 ai->ai_canonname = h->ai_canonname;
1916 ai->ai_addr = memcpy(ai + 1, li->li_addr,
1917 ai->ai_addrlen = li->li_addrlen);
1918 su = (void *)ai->ai_addr;
1919 su->su_portsu_sin.sin_port = htons(lport)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (lport); if (__builtin_constant_p (__x)) __v = ((unsigned
short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff
) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0"
(__x) : "cc"); __v; }))
;
1920 }
1921 }
1922
1923 su_freelocalinfo(li_result);
1924
1925 if (li) {
1926 tport_freeaddrinfo(*return_ai);
1927 su_seterrno(ENOMEM12);
1928 return -1;
1929 }
1930
1931 if (*return_ai == NULL((void*)0)) {
1932 su_seterrno(ENOENT2);
1933 return -1;
1934 }
1935
1936 return 0;
1937}
1938
1939su_inlinestatic inline su_addrinfo_t *get_next_addrinfo(su_addrinfo_t **all);
1940
1941/** Translate address and service.
1942 *
1943 * This is a getaddrinfo() supporting multiple hints in a list.
1944 */
1945int tport_getaddrinfo(char const *node, char const *service,
1946 su_addrinfo_t const *hints,
1947 su_addrinfo_t **res)
1948{
1949 su_addrinfo_t const *h0;
1950 su_addrinfo_t *tbf, **prev;
1951 int error = EAI_SOCKTYPE-7;
1952 int i, N;
1953 su_addrinfo_t *all[TPORT_N(8) + 1]; /* Lists for all supported transports */
1954 su_addrinfo_t *results[TPORT_N(8) + 1];
1955 void *addr;
1956 int addrlen;
1957
1958 *res = NULL((void*)0);
1959
1960 for (N = 0, h0 = hints; h0; h0 = h0->ai_next) {
1961 su_addrinfo_t h[1];
1962
1963 *h = *h0, h->ai_next = NULL((void*)0), h->ai_canonname = NULL((void*)0);
1964
1965 error = su_getaddrinfo(node, service, h, &all[N]);
1966 results[N] = all[N];
1967 if (error == EAI_SOCKTYPE-7) {
1968 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__, 1970, "%s(): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, node ? node : "\"\"", service, h0->ai_canonname
, su_gai_strerror(error))) : (void)0)
1969 __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__, 1970, "%s(): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, node ? node : "\"\"", service, h0->ai_canonname
, su_gai_strerror(error))) : (void)0)
1970 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__, 1970, "%s(): su_getaddrinfo(%s, %s) for %s: %s\n"
, __func__, node ? node : "\"\"", service, h0->ai_canonname
, su_gai_strerror(error))) : (void)0)
;
1971 continue;
1972 }
1973
1974 if (error || !all[N])
1975 break;
1976 N++;
1977 }
1978
1979 if (h0)
1980 for (i = 0; i < N; i++)
1981 su_freeaddrinfo(all[i]);
1982 if (error)
1983 return error;
1984
1985 /* Combine all the valid addrinfo structures to a single list */
1986 prev = &tbf, tbf = NULL((void*)0);
1987
1988 for (;;) {
1989 su_addrinfo_t *ai = NULL((void*)0), *ai0;
1990
1991 for (i = 0, h0 = hints; i < N; i++, h0 = h0->ai_next) {
1992 if ((ai = get_next_addrinfo(&results[i])))
1993 break;
1994 }
1995 if (i == N)
1996 break;
1997
1998 assert(ai)((ai) ? (void) (0) : __assert_fail ("ai", "tport.c", 1998, __PRETTY_FUNCTION__
))
;
1999 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))
;
2000 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)))
;
2001
2002 /* Copy all the addrinfo structures with same address to the list */
2003 for (; i < N; i++, h0 = h0->ai_next) {
2004 while ((ai0 = get_next_addrinfo(&results[i]))) {
2005 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))
;
2006
2007 if (memcmp(addr, a, addrlen)) /* Different address */
2008 break;
2009
2010 results[i] = ai0->ai_next;
2011
2012 ai = calloc(1, sizeof *ai + ai0->ai_addrlen);
2013 if (ai == NULL((void*)0))
2014 goto error;
2015 *prev = memcpy(ai, ai0, sizeof *ai); prev = &ai->ai_next; *prev = NULL((void*)0);
2016 ai->ai_addr = memcpy(ai + 1, ai0->ai_addr, ai0->ai_addrlen);
2017 ai->ai_canonname = h0->ai_canonname;
2018 }
2019 }
2020 }
2021
2022 for (i = 0; i < N; i++)
2023 su_freeaddrinfo(all[i]);
2024
2025 *res = tbf;
2026 return 0;
2027
2028 error:
2029 for (i = 0; i < N; i++)
2030 su_freeaddrinfo(all[i]);
2031 tport_freeaddrinfo(tbf);
2032 return EAI_MEMORY-10;
2033}
2034
2035su_inlinestatic inline
2036su_addrinfo_t *get_next_addrinfo(su_addrinfo_t **all)
2037{
2038 su_addrinfo_t *ai;
2039
2040 while ((ai = *all)) {
2041 if (ai->ai_family == AF_INET2)
2042 return ai;
2043#if SU_HAVE_IN61
2044 if (ai->ai_family == AF_INET610)
2045 return ai;
2046#endif
2047 *all = ai->ai_next;
2048 }
2049 return ai;
2050}
2051
2052static
2053void tport_freeaddrinfo(su_addrinfo_t *ai)
2054{
2055 su_addrinfo_t *ai_next;
2056
2057 while (ai) {
2058 ai_next = ai->ai_next;
2059 free(ai);
2060 ai = ai_next;
2061 }
2062}
2063
2064static
2065int tport_addrinfo_copy(su_addrinfo_t *dst, void *addr, socklen_t addrlen,
2066 su_addrinfo_t const *src)
2067{
2068 if (addrlen < src->ai_addrlen)
2069 return -1;
2070
2071 memcpy(dst, src, sizeof *dst);
2072
2073 if (src->ai_addrlen < addrlen)
2074 memset(addr, 0, addrlen);
2075
2076 dst->ai_addr = memcpy(addr, src->ai_addr, src->ai_addrlen);
2077 dst->ai_next = NULL((void*)0);
2078
2079 return 0;
2080}
2081
2082/** Close a transport.
2083 *
2084 * Close the socket associated with a transport object. Report an error to
2085 * all pending clients, if required. Set/reset timer, too.
2086 */
2087void tport_close(tport_t *self)
2088{
2089 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__, 2090, "%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)
2090 __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__, 2090, "%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)
;
2091
2092 if (self->tp_refs == -1) {
2093 self->tp_refs = 0;
2094 }
2095
2096 if (self->tp_closed || !tport_is_secondary(self))
2097 return;
2098
2099 tprb_remove(&self->tp_pri->pri_open, self);
2100 tplist_insert(&self->tp_pri->pri_closed, self);
2101
2102 self->tp_closed = 1;
2103 self->tp_send_close = 3;
2104 self->tp_recv_close = 3;
2105
2106 if (self->tp_params->tpp_sdwn_error && self->tp_pused)
2107 tport_error_report(self, -1, NULL((void*)0));
2108
2109 if (self->tp_pri->pri_vtable->vtp_shutdown)
2110 self->tp_pri->pri_vtable->vtp_shutdown(self, 2);
2111 else if (self->tp_socket != -1)
2112 shutdown(self->tp_socket, 2);
2113
2114 if (self->tp_index)
2115 su_root_deregister(self->tp_master->mr_root, self->tp_index);
2116 self->tp_index = 0;
2117#if SU_HAVE_BSDSOCK1
2118 if (self->tp_socket != -1)
2119 su_close(self->tp_socket);
2120 self->tp_socket = -1;
2121#endif
2122
2123 /* Zap the queued messages */
2124 if (self->tp_queue) {
2125 unsigned short i, N = self->tp_params->tpp_qsize;
2126 for (i = 0; i < N; i++) {
2127 if (self->tp_queue[i])
2128 msg_ref_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL((void*)0);
2129 }
2130 }
2131
2132 self->tp_index = 0;
2133 self->tp_events = 0;
2134}
2135
2136/** Shutdown a transport.
2137 *
2138 * The tport_shutdown() shuts down a full-duplex transport connection
2139 * partially or completely. If @a how is 0, the further incoming data is
2140 * shut down. If @a how is 1, further outgoing data is shut down. If @a how
2141 * is 2, both incoming and outgoing traffic is shut down.
2142 *
2143 */
2144int tport_shutdown(tport_t *self, int how)
2145{
2146 int retval;
2147 if (!tport_is_secondary(self))
2148 return -1;
2149 retval = tport_shutdown0(self, how);
2150 tport_set_secondary_timer(self);
2151 return retval;
2152}
2153
2154/** Internal shutdown function */
2155int tport_shutdown0(tport_t *self, int how)
2156{
2157 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__, 2157, "%s(%p, %d)\n", __func__, (void *)self
, how)) : (void)0)
;
2158
2159 if (!tport_is_tcp(self) ||
2160 how < 0 || how >= 2 ||
2161 (how == 0 && self->tp_send_close) ||
2162 (how == 1 && self->tp_recv_close > 1)) {
2163 tport_close(self);
2164 return 1;
2165 }
2166
2167 if (self->tp_pri->pri_vtable->vtp_shutdown)
2168 self->tp_pri->pri_vtable->vtp_shutdown(self, how);
2169 else
2170 shutdown(self->tp_socket, how);
2171
2172 if (how == 0) {
2173 self->tp_recv_close = 2;
2174 tport_set_events(self, 0, SU_WAIT_IN(0x001));
2175 if (self->tp_params->tpp_sdwn_error && self->tp_pused)
2176 tport_error_report(self, -1, NULL((void*)0));
2177 }
2178 else if (how == 1) {
2179 self->tp_send_close = 2;
2180 tport_set_events(self, 0, SU_WAIT_OUT(0x004));
2181 if (tport_has_queued(self)) {
2182 unsigned short i, N = self->tp_params->tpp_qsize;
2183 for (i = 0; i < N; i++) {
2184 if (self->tp_queue[i]) {
2185 tport_pending_errmsg(self, self->tp_queue[i], EPIPE32);
2186 msg_ref_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL((void*)0);
2187 }
2188 }
2189 }
2190 }
2191
2192 return 0;
2193}
2194
2195static void tport_secondary_timer(su_root_magic_t *magic,
2196 su_timer_t *t,
2197 tport_t *self)
2198{
2199 su_time_t now;
2200
2201 if (tport_is_closed(self)) {
2202 if (self->tp_refs == 0)
2203 tport_zap_secondary(self);
2204 return;
2205 }
2206
2207 now = /* su_timer_expired(t); */ su_now();
2208
2209 if (self->tp_pri->pri_vtable->vtp_secondary_timer)
2210 self->tp_pri->pri_vtable->vtp_secondary_timer(self, now);
2211 else
2212 tport_base_timer(self, now);
2213}
2214
2215/** Base timer for secondary transports.
2216 *
2217 * Closes and zaps unused transports. Sets the timer again.
2218 */
2219void tport_base_timer(tport_t *self, su_time_t now)
2220{
2221 unsigned timeout = self->tp_params->tpp_idle;
2222
2223 if (timeout != UINT_MAX(2147483647 *2U +1U)) {
2224 if (self->tp_refs == 0 &&
2225 self->tp_msg == NULL((void*)0) &&
2226 !tport_has_queued(self) &&
2227 su_time_cmp(su_time_add(self->tp_rtime, timeout), now) < 0 &&
2228 su_time_cmp(su_time_add(self->tp_stime, timeout), now) < 0) {
2229 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__, 2231, "%s(%p): unused for %d ms,%s zapping\n"
, __func__, (void *)self, timeout, tport_is_closed(self) ? ""
: " closing and")) : (void)0)
2230 __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__, 2231, "%s(%p): unused for %d ms,%s zapping\n"
, __func__, (void *)self, timeout, tport_is_closed(self) ? ""
: " closing and")) : (void)0)
2231 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__, 2231, "%s(%p): unused for %d ms,%s zapping\n"
, __func__, (void *)self, timeout, tport_is_closed(self) ? ""
: " closing and")) : (void)0)
;
2232 if (!tport_is_closed(self))
2233 tport_close(self);
2234 tport_zap_secondary(self);
2235 return;
2236 }
2237 }
2238
2239 tport_set_secondary_timer(self);
2240}
2241
2242/** Set timer for a secondary transport.
2243 *
2244 * This function should be called after any network activity:
2245 * tport_base_connect(), tport_send_msg(), tport_send_queue(),
2246 * tport_recv_data(), tport_shutdown0(), tport_close(),
2247 *
2248 * @retval 0 always
2249 */
2250int tport_set_secondary_timer(tport_t *self)
2251{
2252 su_time_t const infinity = { ULONG_MAX(9223372036854775807L *2UL+1UL), 999999 };
2253 su_time_t target = infinity;
2254 char const *why = "not specified";
2255 su_timer_f timer = tport_secondary_timer;
2256
2257 if (!tport_is_secondary(self))
2258 return 0;
2259
2260 if (tport_is_closed(self)) {
2261 if (self->tp_refs == 0) {
2262 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__, 2263, "tport(%p): set timer at %u ms because %s\n"
, (void *)self, 0, "zap")) : (void)0)
2263 (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__, 2263, "tport(%p): set timer at %u ms because %s\n"
, (void *)self, 0, "zap")) : (void)0)
;
2264 su_timer_set_interval(self->tp_timer, timer, self, 0);
2265 }
2266 else
2267 su_timer_reset(self->tp_timer);
2268
2269 return 0;
2270 }
2271
2272 if (self->tp_params->tpp_idle != UINT_MAX(2147483647 *2U +1U)) {
2273 if (self->tp_refs == 0 &&
2274 self->tp_msg == NULL((void*)0) && !tport_has_queued(self)) {
2275 if (su_time_cmp(self->tp_stime, self->tp_rtime) < 0) {
2276 target = su_time_add(self->tp_rtime, self->tp_params->tpp_idle);
2277 why = "idle since recv";
2278 }
2279 else {
2280 target = su_time_add(self->tp_stime, self->tp_params->tpp_idle);
2281 why = "idle since send";
2282 }
2283 }
2284 }
2285
2286 if (self->tp_pri->pri_vtable->vtp_next_secondary_timer)
2287 self->tp_pri->pri_vtable->
2288 vtp_next_secondary_timer(self, &target, &why);
2289
2290 if (su_time_cmp(target, infinity)) {
2291 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__, 2292, "tport(%p): set timer at %ld ms because %s\n"
, (void *)self, su_duration(target, su_now()), why)) : (void)
0)
2292 (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__, 2292, "tport(%p): set timer at %ld ms because %s\n"
, (void *)self, su_duration(target, su_now()), why)) : (void)
0)
;
2293 su_timer_set_at(self->tp_timer, timer, self, target);
2294 }
2295 else {
2296 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__, 2296, "tport(%p): reset timer\n", (void *)self
)) : (void)0)
;
2297 su_timer_reset(self->tp_timer);
2298 }
2299
2300 return 0;
2301}
2302
2303
2304/** Flush idle connections. */
2305int tport_flush(tport_t *tp)
2306{
2307 tport_t *tp_next;
2308 tport_primary_t *pri;
2309
2310 if (tp == NULL((void*)0))
2311 return -1;
2312
2313 pri = tp->tp_pri;
2314
2315 while (pri->pri_closed)
2316 tport_zap_secondary(pri->pri_closed);
2317
2318 /* Go through all secondary transports, zap idle ones */
2319 for (tp = tprb_first(tp->tp_pri->pri_open); tp; tp = tp_next) {
2320 tp_next = tprb_succ(tp);
2321
2322 if (tp->tp_refs != 0)
2323 continue;
2324
2325 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__, 2326, "tport_flush(%p): %szapping\n", (void
*)tp, tport_is_closed(tp) ? "" : "closing and ")) : (void)0)
2326 (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__, 2326, "tport_flush(%p): %szapping\n", (void
*)tp, tport_is_closed(tp) ? "" : "closing and ")) : (void)0)
;
2327
2328 tport_close(tp);
2329 tport_zap_secondary(tp);
2330 }
2331
2332 return 0;
2333}
2334
2335/**Convert sockaddr_t to a transport name.
2336 *
2337 * @retval 0 when successful
2338 * @retval -1 upon an error
2339 */
2340int tport_convert_addr(su_home_t *home,
2341 tp_name_t *tpn,
2342 char const *protoname,
2343 char const *canon,
2344 su_sockaddr_t const *su)
2345{
2346 tp_name_t name[1] = {{ NULL((void*)0) }};
2347 char const *host;
2348 char buf[TPORT_HOSTPORTSIZE(55)];
2349 char port[8];
2350 size_t canonlen = canon ? strlen(canon) : 0;
2351
2352 if (su == NULL((void*)0))
2353 host = "*";
2354 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))
)
2355 host = tport_hostport(buf, sizeof(buf), su, 0);
2356 else if (canonlen && su->su_familysu_sa.sa_family == AF_INET2 &&
2357 strspn(canon, "0123456789.")__extension__ ({ char __a0, __a1, __a2; (__builtin_constant_p
("0123456789.") && ((size_t)(const void *)(("0123456789."
) + 1) - (size_t)(const void *)("0123456789.") == 1) ? ((__builtin_constant_p
(canon) && ((size_t)(const void *)((canon) + 1) - (size_t
)(const void *)(canon) == 1)) ? __builtin_strspn (canon, "0123456789."
) : ((__a0 = ((const char *) ("0123456789."))[0], __a0 == '\0'
) ? ((void) (canon), (size_t) 0) : ((__a1 = ((const char *) (
"0123456789."))[1], __a1 == '\0') ? __strspn_c1 (canon, __a0)
: ((__a2 = ((const char *) ("0123456789."))[2], __a2 == '\0'
) ? __strspn_c2 (canon, __a0, __a1) : (((const char *) ("0123456789."
))[3] == '\0' ? __strspn_c3 (canon, __a0, __a1, __a2) : __builtin_strspn
(canon, "0123456789.")))))) : __builtin_strspn (canon, "0123456789."
)); })
== canonlen)
2358 host = canon;
2359#if SU_HAVE_IN61
2360 else if (canonlen && su->su_familysu_sa.sa_family == AF_INET610 &&
2361 strspn(canon, "0123456789abcdefABCDEF:.")__extension__ ({ char __a0, __a1, __a2; (__builtin_constant_p
("0123456789abcdefABCDEF:.") && ((size_t)(const void
*)(("0123456789abcdefABCDEF:.") + 1) - (size_t)(const void *
)("0123456789abcdefABCDEF:.") == 1) ? ((__builtin_constant_p (
canon) && ((size_t)(const void *)((canon) + 1) - (size_t
)(const void *)(canon) == 1)) ? __builtin_strspn (canon, "0123456789abcdefABCDEF:."
) : ((__a0 = ((const char *) ("0123456789abcdefABCDEF:."))[0]
, __a0 == '\0') ? ((void) (canon), (size_t) 0) : ((__a1 = ((const
char *) ("0123456789abcdefABCDEF:."))[1], __a1 == '\0') ? __strspn_c1
(canon, __a0) : ((__a2 = ((const char *) ("0123456789abcdefABCDEF:."
))[2], __a2 == '\0') ? __strspn_c2 (canon, __a0, __a1) : (((const
char *) ("0123456789abcdefABCDEF:."))[3] == '\0' ? __strspn_c3
(canon, __a0, __a1, __a2) : __builtin_strspn (canon, "0123456789abcdefABCDEF:."
)))))) : __builtin_strspn (canon, "0123456789abcdefABCDEF:.")
); })
== canonlen)
2362 host = canon;
2363#endif
2364 else
2365 host = localipname(su->su_familysu_sa.sa_family, buf, sizeof(buf));
2366
2367 if (host == NULL((void*)0))
2368 return -1;
2369
2370 if (su == NULL((void*)0))
2371 strcpy(port, "*");
2372 else
2373 snprintf(port, sizeof(port), "%u", ntohs(su->su_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (su->su_sin.sin_port); if (__builtin_constant_p (__x
)) __v = ((unsigned short int) ((((__x) >> 8) & 0xff
) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; }))
);
2374
2375 name->tpn_proto = protoname;
2376 name->tpn_host = host;
2377 name->tpn_canon = canon ? canon : host;
2378 name->tpn_port = port;
2379
2380 return tport_name_dup(home, tpn, name);
2381}
2382
2383/** Set transport object name. @internal
2384 */
2385int tport_setname(tport_t *self,
2386 char const *protoname,
2387 su_addrinfo_t const *ai,
2388 char const *canon)
2389{
2390 su_addrinfo_t *selfai = self->tp_addrinfo;
2391
2392 if (tport_convert_addr(self->tp_home, self->tp_name,
2393 protoname, canon,
2394 (su_sockaddr_t *)ai->ai_addr) < 0)
2395 return -1;
2396
2397 if (tport_is_secondary(self))
2398 self->tp_identtp_name->tpn_ident = self->tp_pri->pri_primary->tp_identtp_name->tpn_ident;
2399
2400 selfai->ai_flags = ai->ai_flags & TP_AI_MASK0xff000;
2401
2402 selfai->ai_family = ai->ai_family;
2403 selfai->ai_socktype = ai->ai_socktype;
2404 selfai->ai_protocol = ai->ai_protocol;
2405 selfai->ai_canonname = (char *)self->tp_name->tpn_canon;
2406
2407 if (ai->ai_addr) {
2408 assert(ai->ai_family)((ai->ai_family) ? (void) (0) : __assert_fail ("ai->ai_family"
, "tport.c", 2408, __PRETTY_FUNCTION__))
, assert(ai->ai_socktype)((ai->ai_socktype) ? (void) (0) : __assert_fail ("ai->ai_socktype"
, "tport.c", 2408, __PRETTY_FUNCTION__))
, assert(ai->ai_protocol)((ai->ai_protocol) ? (void) (0) : __assert_fail ("ai->ai_protocol"
, "tport.c", 2408, __PRETTY_FUNCTION__))
;
2409 memcpy(self->tp_addr, ai->ai_addr, selfai->ai_addrlen = ai->ai_addrlen);
2410 }
2411
2412 return 0;
2413}
2414
2415/**Resolve protocol name.
2416 *
2417 * Convert a protocol name to IP protocol number and socket type used by
2418 * su_getaddrinfo().
2419 *
2420 * @param hints hints with the protocol number and socktype [OUT]
2421 * @param proto protocol name [IN]
2422 * @param flags hint flags
2423 */
2424static
2425int getprotohints(su_addrinfo_t *hints,
2426 char const *proto,
2427 int flags)
2428{
2429 memset(hints, 0, sizeof *hints);
2430
2431 hints->ai_flags = flags;
2432 hints->ai_canonname = (char *)proto;
2433
2434#if HAVE_TLS1
2435 if (su_casematch(proto, "tls"))
2436 proto = "tcp";
2437#endif
2438
2439#if HAVE_SOFIA_NTH1
2440 if (su_casematch(proto, "ws"))
2441 proto = "tcp";
2442 if (su_casematch(proto, "wss"))
2443 proto = "tcp";
2444#endif
2445
2446#if HAVE_SCTP
2447 if (su_casematch(proto, "sctp")) {
2448 hints->ai_protocol = IPPROTO_SCTPIPPROTO_SCTP;
2449 hints->ai_socktype = SOCK_STREAMSOCK_STREAM;
2450 return 0;
2451 }
2452#endif
2453
2454 if (su_casematch(proto, "udp")) {
2455 hints->ai_protocol = IPPROTO_UDPIPPROTO_UDP;
2456 hints->ai_socktype = SOCK_DGRAMSOCK_DGRAM;
2457 return 0;
2458 }
2459
2460 if (su_casematch(proto, "tcp")) {
2461 hints->ai_protocol = IPPROTO_TCPIPPROTO_TCP;
2462 hints->ai_socktype = SOCK_STREAMSOCK_STREAM;
2463 return 0;
2464 }
2465
2466 return -1;
2467}
2468
2469/** Get local IP.
2470 *
2471 * Get primary local IP address in URI format (IPv6 address will be
2472 * []-quoted).
2473 */
2474static
2475char *localipname(int pf, char *buf, size_t bufsiz)
2476{
2477 su_localinfo_t *li = NULL((void*)0), hints[1] = {{ LI_NUMERIC | LI_CANONNAME }};
2478 size_t n;
2479 int error;
2480
2481 hints->li_family = pf;
2482
2483#if SU_HAVE_IN61
2484 if (pf == AF_INET610) {
2485 /* Link-local addresses are not usable on IPv6 */
2486 hints->li_scope = LI_SCOPE_GLOBAL | LI_SCOPE_SITE /* | LI_SCOPE_HOST */;
2487 }
2488#endif
2489
2490 if ((error = su_getlocalinfo(hints, &li))) {
2491#if SU_HAVE_IN61
2492 if (error == ELI_NOADDRESS && pf == AF_INET610) {
2493 hints->li_family = AF_INET2;
2494 error = su_getlocalinfo(hints, &li);
2495 if (error == ELI_NOADDRESS) {
2496 hints->li_family = AF_INET610; hints->li_scope |= LI_SCOPE_HOST;
2497 error = su_getlocalinfo(hints, &li);
2498 }
2499 if (error == ELI_NOADDRESS) {
2500 hints->li_family = AF_INET2;
2501 error = su_getlocalinfo(hints, &li);
2502 }
2503 }
2504#endif
2505 if (error) {
2506 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__, 2506, "tport: su_getlocalinfo: %s\n", su_gli_strerror
(error))) : (void)0)
;
2507 return NULL((void*)0);
2508 }
2509 }
2510
2511 assert(li)((li) ? (void) (0) : __assert_fail ("li", "tport.c", 2511, __PRETTY_FUNCTION__
))
; assert(li->li_canonname)((li->li_canonname) ? (void) (0) : __assert_fail ("li->li_canonname"
, "tport.c", 2511, __PRETTY_FUNCTION__))
;
2512
2513 n = strlen(li->li_canonname);
2514
2515 if (li->li_family == AF_INET2) {
2516 if (n >= bufsiz)
2517 return NULL((void*)0);
2518
2519 memcpy(buf, li->li_canonname, n + 1);
2520 }
2521 else {
2522 if (n + 2 >= bufsiz)
2523 return NULL((void*)0);
2524
2525 memcpy(buf + 1, li->li_canonname, n);
2526 buf[0] = '['; buf[++n] = ']'; buf[++n] = '\0';
2527 }
2528
2529 su_freelocalinfo(li);
2530
2531 return buf;
2532}
2533
2534/** Process errors from transport. */
2535void tport_error_report(tport_t *self, int errcode,
2536 su_sockaddr_t const *addr)
2537{
2538 char const *errmsg;
2539
2540 if (errcode == 0)
2541 return;
2542 else if (errcode > 0)
2543 errmsg = su_strerror(errcode);
2544 else
2545 /* Should be something like ENOTCONN */
2546 errcode = 0, errmsg = "stream closed";
2547
2548 if (addr && addr->su_familysu_sa.sa_family == AF_UNSPEC0)
2549 addr = NULL((void*)0);
2550
2551 /* Mark this connection as unusable */
2552 if (errcode > 0 && tport_has_connection(self))
2553 self->tp_reusable = 0;
2554
2555 /* Report error */
2556 if (addr && tport_pending_error(self, addr, errcode))
2557 ;
2558 else if (tport_is_secondary(self) &&
2559 tport_pending_error(self, NULL((void*)0), errcode) > 0)
2560 ;
2561 else if (self->tp_master->mr_tpac->tpac_error) {
2562 char *dstname = NULL((void*)0);
2563 char hp[TPORT_HOSTPORTSIZE(55)];
2564
2565 if (addr)
2566 dstname = tport_hostport(hp, sizeof hp, addr, 1);
2567
2568 STACK_ERROR(self, errcode, dstname)(self)->tp_master->mr_tpac->tpac_error((self)->tp_master
->mr_stack, (self), (errcode), (dstname))
;
2569 }
2570 else {
2571 if (tport_is_primary(self))
2572 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__, 2573, "%s(%p): %s (with %s)\n", __func__, (
void *)self, errmsg, self->tp_name->tpn_proto)) : (void
)0)
2573 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__, 2573, "%s(%p): %s (with %s)\n", __func__, (
void *)self, errmsg, self->tp_name->tpn_proto)) : (void
)0)
;
2574 else
2575 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__, 2576, "%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)
2576 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__, 2576, "%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)
;
2577 }
2578
2579 /* Close connection */
2580 if (!self->tp_closed && errcode > 0 && tport_has_connection(self))
2581 tport_close(self);
2582}
2583
2584/** Accept a new connection.
2585 *
2586 * The function tport_accept() accepts a new connection and creates a
2587 * secondary transport object for the new socket.
2588 */
2589int tport_accept(tport_primary_t *pri, int events)
2590{
2591 tport_t *self;
2592 su_addrinfo_t ai[1];
2593 su_sockaddr_t su[1];
2594 socklen_t sulen = sizeof su;
2595 su_socket_t s = INVALID_SOCKET((su_socket_t)INVALID_SOCKET), l = pri->pri_primary->tp_socket;
2596 char const *reason = "accept";
2597
2598 if (events & SU_WAIT_ERR(0x008))
2599 tport_error_event(pri->pri_primary);
2600
2601 if (!(events & SU_WAIT_ACCEPT(0x001)))
2602 return 0;
2603
2604 memcpy(ai, pri->pri_primary->tp_addrinfo, sizeof ai);
2605 ai->ai_canonname = NULL((void*)0);
2606
2607 s = accept(l, &su->su_sa, &sulen);
2608
2609 if (s < 0) {
2610 tport_error_report(pri->pri_primary, su_errno(), NULL((void*)0));
2611 return 0;
2612 }
2613
2614 ai->ai_addr = &su->su_sa, ai->ai_addrlen = sulen;
2615
2616 /* Alloc a new transport object, then register socket events with it */
2617 if ((self = tport_alloc_secondary(pri, s, 1, &reason)) == NULL((void*)0)) {
2618 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__, 2620, "%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)
2619 " 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__, 2620, "%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)
2620 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__, 2620, "%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)
;
2621 shutdown(s, 2);
2622 su_close(s);
2623 return 0;
2624 }
2625 else {
2626 int events = SU_WAIT_IN(0x001)|SU_WAIT_ERR(0x008)|SU_WAIT_HUP(0x010);
2627
2628 SU_CANONIZE_SOCKADDR(su)((su)->su_sa.sa_family == 10 ? su_canonize_sockaddr(su) : (
void)0)
;
2629
2630 if (/* Name this transport */
2631 tport_setname(self, pri->pri_protonamepri_primary->tp_name->tpn_proto, ai, NULL((void*)0)) != -1
2632 /* Register this secondary */
2633 &&
2634 tport_register_secondary(self, tport_wakeup, events) != -1) {
2635
2636 self->tp_conn_orient = 1;
2637 self->tp_is_connected = 1;
2638
2639 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__, 2640, "%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)
2640 __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__, 2640, "%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)
;
2641
2642 return 0;
2643 }
2644
2645 /* Failure: shutdown socket, */
2646 tport_close(self);
2647 tport_zap_secondary(self);
2648 self = NULL((void*)0);
2649 }
2650
2651 return 0;
2652}
2653
2654/** Allocate a new message object */
2655msg_t *tport_msg_alloc(tport_t const *self, usize_t size)
2656{
2657 if (self) {
2658 tport_master_t *mr = self->tp_master;
2659 msg_t *msg = mr->mr_tpac->tpac_alloc(mr->mr_stack, mr->mr_log,
2660 NULL((void*)0), size, self, NULL((void*)0));
2661 if (msg) {
2662 su_addrinfo_t *mai = msg_addrinfo(msg);
2663 su_addrinfo_t const *tai = self->tp_addrinfo;
2664
2665 mai->ai_family = tai->ai_family;
2666 mai->ai_protocol = tai->ai_protocol;
2667 mai->ai_socktype = tai->ai_socktype;
2668 }
2669
2670 return msg;
2671 }
2672 else {
2673 return NULL((void*)0);
2674 }
2675}
2676
2677/** Process events for socket waiting to be connected
2678 */
2679static int tport_connected(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
2680{
2681 int events = su_wait_events(w, self->tp_socket);
2682 tport_master_t *mr = self->tp_master;
2683 su_wait_t wait[1] = { SU_WAIT_INIT{ ((su_socket_t)INVALID_SOCKET), 0, 0 } };
2684
2685 int error;
2686
2687 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__, 2689, "tport_connected(%p): events%s%s\n", (
void *)self, events & (0x004) ? " CONNECTED" : "", events
& (0x008) ? " ERR" : "")) : (void)0)
2688 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__, 2689, "tport_connected(%p): events%s%s\n", (
void *)self, events & (0x004) ? " CONNECTED" : "", events
& (0x008) ? " ERR" : "")) : (void)0)
2689 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__, 2689, "tport_connected(%p): events%s%s\n", (
void *)self, events & (0x004) ? " CONNECTED" : "", events
& (0x008) ? " ERR" : "")) : (void)0)
;
2690
2691#if HAVE_POLL1
2692 assert(w->fd == self->tp_socket)((w->fd == self->tp_socket) ? (void) (0) : __assert_fail
("w->fd == self->tp_socket", "tport.c", 2692, __PRETTY_FUNCTION__
))
;
2693#endif
2694
2695 if (events & SU_WAIT_ERR(0x008))
2696 tport_error_event(self);
2697
2698 if (!(events & SU_WAIT_CONNECT(0x004)) || self->tp_closed) {
2699 return 0;
2700 }
2701
2702 error = su_soerror(self->tp_socket);
2703 if (error) {
2704 tport_error_report(self, error, NULL((void*)0));
2705 return 0;
2706 }
2707
2708 self->tp_is_connected = 1;
2709
2710 su_root_deregister(mr->mr_root, self->tp_index);
2711 self->tp_index = -1;
2712 self->tp_events = SU_WAIT_IN(0x001) | SU_WAIT_ERR(0x008) | SU_WAIT_HUP(0x010);
2713
2714 if (su_wait_create(wait, self->tp_socket, self->tp_events) == -1 ||
2715 (self->tp_index = su_root_register(mr->mr_root,
2716 wait, tport_wakeup, self, 0))
2717 == -1) {
2718 tport_close(self);
2719 tport_set_secondary_timer(self);
2720 return 0;
2721 }
2722
2723 if (tport_has_queued(self))
2724 tport_send_event(self);
2725 else
2726 tport_set_secondary_timer(self);
2727
2728 return 0;
2729}
2730
2731/** Process events for primary socket */
2732static int tport_wakeup_pri(su_root_magic_t *m, su_wait_t *w, tport_t *self)
2733{
2734 tport_primary_t *pri = self->tp_pri;
2735 int events = su_wait_events(w, self->tp_socket);
2736
2737#if HAVE_POLL1
2738 assert(w->fd == self->tp_socket)((w->fd == self->tp_socket) ? (void) (0) : __assert_fail
("w->fd == self->tp_socket", "tport.c", 2738, __PRETTY_FUNCTION__
))
;
2739#endif
2740
2741 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__, 2749, "%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)
2742 "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__, 2749, "%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)
2743 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__, 2749, "%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)
2744 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__, 2749, "%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)
2745 (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__, 2749, "%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)
2746 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__, 2749, "%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)
2747 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__, 2749, "%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)
2748 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__, 2749, "%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)
2749 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__, 2749, "%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)
;
2750
2751
2752 if (pri->pri_vtable->vtp_wakeup_pri)
2753 return pri->pri_vtable->vtp_wakeup_pri(pri, events);
2754 else
2755 return tport_base_wakeup(self, events);
2756}
2757
2758/** Process events for connected socket */
2759int tport_wakeup(su_root_magic_t *magic, su_wait_t *w, tport_t *self)
2760{
2761 int events = su_wait_events(w, self->tp_socket);
2762
2763#if HAVE_POLL1
2764 assert(w->fd == self->tp_socket)((w->fd == self->tp_socket) ? (void) (0) : __assert_fail
("w->fd == self->tp_socket", "tport.c", 2764, __PRETTY_FUNCTION__
))
;
2765#endif
2766
2767 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__, 2773, "%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)
2768 "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__, 2773, "%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)
2769 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__, 2773, "%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)
2770 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__, 2773, "%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)
2771 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__, 2773, "%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)
2772 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__, 2773, "%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)
2773 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__, 2773, "%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)
;
2774
2775 if (self->tp_pri->pri_vtable->vtp_wakeup)
2776 return self->tp_pri->pri_vtable->vtp_wakeup(self, events);
2777 else
2778 return tport_base_wakeup(self, events);
2779}
2780
2781static int tport_base_wakeup(tport_t *self, int events)
2782{
2783 int error = 0;
2784
2785 if (events & SU_WAIT_ERR(0x008))
2786 error = tport_error_event(self);
2787
2788 if ((events & SU_WAIT_OUT(0x004)) && !self->tp_closed)
2789 tport_send_event(self);
2790
2791 if ((events & SU_WAIT_IN(0x001)) && !self->tp_closed)
2792 tport_recv_event(self);
2793
2794 if ((events & SU_WAIT_HUP(0x010)) && !self->tp_closed)
2795 tport_hup_event(self);
2796
2797 if (error) {
2798 if (self->tp_closed && error == EPIPE32)
2799 return 0;
2800
2801 tport_error_report(self, error, NULL((void*)0));
2802 }
2803
2804 return 0;
2805}
2806
2807/** Stop reading from socket until tport_continue() is called. */
2808int tport_stall(tport_t *self)
2809{
2810 return tport_set_events(self, 0, SU_WAIT_IN(0x001));
2811}
2812
2813/** Continue reading from socket. */
2814int tport_continue(tport_t *self)
2815{
2816 if (self == NULL((void*)0) || self->tp_recv_close)
2817 return -1;
2818 return tport_set_events(self, SU_WAIT_IN(0x001), 0);
2819}
2820
2821/** Process "hangup" event.
2822 *
2823 */
2824void tport_hup_event(tport_t *self)
2825{
2826 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__, 2826, "%s(%p)\n", __func__, (void *)self)) :
(void)0)
;
2827
2828 if (self->tp_msg) {
2829 su_time_t now = su_now();
2830 msg_recv_commit(self->tp_msg, 0, 1);
2831 tport_parse(self, 1, now);
2832 }
2833
2834 if (!tport_is_secondary(self))
2835 return;
2836
2837 /* Shutdown completely if there are no queued messages */
2838 /* Problem reported by Arsen Chaloyan */
2839 tport_shutdown0(self, tport_has_queued(self) ? 0 : 2);
2840 tport_set_secondary_timer(self);
2841}
2842
2843/** Receive data available on the socket.
2844 *
2845 * @retval -1 error
2846 * @retval 0 end-of-stream
2847 * @retval 1 normal receive
2848 * @retval 2 incomplete recv, recv again
2849 * @retval 3 STUN keepalive, ignore
2850 */
2851su_inlinestatic inline
2852int tport_recv_data(tport_t *self)
2853{
2854 return self->tp_pri->pri_vtable->vtp_recv(self);
2855}
2856
2857/** Process "ready to receive" event.
2858 *
2859 */
2860void tport_recv_event(tport_t *self)
2861{
2862 int again;
2863
2864 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__, 2864, "%s(%p)\n", "tport_recv_event", (void
*)self)) : (void)0)
;
2865
2866 do {
2867 /* Receive data from socket */
2868 again = tport_recv_data(self);
2869
2870 su_time(&self->tp_rtime);
2871
2872#if HAVE_SOFIA_STUN
2873 if (again == 3) /* STUN keepalive */
2874 return;
2875#endif
2876
2877 if (again < 0) {
2878 int error = su_errno();
2879
2880 if (!su_is_blocking(error)((error) == 115 || (error) == 11 || (error) == 11 || (error) ==
4)
) {
2881 tport_error_report(self, error, NULL((void*)0));
2882 return;
2883 }
2884 else {
2885 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__, 2886, "%s: recvfrom(): %s (%d)\n", __func__
, su_strerror(11), 11)) : (void)0)
2886 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__, 2886, "%s: recvfrom(): %s (%d)\n", __func__
, su_strerror(11), 11)) : (void)0)
;
2887 }
2888 }
2889
2890 if (again >= 0)
2891 tport_parse(self, self->tp_pre_framed ? 1 : !again, self->tp_rtime);
2892 }
2893 while (again > 1);
2894
2895 if (!tport_is_secondary(self))
2896 return;
2897
2898 if (again == 0 && !tport_is_dgram(self)) {
2899 /* End of stream */
2900 if (!self->tp_closed) {
2901 /* Don't shutdown completely if there are queued messages */
2902 tport_shutdown0(self, tport_has_queued(self) ? 0 : 2);
2903 }
2904 }
2905
2906 tport_set_secondary_timer(self);
2907}
2908
2909/*
2910 * Parse the data and feed complete messages to the stack
2911 */
2912static void tport_parse(tport_t *self, int complete, su_time_t now)
2913{
2914 msg_t *msg, *next = NULL((void*)0);
2915 int n, streaming, stall = 0;
2916
2917 for (msg = self->tp_msg; msg; msg = next) {
2918 n = msg_extract(msg); /* Parse message */
2919
2920 streaming = 0;
2921
2922 if (n == 0) {
2923 if (complete)
2924 msg_mark_as_complete(msg, MSG_FLG_ERROR), n = -1;
2925 else if (!(streaming = msg_is_streaming(msg))) {
2926 tport_sigcomp_accept_incomplete(self, msg);
2927 break;
2928 }
2929 }
2930
2931 if (msg_get_flags(msg, MSG_FLG_TOOLARGE))
2932 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__, 2933, "%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)
2933 __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__, 2933, "%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)
;
2934
2935 /* Do not try to read anymore from this connection? */
2936 if (tport_is_stream(self) &&
2937 msg_get_flags(msg, MSG_FLG_TOOLARGE | MSG_FLG_ERROR))
2938 self->tp_recv_close = stall = 1;
2939
2940 if (n == -1)
2941 next = NULL((void*)0);
2942 else if (streaming)
2943 msg_ref_create(msg); /* Keep a reference */
2944 else if (tport_is_stream(self))
2945 next = msg_next(msg);
2946 else
2947 next = NULL((void*)0);
2948
2949 tport_deliver(self, msg, next, self->tp_comp, now);
2950
2951 if (streaming && next == NULL((void*)0))
2952 break;
2953 }
2954
2955 if (stall)
2956 tport_stall(self);
2957
2958 if (self->tp_rlogged != msg)
2959 self->tp_rlogged = NULL((void*)0);
2960
2961 self->tp_msg = msg;
2962}
2963
2964/** Deliver message to the protocol stack */
2965void tport_deliver(tport_t *self,
2966 msg_t *msg,
2967 msg_t *next,
2968 tport_compressor_t *sc,
2969 su_time_t now)
2970{
2971 tport_t *ref;
2972 int error;
2973 struct tport_delivery *d;
2974 char ipaddr[SU_ADDRSIZE(48) + 2];
2975
2976 assert(msg)((msg) ? (void) (0) : __assert_fail ("msg", "tport.c", 2976, __PRETTY_FUNCTION__
))
;
2977
2978 d = self->tp_master->mr_delivery;
2979
2980 d->d_tport = self;
2981 d->d_msg = msg;
2982 *d->d_from = *self->tp_name;
2983
2984 if (tport_is_primary(self)) {
2985 su_sockaddr_t const *su = msg_addr(msg);
2986
2987#if SU_HAVE_IN61
2988 if (su->su_familysu_sa.sa_family == AF_INET610) {
2989 ipaddr[0] = '[';
2990 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));
2991 strcat(ipaddr, "]");
2992 }
2993 else {
2994 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));
2995 }
2996#else
2997 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));
2998#endif
2999
3000 d->d_from->tpn_canon = ipaddr;
3001 d->d_from->tpn_host = ipaddr;
3002 }
3003
3004 d->d_comp = sc;
3005 if (!sc)
3006 d->d_from->tpn_comp = NULL((void*)0);
3007
3008 error = msg_has_error(msg);
3009
3010 if (error && !*msg_chain_head(msg)) {
3011 /* This is badly damaged packet */
3012 }
3013 else if (self->tp_master->mr_log && msg != self->tp_rlogged) {
3014 char const *via = "recv";
3015 tport_log_msg(self, msg, via, "from", now);
3016 self->tp_rlogged = msg;
3017 }
3018
3019 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__, 3023, "%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)
3020 " 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__, 3023, "%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)
3021 __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__, 3023, "%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)
3022 (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__, 3023, "%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)
3023 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__, 3023, "%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)
;
3024
3025 ref = tport_incref(self);
3026
3027 if (self->tp_pri->pri_vtable->vtp_deliver) {
3028 self->tp_pri->pri_vtable->vtp_deliver(self, msg, now);
3029 }
3030 else
3031 tport_base_deliver(self, msg, now);
3032
3033 memset(d->d_from, 0, sizeof d->d_from);
3034 d->d_msg = NULL((void*)0);
3035
3036 tport_decref(&ref);
3037}
3038
3039/** Pass message to the protocol stack */
3040void
3041tport_base_deliver(tport_t *self, msg_t *msg, su_time_t now)
3042{
3043 STACK_RECV(self, msg, now)(self)->tp_master->mr_tpac->tpac_recv((self)->tp_master
->mr_stack, (self), (msg), (self)->tp_magic, (now))
;
3044}
3045
3046/** Return source transport object for delivered message */
3047tport_t *tport_delivered_by(tport_t const *tp, msg_t const *msg)
3048{
3049 if (tp && msg && msg == tp->tp_master->mr_delivery->d_msg)
3050 return tp->tp_master->mr_delivery->d_tport;
3051 else
3052 return NULL((void*)0);
3053}
3054
3055
3056/** Return source transport name for delivered message */
3057int tport_delivered_from(tport_t *tp, msg_t const *msg, tp_name_t name[1])
3058{
3059 if (name == NULL((void*)0))
3060 return -1;
3061
3062 if (tp == NULL((void*)0) || msg == NULL((void*)0) || msg != tp->tp_master->mr_delivery->d_msg) {
3063 memset(name, 0, sizeof *name);
3064 return -1;
3065 }
3066 else {
3067 *name = *tp->tp_master->mr_delivery->d_from;
3068 return 0;
3069 }
3070}
3071
3072/** Return TLS Subjects provided by the source transport */
3073su_strlst_t const *tport_delivered_from_subjects(tport_t *tp, msg_t const *msg)
3074{
3075 if (tp && msg && msg == tp->tp_master->mr_delivery->d_msg) {
3076 tport_t *tp_sec = tp->tp_master->mr_delivery->d_tport;
3077 return (tp_sec) ? tp_sec->tp_subjects : NULL((void*)0);
3078 }
3079 else
3080 return NULL((void*)0);
3081}
3082
3083/** Return UDVM used to decompress the message. */
3084int
3085tport_delivered_with_comp(tport_t *tp, msg_t const *msg,
3086 tport_compressor_t **return_compressor)
3087{
3088 if (tp == NULL((void*)0) || msg == NULL((void*)0) || msg != tp->tp_master->mr_delivery->d_msg)
3089 return -1;
3090
3091 if (return_compressor)
3092 *return_compressor = tp->tp_master->mr_delivery->d_comp;
3093
3094 return 0;
3095}
3096
3097/** Search for subject in list of TLS Certificate subjects */
3098int
3099tport_subject_search(char const *subject, su_strlst_t const *lst)
3100{
3101 usize_t idx, ilen;
3102 const char *subjuri;
3103
3104 if (!subject || su_strmatch(tpn_any, subject))
3105 return 1;
3106
3107 if (!lst)
3108 return 0;
3109
3110 /* Check if subject is a URI */
3111 if (su_casenmatch(subject,"sip:",4) || su_casenmatch(subject,"sips:",5))
3112 subjuri = subject + su_strncspn(subject,5,":") + 1;
3113 else
3114 subjuri = NULL((void*)0);
3115
3116 ilen = su_strlst_len(lst);
3117
3118 for (idx = 0; idx < ilen; idx++) {
3119 const char *lsturi, *lststr;
3120
3121 lststr = su_strlst_item(lst, idx);
3122
3123 /* check if lststr is a URI (sips URI is an unacceptable cert subject) */
3124 if (su_casenmatch(lststr,"sip:",4))
3125 lsturi = lststr + su_strncspn(lststr,4,":") + 1;
3126 else
3127 lsturi = NULL((void*)0);
3128
3129
3130 /* Match two SIP Server Identities */
3131 if (host_cmp(subjuri ? subjuri : subject, lsturi ? lsturi : lststr) == 0)
3132 return 1;
3133#if 0
3134 /* XXX - IETF drafts forbid wildcard certs */
3135 if (!subjuri && !lsturi && su_strnmatch("*.", lststr, 2)) {
3136 size_t urioffset = su_strncspn(subject, 64, ".");
3137 if (urioffset) {
3138 if (su_casematch(subject + urioffset, lststr+1))
3139 return 1;
3140 }
3141 }
3142#endif
3143 }
3144
3145 return 0;
3146}
3147
3148/** Allocate message for N bytes,
3149 * return message buffer as a iovec
3150 */
3151ssize_t tport_recv_iovec(tport_t const *self,
3152 msg_t **in_out_msg,
3153 msg_iovec_t iovec[msg_n_fragments],
3154 size_t N,
3155 int exact)
3156{
3157 msg_t *msg = *in_out_msg;
3158 ssize_t i, veclen;
3159 int fresh;
3160
3161 if (N == 0)
3162 return 0;
3163
3164 fresh = !msg;
3165
3166 /*
3167 * Allocate a new message if needed
3168 */
3169 if (!msg) {
3170 if (!(*in_out_msg = msg = tport_msg_alloc(self, N))) {
3171 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__, 3174, "%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)
3172 "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__, 3174, "%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)
3173 __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__, 3174, "%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)
3174 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__, 3174, "%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)
;
3175 return -1;
3176 }
3177 }
3178
3179 /*
3180 * Get enough buffer space for the incoming data
3181 */
3182 veclen = msg_recv_iovec(msg, iovec, msg_n_fragments, N, exact);
3183 if (veclen < 0) {
3184 int err = su_errno();
3185 if (fresh && err == ENOBUFS105 && msg_get_flags(msg, MSG_FLG_TOOLARGE))
3186 veclen = msg_recv_iovec(msg, iovec, msg_n_fragments, 4096, 1);
3187 }
3188 if (veclen < 0) {
3189 int err = su_errno();
3190 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__, 3194, "%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)
3191 "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__, 3194, "%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)
3192 __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__, 3194, "%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)
3193 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__, 3194, "%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)
3194 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__, 3194, "%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)
;
3195 su_seterrno(err);
3196 return veclen;
3197 }
3198
3199 assert(veclen <= msg_n_fragments)((veclen <= msg_n_fragments) ? (void) (0) : __assert_fail (
"veclen <= msg_n_fragments", "tport.c", 3199, __PRETTY_FUNCTION__
))
;
3200
3201 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__, 3205, "%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)
3202 "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__, 3205, "%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)
3203 __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__, 3205, "%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)
3204 (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__, 3205, "%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)
3205 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__, 3205, "%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)
;
3206
3207 for (i = 0; veclen > 1 && i < veclen; i++) {
3208 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__, 3208, "\tiovec[%lu] = %lu bytes\n", (LU)i, (
LU)iovec[i].siv_len)) : (void)0)
;
3209 }
3210
3211 return veclen;
3212}
3213
3214int tport_recv_error_report(tport_t *self)
3215{
3216 if (su_is_blocking(su_errno())((su_errno()) == 115 || (su_errno()) == 11 || (su_errno()) ==
11 || (su_errno()) == 4)
)
3217 return 1;
3218
3219 /* Report error */
3220 tport_error_report(self, su_errno(), NULL((void*)0));
3221
3222 return -1;
3223}
3224
3225/** Send a message.
3226 *
3227 * The function tport_tsend() sends a message using the transport @a self.
3228 *
3229 * @TAGS
3230 * TPTAG_MTU(), TPTAG_REUSE(), TPTAG_CLOSE_AFTER(), TPTAG_SDWN_AFTER(),
3231 * TPTAG_FRESH(), TPTAG_COMPARTMENT(), TPTAG_X509_SUBJECT()
3232 */
3233tport_t *tport_tsend(tport_t *self,
3234 msg_t *msg,
3235 tp_name_t const *_tpn,
3236 tag_type_t tag, tag_value_t value, ...)
3237{
3238 ta_list ta;
3239 tagi_t const *t;
3240 int reuse, sdwn_after, close_after, resolved = 0, fresh;
3241 unsigned mtu;
3242 su_addrinfo_t *ai;
3243 tport_primary_t *primary;
3244 tp_name_t tpn[1];
3245 struct sigcomp_compartment *cc;
3246
3247 assert(self)((self) ? (void) (0) : __assert_fail ("self", "tport.c", 3247
, __PRETTY_FUNCTION__))
;
3248
3249 if (!self || !msg || !_tpn) {
3250 msg_set_errno(msg, EINVAL22);
3251 return NULL((void*)0);
3252 }
3253
3254 *tpn = *_tpn;
3255
3256 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__, 3257, "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)
3257 (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__, 3257, "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)
;
3258
3259 if (tport_is_master(self)) {
3260 primary = (tport_primary_t *)tport_primary_by_name(self, tpn);
3261 if (!primary) {
3262 msg_set_errno(msg, EPROTONOSUPPORT93);
3263 return NULL((void*)0);
3264 }
3265 }
3266 else {
3267 primary = self->tp_pri;
3268 }
3269
3270 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)
;
3271
3272 reuse = primary->pri_primary->tp_reusable && self->tp_reusable;
3273 fresh = 0;
3274 sdwn_after = 0;
3275 close_after = 0;
3276 mtu = 0;
3277 cc = NULL((void*)0);
3278
3279 /* tl_gets() is a bit too slow here... */
3280 for (t = ta_args(ta)(ta).tl; t; t = tl_next(t)) {
3281 tag_type_t tt = t->t_tag;
3282
3283 if (tptag_reuse == tt)
3284 reuse = t->t_value != 0;
3285 else if (tptag_mtu == tt)
3286 mtu = t->t_value;
3287 else if (tptag_sdwn_after == tt)
3288 sdwn_after = t->t_value != 0;
3289 else if (tptag_close_after == tt)
3290 close_after = t->t_value != 0;
3291 else if (tptag_fresh == tt)
3292 fresh = t->t_value != 0;
3293 else if (tptag_compartment == tt)
3294 cc = (struct sigcomp_compartment *)t->t_value;
3295 }
3296
3297 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))
;
3298
3299 fresh = fresh || !reuse;
3300
3301 ai = msg_addrinfo(msg);
3302
3303 ai->ai_flags = 0;
3304
3305 tpn->tpn_comp = tport_canonize_comp(tpn->tpn_comp);
3306 if (tpn->tpn_comp) {
3307 ai->ai_flags |= TP_AI_COMPRESSED0x01000;
3308 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__, 3309, "%s: compressed msg(%p) with %s\n", __func__
, (void *)msg, tpn->tpn_comp)) : (void)0)
3309 __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__, 3309, "%s: compressed msg(%p) with %s\n", __func__
, (void *)msg, tpn->tpn_comp)) : (void)0)
;
3310 }
3311
3312 if (!tpn->tpn_comp || cc == NONE((void *)-1))
3313 cc = NULL((void*)0);
3314
3315 if (sdwn_after)
3316 ai->ai_flags |= TP_AI_SHUTDOWN0x04000;
3317 if (close_after)
3318 ai->ai_flags |= TP_AI_CLOSE0x08000;
3319
3320 if (fresh) {
3321 /* Select a primary protocol, make a fresh connection */
3322 self = primary->pri_primary;
3323 }
3324 else if (tport_is_secondary(self) && tport_is_clear_to_send(self)) {
3325 /* self = self; */
3326 ;
3327 }
3328 /*
3329 * Try to find an already open connection to the destination,
3330 * or get a primary protocol
3331 */
3332 else {
3333 /* If primary, resolve the destination address, store it in the msg */
3334 if (tport_resolve(primary->pri_primary, msg, tpn) < 0) {
3335 return NULL((void*)0);
3336 }
3337 resolved = 1;
3338
3339 self = tport_by_addrinfo(primary, msg_addrinfo(msg), tpn);
3340
3341 if (!self)
3342 self = primary->pri_primary;
3343 }
3344
3345 if (tport_is_primary(self)) {
3346 /* If primary, resolve the destination address, store it in the msg */
3347 if (!resolved && tport_resolve(self, msg, tpn) < 0) {
3348 return NULL((void*)0);
3349 }
3350
3351 if (tport_is_connection_oriented(self)
3352 || self->tp_params->tpp_conn_orient) {
3353#if 0 && HAVE_UPNP0 /* We do not want to use UPnP with secondary transports! */
3354 if (upnp_register_upnp_client(1) != 0) {
3355 upnp_check_for_nat();
3356 }
3357#endif
3358
3359 tpn->tpn_proto = self->tp_protonametp_name->tpn_proto;
3360
3361 if (!cc)
3362 tpn->tpn_comp = NULL((void*)0);
3363
3364 /* Create a secondary transport which is connected to the destination */
3365 self = tport_connect(primary, msg_addrinfo(msg), tpn);
3366
3367#if 0 && HAVE_UPNP0 /* We do not want to use UPnP with secondary transports! */
3368 upnp_deregister_upnp_client(0, 0);
3369#endif
3370
3371 if (!self) {
3372 msg_set_errno(msg, su_errno());
3373 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__, 3373, "tport_socket failed in tsend\n" "%s"
, "")) : (void)0)
;
3374 return NULL((void*)0);
3375 }
3376
3377 if (cc)
3378 tport_sigcomp_assign(self, cc);
3379 }
3380 }
3381 else if (tport_is_secondary(self)) {
3382 cc = tport_sigcomp_assign_if_needed(self, cc);
3383 }
3384
3385 if (cc == NULL((void*)0))
3386 tpn->tpn_comp = NULL((void*)0);
3387
3388 if (tport_is_secondary(self)) {
3389 /* Set the peer address to msg */
3390 tport_peer_address(self, msg);
3391 if (sdwn_after || close_after)
3392 self->tp_reusable = 0;
3393 }
3394
3395 if (self->tp_pri->pri_vtable->vtp_prepare
3396 ? self->tp_pri->pri_vtable->vtp_prepare(self, msg, tpn, cc, mtu) < 0
3397 : tport_prepare_and_send(self, msg, tpn, cc, mtu) < 0)
3398 return NULL((void*)0);
3399 else
3400 return self;
3401}
3402
3403int tport_prepare_and_send(tport_t *self, msg_t *msg,
3404 tp_name_t const *tpn,
3405 struct sigcomp_compartment *cc,
3406 unsigned mtu)
3407{
3408 int retval;
3409
3410 /* Prepare message for sending - i.e., encode it */
3411 if (msg_prepare(msg) < 0) {
3412 msg_set_errno(msg, errno(*__errno_location ())); /* msg parser uses plain errno. Hmph. */
3413 return -1;
3414 }
3415
3416 if (msg_size(msg) > (usize_t)(mtu ? mtu : tport_mtu(self))) {
3417 msg_set_errno(msg, EMSGSIZE90);
3418 return -1;
3419 }
3420
3421 /*
3422 * If there is already an queued message,
3423 * put this message straight in the queue
3424 */
3425 if ((self->tp_queue && self->tp_queue[self->tp_qhead]) ||
3426 /* ...or we are connecting */
3427 (self->tp_events & (SU_WAIT_CONNECT(0x004) | SU_WAIT_OUT(0x004)))) {
3428 if (tport_queue(self, msg) < 0) {
3429 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__, 3429, "tport_queue failed in tsend\n" "%s",
"")) : (void)0)
;
3430 return -1;
3431 }
3432 return 0;
3433 }
3434
3435 retval = tport_send_msg(self, msg, tpn, cc);
3436
3437 tport_set_secondary_timer(self);
3438
3439 return retval;
3440}
3441
3442
3443/** Send a message.
3444 *
3445 * @retval 0 when succesful
3446 * @retval -1 upon an error
3447 */
3448int tport_send_msg(tport_t *self, msg_t *msg,
3449 tp_name_t const *tpn,
3450 struct sigcomp_compartment *cc)
3451{
3452 msg_iovec_t *iov, auto_iov[40];
3453 size_t iovlen, iovused, i, total;
3454 size_t n;
3455 ssize_t nerror;
3456 int sdwn_after, close_after;
3457 su_time_t now;
3458 su_addrinfo_t *ai;
3459
3460 assert(self->tp_queue == NULL ||((self->tp_queue == ((void*)0) || self->tp_queue[self->
tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead
] == msg) ? (void) (0) : __assert_fail ("self->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3462, __PRETTY_FUNCTION__))
3461 self->tp_queue[self->tp_qhead] == NULL ||((self->tp_queue == ((void*)0) || self->tp_queue[self->
tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead
] == msg) ? (void) (0) : __assert_fail ("self->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3462, __PRETTY_FUNCTION__))
3462 self->tp_queue[self->tp_qhead] == msg)((self->tp_queue == ((void*)0) || self->tp_queue[self->
tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead
] == msg) ? (void) (0) : __assert_fail ("self->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3462, __PRETTY_FUNCTION__))
;
3463
3464 if (self->tp_iov)
3465 /* Use the heap-allocated I/O vector */
3466 iov = self->tp_iov, iovlen = self->tp_iovlen;
3467 else
3468 /* Use the stack I/O vector */
3469 iov = auto_iov, iovlen = sizeof(auto_iov)/sizeof(auto_iov[0]);
3470
3471 /* Get a iovec for message contents */
3472 for (;;) {
3473 iovused = msg_iovec(msg, iov, iovlen);
3474 if (iovused <= iovlen)
3475 break;
3476
3477 iov = su_realloc(self->tp_home, self->tp_iov, sizeof(*iov) * iovused);
3478
3479 if (iov == NULL((void*)0)) {
3480 msg_set_errno(msg, errno(*__errno_location ()));
3481 return -1;
3482 }
3483
3484 self->tp_iov = iov, self->tp_iovlen = iovlen = iovused;
3485 }
3486
3487 assert(iovused > 0)((iovused > 0) ? (void) (0) : __assert_fail ("iovused > 0"
, "tport.c", 3487, __PRETTY_FUNCTION__))
;
3488
3489 self->tp_stime = self->tp_ktime = now = su_now();
3490
3491 nerror = tport_vsend(self, msg, tpn, iov, iovused, cc);
3492 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__, 3492, "tport_vsend returned ""%zd""\n", nerror
)) : (void)0)
;
3493
3494 if (nerror == -1)
3495 return -1;
3496
3497 n = (size_t)nerror;
3498
3499 self->tp_unsent = NULL((void*)0), self->tp_unsentlen = 0;
3500
3501 if (n > 0 && self->tp_master->mr_log && self->tp_slogged != msg) {
3502 tport_log_msg(self, msg, "send", "to", now);
3503 self->tp_slogged = msg;
3504 }
3505
3506 for (i = 0, total = 0; i < iovused; i++) {
3507 if (total + (size_t)iov[i].mv_lensiv_len > n) {
3508 if (tport_is_connection_oriented(self)) {
3509 iov[i].mv_lensiv_len -= (su_ioveclen_t)(n - total);
3510 iov[i].mv_basesiv_base = (char *)iov[i].mv_basesiv_base + (n - total);
3511 if (tport_queue_rest(self, msg, &iov[i], iovused - i) < 0)
3512 return tport_send_fatal(self, msg, tpn, "tport_queue_rest");
3513 else
3514 return 0;
3515 }
3516 else {
3517 char const *comp = tpn->tpn_comp;
3518
3519 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__, 3521, "%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)
3520 "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__, 3521, "%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)
3521 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__, 3521, "%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)
;
3522
3523 msg_set_errno(msg, EIO5);
3524 return /* tport_send_fatal(self, msg, tpn, "tport_send") */ -1;
3525 }
3526 }
3527
3528 total += iov[i].mv_lensiv_len;
3529 }
3530
3531 /* We have sent a complete message */
3532 tport_sent_message(self, msg, 0);
3533
3534 if (!tport_is_secondary(self))
3535 return 0;
3536
3537 ai = msg_addrinfo(msg); assert(ai)((ai) ? (void) (0) : __assert_fail ("ai", "tport.c", 3537, __PRETTY_FUNCTION__
))
;
3538 close_after = (ai->ai_flags & TP_AI_CLOSE0x08000) == TP_AI_CLOSE0x08000;
3539 sdwn_after = (ai->ai_flags & TP_AI_SHUTDOWN0x04000) == TP_AI_SHUTDOWN0x04000 ||
3540 self->tp_send_close;
3541
3542 if (close_after || sdwn_after)
3543 tport_shutdown0(self, close_after ? 2 : 1);
3544
3545 return 0;
3546}
3547
3548static
3549ssize_t tport_vsend(tport_t *self,
3550 msg_t *msg,
3551 tp_name_t const *tpn,
3552 msg_iovec_t iov[],
3553 size_t iovused,
3554 struct sigcomp_compartment *cc)
3555{
3556 ssize_t n;
3557 su_addrinfo_t *ai = msg_addrinfo(msg);
3558
3559 if (cc) {
3560 n = tport_send_comp(self, msg, iov, iovused, cc, self->tp_comp);
3561 }
3562 else {
3563 ai->ai_flags &= ~TP_AI_COMPRESSED0x01000;
3564 n = self->tp_pri->pri_vtable->vtp_send(self, msg, iov, iovused);
3565 }
3566
3567 if (n == 0)
3568 return 0;
3569
3570 if (n == -1)
3571 return tport_send_error(self, msg, tpn, "tport_vsend");
3572
3573 tport_sent_bytes(self, n, n); /* Sigcomp will decrease on_line accodingly */
3574
3575 if (n > 0 && self->tp_master->mr_dump_file)
3576 tport_dump_iovec(self, msg, n, iov, iovused, "sent", "to");
3577
3578 if (n > 0 && self->tp_master->mr_capt_sock)
3579 tport_capt_msg(self, msg, n, iov, iovused, "sent");
3580
3581
3582 if (tport_log->log_level >= 7) {
3583 size_t i, m = 0;
3584
3585 for (i = 0; i < iovused; i++)
3586 m += iov[i].mv_lensiv_len;
3587
3588 if (tpn == NULL((void*)0) || tport_is_connection_oriented(self))
3589 tpn = self->tp_name;
3590
3591 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__, 3594, "%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)
3592 "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__, 3594, "%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)
3593 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__, 3594, "%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)
3594 (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__, 3594, "%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)
;
3595 }
3596
3597 return n;
3598}
3599
3600static
3601int tport_send_error(tport_t *self, msg_t *msg, tp_name_t const *tpn,
3602 char const *who)
3603{
3604 int error = su_errno();
3605
3606 if (error == EPIPE32) {
3607 /*Xyzzy*/
3608 }
3609
3610 if (su_is_blocking(error)((error) == 115 || (error) == 11 || (error) == 11 || (error) ==
4)
) {
3611 su_addrinfo_t *ai = msg_addrinfo(msg);
3612 char const *comp = (ai->ai_flags & TP_AI_COMPRESSED0x01000) ? ";comp=sigcomp" : "";
3613 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__, 3615, "%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)
3614 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__, 3615, "%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)
3615 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__, 3615, "%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)
;
3616 return 0;
3617 }
3618
3619 msg_set_errno(msg, error);
3620
3621 return tport_send_fatal(self, msg, tpn, who);
3622}
3623
3624static
3625int tport_send_fatal(tport_t *self, msg_t *msg, tp_name_t const *tpn,
3626 char const *who)
3627{
3628 su_addrinfo_t *ai = msg_addrinfo(msg);
3629 char const *comp = (ai->ai_flags & TP_AI_COMPRESSED0x01000) ? ";comp=sigcomp" : "";
3630
3631 int error = msg_errno(msg);
3632
3633 if (self->tp_addrinfo->ai_family == AF_INET2) {
3634 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__, 3636, "%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)
3635 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__, 3636, "%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)
3636 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__, 3636, "%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)
;
3637 }
3638#if SU_HAVE_IN61
3639 else if (self->tp_addrinfo->ai_family == AF_INET610) {
3640 su_sockaddr_t const *su = (su_sockaddr_t const *)ai->ai_addr;
3641 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__, 3645, "%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)
3642 " (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__, 3645, "%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)
3643 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__, 3645, "%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)
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)) >= 3 ? (_su_llog(tport_log, 3, "tport.c", (const
char *)__func__, 3645, "%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)
3645 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__, 3645, "%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)
;
3646 }
3647#endif
3648 else {
3649 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__, 3651, "%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)
3650 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__, 3651, "%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)
3651 (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__, 3651, "%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)
;
3652 }
3653
3654#if 0
3655 int i;
3656 for (i = 0; i < iovused; i++)
3657 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__, 3658, "\t\tiov[%d] = { %d bytes @ %p }\n", i
, iov[i].siv_len, (void *)iov[i].siv_base)) : (void)0)
3658 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__, 3658, "\t\tiov[%d] = { %d bytes @ %p }\n", i
, iov[i].siv_len, (void *)iov[i].siv_base)) : (void)0)
;
3659#endif
3660
3661 if (tport_is_connection_oriented(self)) {
3662 tport_error_report(self, error, NULL((void*)0));
3663 if (tport_has_connection(self))
3664 tport_close(self);
3665 }
3666
3667 return -1;
3668}
3669
3670
3671static
3672int tport_queue_rest(tport_t *self,
3673 msg_t *msg,
3674 msg_iovec_t iov[],
3675 size_t iovused)
3676{
3677 size_t iovlen = self->tp_iovlen;
3678
3679 assert(tport_is_connection_oriented(self))((tport_is_connection_oriented(self)) ? (void) (0) : __assert_fail
("tport_is_connection_oriented(self)", "tport.c", 3679, __PRETTY_FUNCTION__
))
;
3680 assert(self->tp_queue == NULL ||((self->tp_queue == ((void*)0) || self->tp_queue[self->
tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead
] == msg) ? (void) (0) : __assert_fail ("self->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3682, __PRETTY_FUNCTION__))
3681 self->tp_queue[self->tp_qhead] == NULL ||((self->tp_queue == ((void*)0) || self->tp_queue[self->
tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead
] == msg) ? (void) (0) : __assert_fail ("self->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3682, __PRETTY_FUNCTION__))
3682 self->tp_queue[self->tp_qhead] == msg)((self->tp_queue == ((void*)0) || self->tp_queue[self->
tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead
] == msg) ? (void) (0) : __assert_fail ("self->tp_queue == ((void*)0) || self->tp_queue[self->tp_qhead] == ((void*)0) || self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3682, __PRETTY_FUNCTION__))
;
3683
3684 if (tport_queue(self, msg) < 0)
3685 return -1;
3686
3687 assert(self->tp_queue[self->tp_qhead] == msg)((self->tp_queue[self->tp_qhead] == msg) ? (void) (0) :
__assert_fail ("self->tp_queue[self->tp_qhead] == msg"
, "tport.c", 3687, __PRETTY_FUNCTION__))
;
3688
3689 if (self->tp_iov == NULL((void*)0)) {
3690 if (iovlen < 40) iovlen = 40;
3691 if (iovlen < iovused) iovlen = iovused;
3692 self->tp_iov = su_alloc(self->tp_home, iovlen * sizeof(iov[0]));
3693 self->tp_iovlen = iovlen;
3694
3695 if (!self->tp_iov) {
3696 msg_set_errno(msg, errno(*__errno_location ()));
3697 return -1;
3698 }
3699
3700 memcpy(self->tp_iov, iov, iovused * sizeof(iov[0]));
3701
3702 iov = self->tp_iov;
3703 }
3704
3705 self->tp_unsent = iov;
3706 self->tp_unsentlen = iovused;
3707
3708 /* the POLLOUT event is far too unreliable with SCTP */
3709 if (self->tp_addrinfo->ai_protocol == IPPROTO_SCTPIPPROTO_SCTP)
3710 return 0;
3711
3712 /* Ask for a send event */
3713 tport_set_events(self, SU_WAIT_OUT(0x004), 0);
3714
3715 return 0;
3716}
3717
3718/** Queue a message to transport.
3719 *
3720 * The tport_tqueue() function queues a message in the send queue. It is
3721 * used by an (server) application that is required to send (response)
3722 * messages in certain order. For example, a HTTP server or proxy may
3723 * receive multiple requests from a single TCP connection. The server is
3724 * required to answer to the requests in same order as they are received.
3725 * The responses are, however, sometimes generated asynchronously, that is,
3726 * a response to a later request may be ready earlier. For that purpose, the
3727 * HTTP protocol stack queues an empty response message immediately upon
3728 * receiving a request. Other messages cannot be sent before the queued one.
3729 *
3730 * The function tport_tqsend() is used to send the completed response message.
3731 *
3732 * @param self pointer to transport object
3733 * @param msg message to be inserted into queue
3734 * @param tag,value,... tagged argument list
3735 *
3736 * @TAGS
3737 * @par Currently none.
3738 *
3739 * @retval 0 when successful
3740 * @retval -1 upon an error
3741
3742 * @ERRORS
3743 * @ERROR EINVAL Invalid argument(s).
3744 * @ERROR ENOMEM Memory was exhausted.
3745 * @ERROR ENOBUFS The transport object queue was full.
3746 *
3747 * @deprecated Alternative interface will be provided in near future.
3748 *
3749 * @sa tport_tqsend()
3750 */
3751int tport_tqueue(tport_t *self, msg_t *msg,
3752 tag_type_t tag, tag_value_t value, ...)
3753{
3754 msg_unprepare(msg);
3755
3756 return tport_queue(self, msg);
3757}
3758
3759/** Return number of queued messages. */
3760isize_t tport_queuelen(tport_t const *self)
3761{
3762 isize_t retval = 0;
3763
3764 if (self && self->tp_queue) {
3765 unsigned short i, N = self->tp_params->tpp_qsize;
3766
3767 for (i = self->tp_qhead; self->tp_queue[i] && retval < N; i = (i + 1) % N)
3768 retval++;
3769 }
3770
3771 return retval;
3772}
3773
3774static
3775int tport_queue(tport_t *self, msg_t *msg)
3776{
3777 unsigned short qhead = self->tp_qhead;
3778 unsigned short N = self->tp_params->tpp_qsize;
3779
3780 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__, 3782, "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)
3781 (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__, 3782, "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)
3782 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__, 3782, "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)
;
3783
3784 if (self->tp_queue == NULL((void*)0)) {
3785 assert(N > 0)((N > 0) ? (void) (0) : __assert_fail ("N > 0", "tport.c"
, 3785, __PRETTY_FUNCTION__))
;
3786 assert(qhead == 0)((qhead == 0) ? (void) (0) : __assert_fail ("qhead == 0", "tport.c"
, 3786, __PRETTY_FUNCTION__))
;
3787 self->tp_queue = su_zalloc(self->tp_home, N * sizeof(msg));
3788 if (!self->tp_queue) {
3789 msg_set_errno(msg, errno(*__errno_location ()));
3790 return -1;
3791 }
3792 }
3793
3794 if (self->tp_queue[qhead] == msg)
3795 return 0;
3796
3797 while (self->tp_queue[qhead]) {
3798 qhead = (qhead + 1) % N;
3799 if (qhead == self->tp_qhead) {
3800 msg_set_errno(msg, ENOBUFS105);
3801 return -1;
3802 }
3803 }
3804
3805 self->tp_queue[qhead] = msg_ref_create(msg);
3806
3807 return 0;
3808}
3809
3810/** Send a queued message (and queue another, if required).
3811 *
3812 * The function tport_tqsend() sends a message to the transport.
3813 *
3814 * @deprecated Alternative interface will be provided in near future.
3815 */
3816int tport_tqsend(tport_t *self, msg_t *msg, msg_t *next,
3817 tag_type_t tag, tag_value_t value, ...)
3818{
3819 unsigned short qhead;
3820 ta_list ta;
3821 int reuse, sdwn_after, close_after;
3822 unsigned short N;
3823 su_addrinfo_t *ai;
3824
3825 if (self == NULL((void*)0))
3826 return -1;
3827
3828 qhead = self->tp_qhead;
3829 N = self->tp_params->tpp_qsize;
3830 reuse = self->tp_reusable;
3831 sdwn_after = 0;
3832 close_after = 0;
3833
3834 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)
;
3835
3836 tl_gets(ta_args(ta)(ta).tl,
3837 TPTAG_REUSE_REF(reuse)tptag_reuse_ref, tag_bool_vr(&(reuse)),
3838 TPTAG_SDWN_AFTER_REF(sdwn_after)tptag_sdwn_after_ref, tag_bool_vr(&(sdwn_after)),
3839 TPTAG_CLOSE_AFTER_REF(close_after)tptag_close_after_ref, tag_bool_vr(&(close_after)),
3840 TAG_END()(tag_type_t)0, (tag_value_t)0);
3841
3842 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))
;
3843
3844 /* If "next", make sure we can queue it */
3845 if (next && self->tp_queue[qhead == 0 ? N - 1 : qhead - 1]) {
3846 msg_set_errno(next, ENOBUFS105);
3847 return -1;
3848 }
3849
3850 /* Prepare message for sending - i.e., encode it */
3851 if (msg_prepare(msg) < 0) {
3852 msg_set_errno(msg, errno(*__errno_location ()));
3853 return -1;
3854 }
3855
3856 tport_peer_address(self, msg); /* Set addrinfo */
3857 if (next == NULL((void*)0)) {
3858 ai = msg_addrinfo(msg);
3859
3860 if (sdwn_after)
3861 ai->ai_flags |= TP_AI_SHUTDOWN0x04000;
3862 if (close_after)
3863 ai->ai_flags |= TP_AI_CLOSE0x08000;
3864
3865 if (self->tp_queue[qhead] == msg) {
3866 tport_send_queue(self);
3867 tport_set_secondary_timer(self);
3868 }
3869 return 0;
3870 }
3871
3872 ai = msg_addrinfo(next);
3873
3874 if (sdwn_after)
3875 ai->ai_flags |= TP_AI_SHUTDOWN0x04000;
3876 if (close_after)
3877 ai->ai_flags |= TP_AI_CLOSE0x08000;
3878
3879 if (self->tp_queue[qhead] == msg) {
3880 /* XXX - what about errors? */
3881 tport_send_msg(self, msg, self->tp_name, NULL((void*)0));
3882 tport_set_secondary_timer(self);
3883 if (!self->tp_unsent) {
3884 msg_destroy(self->tp_queue[qhead]);
3885 if ((self->tp_queue[qhead] = msg_ref_create(next)))
3886 msg_unprepare(next);
3887 return 0;
3888 }
3889 }
3890
3891 while (self->tp_queue[qhead] && self->tp_queue[qhead] != msg) {
3892 qhead = (qhead + 1) % N;
3893 if (qhead == self->tp_qhead)
3894 break;
3895 }
3896
3897 if (self->tp_queue[qhead] != msg) {
3898 msg_set_errno(next, EINVAL22);
3899 return -1;
3900 }
3901
3902 msg = msg_ref_create(next);
3903
3904 do {
3905 qhead = (qhead + 1) % N;
3906 next = self->tp_queue[qhead]; self->tp_queue[qhead] = msg; msg = next;
3907 /* Above we made sure that there is an empty slot */
3908 assert(!next || qhead != self->tp_qhead)((!next || qhead != self->tp_qhead) ? (void) (0) : __assert_fail
("!next || qhead != self->tp_qhead", "tport.c", 3908, __PRETTY_FUNCTION__
))
;
3909 } while (next);
3910
3911 return 0;
3912}
3913
3914/** Send event.
3915 *
3916 * Process SU_WAIT_OUT event.
3917 */
3918void tport_send_event(tport_t *self)
3919{
3920 assert(tport_is_connection_oriented(self))((tport_is_connection_oriented(self)) ? (void) (0) : __assert_fail
("tport_is_connection_oriented(self)", "tport.c", 3920, __PRETTY_FUNCTION__
))
;
3921
3922 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__, 3923, "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)
3923 (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__, 3923, "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)
;
3924 tport_send_queue(self);
3925 tport_set_secondary_timer(self);
3926}
3927
3928/** Send queued messages */
3929void tport_send_queue(tport_t *self)
3930{
3931 msg_t *msg;
3932 msg_iovec_t *iov;
3933 size_t i, iovused, n, total;
3934 unsigned short qhead = self->tp_qhead, N = self->tp_params->tpp_qsize;
3935
3936 assert(self->tp_queue && self->tp_queue[qhead])((self->tp_queue && self->tp_queue[qhead]) ? (void
) (0) : __assert_fail ("self->tp_queue && self->tp_queue[qhead]"
, "tport.c", 3936, __PRETTY_FUNCTION__))
;
3937
3938 msg = self->tp_queue[qhead];
3939
3940 iov = self->tp_unsent, self->tp_unsent = NULL((void*)0);
3941 iovused = self->tp_unsentlen, self->tp_unsentlen = 0;
3942
3943 if (iov && iovused) {
3944 ssize_t e;
3945
3946 self->tp_stime = self->tp_ktime = su_now();
3947
3948 e = tport_vsend(self, msg, self->tp_name, iov, iovused, NULL((void*)0));
3949
3950 if (e == -1) /* XXX */
3951 return;
3952
3953 n = (size_t)e;
3954
3955 if (n > 0 && self->tp_master->mr_log && self->tp_slogged != msg) {
3956 tport_log_msg(self, msg, "send", "to", self->tp_stime);
3957 self->tp_slogged = msg;
3958 }
3959
3960 for (i = 0, total = 0; i < iovused; i++) {
3961 if (total + (size_t)iov[i].mv_lensiv_len > n) {
3962 iov[i].mv_lensiv_len -= (su_ioveclen_t)(n - total);
3963 iov[i].mv_basesiv_base = (char *)iov[i].mv_basesiv_base + (n - total);
3964
3965 self->tp_unsent = iov + i;
3966 self->tp_unsentlen = iovused - i;
3967
3968 return;
3969 }
3970 total += iov[i].mv_lensiv_len;
3971 }
3972 assert(total == n)((total == n) ? (void) (0) : __assert_fail ("total == n", "tport.c"
, 3972, __PRETTY_FUNCTION__))
;
3973
3974 /* We have sent a complete message */
3975
3976 self->tp_queue[qhead] = NULL((void*)0);
3977 tport_sent_message(self, msg, 0);
3978 msg_destroy(msg);
3979
3980 qhead = (qhead + 1) % N;
3981 }
3982
3983 while (msg_is_prepared(msg = self->tp_queue[self->tp_qhead = qhead])) {
3984 /* XXX - what about errors? */
3985 tport_send_msg(self, msg, self->tp_name, NULL((void*)0));
3986 if (self->tp_unsent)
3987 return;
3988
3989 msg = self->tp_queue[qhead]; /* tport_send_msg() may flush queue! */
3990 self->tp_queue[qhead] = NULL((void*)0);
3991 msg_destroy(msg);
3992 qhead = (qhead + 1) % N;
3993 }
3994
3995 /* No more send event(s)? */
3996 tport_set_events(self, 0, SU_WAIT_OUT(0x004));
3997}
3998
3999static int msg_select_addrinfo(msg_t *msg, su_addrinfo_t *res);
4000
4001static int
4002tport_resolve(tport_t *self, msg_t *msg, tp_name_t const *tpn)
4003{
4004 int error;
4005 char ipaddr[TPORT_HOSTPORTSIZE(55)];
4006 su_addrinfo_t *res, hints[1] = {{ 0 }};
4007 char const *host;
4008 su_sockaddr_t *su;
4009
4010 hints->ai_socktype = self->tp_addrinfo->ai_socktype;
4011 hints->ai_protocol = self->tp_addrinfo->ai_protocol;
4012
4013 if (host_is_ip6_reference(tpn->tpn_host)) {
4014 /* Remove [] around IPv6 address */
4015 size_t len = strlen(tpn->tpn_host);
4016 assert(len < sizeof ipaddr)((len < sizeof ipaddr) ? (void) (0) : __assert_fail ("len < sizeof ipaddr"
, "tport.c", 4016, __PRETTY_FUNCTION__))
;
4017 host = memcpy(ipaddr, tpn->tpn_host + 1, len - 2);
4018 ipaddr[len - 2] = '\0';
4019 hints->ai_flags |= AI_NUMERICHOST0x0004;
4020 }
4021 else {
4022#if HAVE_OPEN_C
4023 if (host_is_ip_address(tpn->tpn_host))
4024 hints->ai_flags |= AI_NUMERICHOST0x0004;
4025#endif
4026 host = tpn->tpn_host;
4027 }
4028
4029 if ((error = su_getaddrinfo(host, tpn->tpn_port, hints, &res))) {
4030 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__, 4032, "tport_resolve: getaddrinfo(\"%s\":%s): %s\n"
, tpn->tpn_host, tpn->tpn_port, su_gai_strerror(error))
) : (void)0)
4031 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__, 4032, "tport_resolve: getaddrinfo(\"%s\":%s): %s\n"
, tpn->tpn_host, tpn->tpn_port, su_gai_strerror(error))
) : (void)0)
4032 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__, 4032, "tport_resolve: getaddrinfo(\"%s\":%s): %s\n"
, tpn->tpn_host, tpn->tpn_port, su_gai_strerror(error))
) : (void)0)
;
4033 msg_set_errno(msg, ENXIO6);
4034 return -1;
4035 }
4036
4037 error = msg_select_addrinfo(msg, res);
4038
4039 su = (su_sockaddr_t *) msg_addrinfo(msg)->ai_addr;
4040
4041#if SU_HAVE_IN61
4042 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__, 4046, "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 ? "]" : "", (__extension__ ({ unsigned short int __v, __x
= (unsigned short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
4043 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__, 4046, "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 ? "]" : "", (__extension__ ({ unsigned short int __v, __x
= (unsigned short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
4044 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__, 4046, "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 ? "]" : "", (__extension__ ({ unsigned short int __v, __x
= (unsigned short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
4045 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__, 4046, "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 ? "]" : "", (__extension__ ({ unsigned short int __v, __x
= (unsigned short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
4046 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__, 4046, "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 ? "]" : "", (__extension__ ({ unsigned short int __v, __x
= (unsigned short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
;
4047#else
4048 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__, 4052, "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))
, "", (__extension__ ({ unsigned short int __v, __x = (unsigned
short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
4049 "",(((tport_log != ((void*)0) && 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__, 4052, "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))
, "", (__extension__ ({ unsigned short int __v, __x = (unsigned
short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
4050 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__, 4052, "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))
, "", (__extension__ ({ unsigned short int __v, __x = (unsigned
short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
4051 "",(((tport_log != ((void*)0) && 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__, 4052, "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))
, "", (__extension__ ({ unsigned short int __v, __x = (unsigned
short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
4052 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__, 4052, "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))
, "", (__extension__ ({ unsigned short int __v, __x = (unsigned
short int) (su->su_sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; })))) : (void)0)
;
4053#endif
4054
4055 su_freeaddrinfo(res);
4056
4057 return error;
4058}
4059
4060static int
4061msg_select_addrinfo(msg_t *msg, su_addrinfo_t *res)
4062{
4063 su_addrinfo_t *ai, *mai = msg_addrinfo(msg);
4064 su_sockaddr_t *su = (su_sockaddr_t *)mai->ai_addr;
4065
4066 for (ai = res; ai; ai = ai->ai_next) {
4067#if SU_HAVE_IN61
4068 if (ai->ai_family != AF_INET2 && ai->ai_family != AF_INET610)
4069 continue;
4070#else
4071 if (ai->ai_family != AF_INET2)
4072 continue;
4073#endif
4074
4075 if (ai->ai_protocol == 0)
4076 continue;
4077 if (ai->ai_addrlen > sizeof(su_sockaddr_t))
4078 continue;
4079
4080 mai->ai_family = ai->ai_family;
4081 mai->ai_socktype = ai->ai_socktype;
4082 mai->ai_protocol = ai->ai_protocol;
4083
4084 if (ai->ai_addrlen < sizeof(su_sockaddr_t))
4085 memset(su, 0, sizeof(su_sockaddr_t));
4086 memcpy(su, ai->ai_addr, ai->ai_addrlen);
4087 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))))
)
4088 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))))
;
4089 else
4090 mai->ai_addrlen = ai->ai_addrlen;
4091 return 0;
4092 }
4093
4094 msg_set_errno(msg, EAFNOSUPPORT97);
4095
4096 return -1;
4097}
4098
4099/** Copy peer address to msg */
4100void
4101tport_peer_address(tport_t *self, msg_t *msg)
4102{
4103 su_addrinfo_t *mai = msg_addrinfo(msg);
4104 su_addrinfo_t const *tai = self->tp_addrinfo;
4105 void *maddr = mai->ai_addr;
4106 int flags = mai->ai_flags;
4107
4108 memcpy(mai, tai, sizeof *mai);
4109 mai->ai_addr = memcpy(maddr, tai->ai_addr, tai->ai_addrlen);
4110 mai->ai_flags = flags;
4111}
4112
4113/** Process error event.
4114 *
4115 * Return events that can be processed afterwards.
4116 */
4117int tport_error_event(tport_t *self)
4118{
4119 int errcode;
4120 su_sockaddr_t name[1] = {{ 0 }};
4121
4122 name->su_familysu_sa.sa_family = AF_UNSPEC0; /* 0 */
4123
4124 if (tport_is_udp(self)) {
4125 errcode = tport_udp_error(self, name);
4126 }
4127 else {
4128 /* Process error event for basic transport. */
4129 errcode = su_soerror(self->tp_socket);
4130 }
4131
4132 if (errcode == 0 || errcode == EPIPE32)
4133 return errcode;
4134
4135 tport_error_report(self, errcode, name);
4136
4137 return 0;
4138}
4139
4140/** Mark message as waiting for a response.
4141 *
4142 * @return Positive integer, or -1 upon an error.
4143 */
4144int tport_pend(tport_t *self,
4145 msg_t *msg,
4146 tport_pending_error_f *callback,
4147 tp_client_t *client)
4148{
4149 tport_pending_t *pending;
4150
4151 if (self == NULL((void*)0) || callback == NULL((void*)0))
4152 return -1;
4153
4154 if (msg == NULL((void*)0) && tport_is_primary(self))
4155 return -1;
4156
4157 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__, 4160, "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)
4158 (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__, 4160, "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)
4159 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__, 4160, "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)
4160 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__, 4160, "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)
;
4161
4162 if (self->tp_released == NULL((void*)0)) {
4163 unsigned i, len = 8;
4164 if (self->tp_plen)
4165 len = 2 * self->tp_plen;
4166 pending = su_realloc(self->tp_home,
4167 self->tp_pending, len * sizeof(*pending));
4168 if (!pending) {
4169 msg_set_errno(msg, errno(*__errno_location ()));
4170 return -1;
4171 }
4172
4173 memset(pending + self->tp_plen, 0, (len - self->tp_plen) * sizeof(*pending));
4174
4175 for (i = self->tp_plen; i + 1 < len; i++)
4176 pending[i].p_client = pending + i + 1;
4177
4178 self->tp_released = pending + self->tp_plen;
4179 self->tp_pending = pending;
4180 self->tp_plen = len;
4181 }
4182
4183 pending = self->tp_released;
4184 self->tp_released = pending->p_client;
4185
4186 pending->p_callback = callback;
4187 pending->p_client = client;
4188 pending->p_msg = msg;
4189 pending->p_reported = self->tp_reported;
4190
4191 self->tp_pused++;
4192
4193 return (pending - self->tp_pending) + 1;
4194}
4195
4196/** Mark message as no more pending */
4197int tport_release(tport_t *self,
4198 int pendd,
4199 msg_t *msg,
4200 msg_t *reply,
4201 tp_client_t *client,
4202 int still_pending)
4203{
4204 tport_pending_t *pending;
4205
4206 if (self == NULL((void*)0) || pendd <= 0 || pendd > (int)self->tp_plen)
4207 return su_seterrno(EINVAL22), -1;
4208
4209 pending = self->tp_pending + (pendd - 1);
4210
4211 if (pending->p_client != client ||
4212 pending->p_msg != msg) {
4213 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__, 4215, "%s(%p): %u %p by %p not pending\n", __func__
, (void *)self, pendd, (void *)msg, (void *)client)) : (void)
0)
4214 __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__, 4215, "%s(%p): %u %p by %p not pending\n", __func__
, (void *)self, pendd, (void *)msg, (void *)client)) : (void)
0)
4215 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__, 4215, "%s(%p): %u %p by %p not pending\n", __func__
, (void *)self, pendd, (void *)msg, (void *)client)) : (void)
0)
;
4216 return su_seterrno(EINVAL22), -1;
4217 }
4218
4219 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__, 4222, "%s(%p): %p by %p with %p%s\n", __func__
, (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending
? " (preliminary)" : "")) : (void)0)
4220 __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__, 4222, "%s(%p): %p by %p with %p%s\n", __func__
, (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending
? " (preliminary)" : "")) : (void)0)
4221 (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__, 4222, "%s(%p): %p by %p with %p%s\n", __func__
, (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending
? " (preliminary)" : "")) : (void)0)
4222 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__, 4222, "%s(%p): %p by %p with %p%s\n", __func__
, (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending
? " (preliminary)" : "")) : (void)0)
;
4223
4224 /* sigcomp can here associate request (msg) with response (reply) */
4225
4226 if (still_pending)
4227 return 0;
4228
4229 /* Just to make sure nobody uses stale data */
4230 memset(pending, 0, sizeof(*pending));
4231 pending->p_client = self->tp_released;
4232 self->tp_released = pending;
4233 self->tp_pused--;
4234 return 0;
4235}
4236
4237/** Report error to pending messages with destination */
4238int
4239tport_pending_error(tport_t *self, su_sockaddr_t const *dst, int error)
4240{
4241 unsigned i, reported, callbacks;
4242 tport_pending_t *pending;
4243 msg_t *msg;
4244 su_addrinfo_t const *ai;
4245
4246 assert(self)((self) ? (void) (0) : __assert_fail ("self", "tport.c", 4246
, __PRETTY_FUNCTION__))
;
4247
4248 callbacks = 0;
4249 reported = ++self->tp_reported;
4250
4251 if (self->tp_pused == 0)
4252 return 0;
4253
4254 for (i = 0; i < self->tp_plen; i++) {
4255 pending = self->tp_pending + i;
4256
4257 if (!pending->p_callback)
4258 continue;
4259
4260 if (pending->p_reported == reported)
4261 continue;
4262
4263 msg = pending->p_msg;
4264
4265 if (dst && msg) {
4266 ai = msg_addrinfo(msg);
4267
4268 if (su_cmp_sockaddr(dst, (su_sockaddr_t *)ai->ai_addr) != 0)
4269 continue;
4270 }
4271
4272 msg_set_errno(msg, error);
4273
4274 pending->p_reported = reported;
4275
4276 pending->p_callback(self->TP_STACKtp_master->mr_stack, pending->p_client, self, msg, error);
4277
4278 callbacks++;
4279 }
4280
4281 return callbacks;
4282}
4283
4284
4285/** Report error via pending message */
4286int
4287tport_pending_errmsg(tport_t *self, msg_t *msg, int error)
4288{
4289 unsigned i, reported, callbacks;
4290 tport_pending_t *pending;
4291
4292 assert(self)((self) ? (void) (0) : __assert_fail ("self", "tport.c", 4292
, __PRETTY_FUNCTION__))
; assert(msg)((msg) ? (void) (0) : __assert_fail ("msg", "tport.c", 4292, __PRETTY_FUNCTION__
))
;
4293
4294 callbacks = 0;
4295 reported = ++self->tp_reported;
4296
4297 msg_set_errno(msg, error);
4298
4299 if (self->tp_pused == 0)
4300 return 0;
4301
4302 for (i = 0; i < self->tp_plen; i++) {
4303 pending = self->tp_pending + i;
4304
4305 if (!pending->p_client ||
4306 pending->p_msg != msg ||
4307 pending->p_reported == reported)
4308 continue;
4309
4310 pending->p_reported = reported;
4311
4312 pending->p_callback(self->TP_STACKtp_master->mr_stack, pending->p_client, self, msg, error);
4313
4314 callbacks++;
4315 }
4316
4317 return callbacks;
4318}
4319
4320
4321/** Set transport magic. */
4322void tport_set_magic(tport_t *self, tp_magic_t *magic)
4323{
4324 self->tp_magic = magic;
4325}
4326
4327/** Get transport magic. */
4328tp_magic_t *tport_magic(tport_t const *self)
4329{
4330 return self ? self->tp_magic : NULL((void*)0);
4331}
4332
4333/** Get primary transport (or self, if primary) */
4334tport_t *tport_parent(tport_t const *self)
4335{
4336 return self ? self->tp_pri->pri_primary : NULL((void*)0);
4337}
4338
4339/** Get list of primary transports */
4340tport_t *tport_primaries(tport_t const *self)
4341{
4342 if (self)
4343 return self->tp_master->mr_primaries->pri_primary;
4344 else
4345 return NULL((void*)0);
4346}
4347
4348/** Get next transport */
4349tport_t *tport_next(tport_t const *self)
4350{
4351 if (self == NULL((void*)0))
4352 return NULL((void*)0);
4353 else if (tport_is_master(self))
4354 return ((tport_master_t *)self)->mr_primaries->pri_primary;
4355
4356 else if (tport_is_primary(self))
4357 return ((tport_primary_t *)self)->pri_next->pri_primary;
4358 else
4359 return tprb_succ(self);
4360}
4361
4362/** Get secondary transports. */
4363tport_t *tport_secondary(tport_t const *self)
4364{
4365 if (tport_is_primary(self))
4366 return self->tp_pri->pri_open;
4367 else
4368 return NULL((void*)0);
4369}
4370
4371#if 0
4372void tport_hints(tport_t const *self, su_addrinfo_t *hints)
4373{
4374 hints->ai_protocol = self->tp_addrinfo->ai_protocol;
4375 hints->ai_socktype = self->tp_addrinfo->ai_socktype;
4376}
4377#endif
4378
4379/** Get transport address list. */
4380su_addrinfo_t const *tport_get_address(tport_t const *self)
4381{
4382 return self ? self->tp_addrinfo : NULL((void*)0);
4383}
4384
4385/** Get transport name. */
4386tp_name_t const *tport_name(tport_t const *self)
4387{
4388 return self->tp_name;
4389}
4390
4391/** Get transport identifier. */
4392char const *tport_ident(tport_t const *self)
4393{
4394 return self ? self->tp_identtp_name->tpn_ident : NULL((void*)0);
4395}
4396
4397/** Get transport by protocol name. */
4398tport_t *tport_by_protocol(tport_t const *self, char const *proto)
4399{
4400 if (proto && strcmp(proto, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(proto) && __builtin_constant_p (tpn_any) &&
(__s1_len = __builtin_strlen (proto), __s2_len = __builtin_strlen
(tpn_any), (!((size_t)(const void *)((proto) + 1) - (size_t)
(const void *)(proto) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((tpn_any) + 1) - (size_t)(const void
*)(tpn_any) == 1) || __s2_len >= 4)) ? __builtin_strcmp (
proto, tpn_any) : (__builtin_constant_p (proto) && ((
size_t)(const void *)((proto) + 1) - (size_t)(const void *)(proto
) == 1) && (__s1_len = __builtin_strlen (proto), __s1_len
< 4) ? (__builtin_constant_p (tpn_any) && ((size_t
)(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) ? __builtin_strcmp (proto, tpn_any) : (__extension__ (
{ const unsigned char *__s2 = (const unsigned char *) (const char
*) (tpn_any); int __result = (((const unsigned char *) (const
char *) (proto))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (proto))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (proto))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (proto))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) && (__s2_len =
__builtin_strlen (tpn_any), __s2_len < 4) ? (__builtin_constant_p
(proto) && ((size_t)(const void *)((proto) + 1) - (size_t
)(const void *)(proto) == 1) ? __builtin_strcmp (proto, tpn_any
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (proto); int __result = (((const unsigned
char *) (const char *) (tpn_any))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (tpn_any))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (tpn_any))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (tpn_any))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (proto, tpn_any)))); })
!= 0) {
4401 for (; self; self = tport_next(self))
4402 if (su_casematch(proto, self->tp_protonametp_name->tpn_proto))
4403 break;
4404 }
4405
4406 return (tport_t *)self;
4407}
4408
4409/** Get transport by protocol name. */
4410tport_t *tport_primary_by_name(tport_t const *tp, tp_name_t const *tpn)
4411{
4412 char const *ident = tpn->tpn_ident;
4413 char const *proto = tpn->tpn_proto;
4414 char const *comp = tpn->tpn_comp;
4415 int family = 0;
4416
4417 tport_primary_t const *self, *nocomp = NULL((void*)0);
4418
4419 self = tp ? tp->tp_master->mr_primaries : NULL((void*)0);
4420
4421 if (ident && strcmp(ident, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(ident) && __builtin_constant_p (tpn_any) &&
(__s1_len = __builtin_strlen (ident), __s2_len = __builtin_strlen
(tpn_any), (!((size_t)(const void *)((ident) + 1) - (size_t)
(const void *)(ident) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((tpn_any) + 1) - (size_t)(const void
*)(tpn_any) == 1) || __s2_len >= 4)) ? __builtin_strcmp (
ident, tpn_any) : (__builtin_constant_p (ident) && ((
size_t)(const void *)((ident) + 1) - (size_t)(const void *)(ident
) == 1) && (__s1_len = __builtin_strlen (ident), __s1_len
< 4) ? (__builtin_constant_p (tpn_any) && ((size_t
)(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) ? __builtin_strcmp (ident, tpn_any) : (__extension__ (
{ const unsigned char *__s2 = (const unsigned char *) (const char
*) (tpn_any); int __result = (((const unsigned char *) (const
char *) (ident))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (ident))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (ident))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (ident))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) && (__s2_len =
__builtin_strlen (tpn_any), __s2_len < 4) ? (__builtin_constant_p
(ident) && ((size_t)(const void *)((ident) + 1) - (size_t
)(const void *)(ident) == 1) ? __builtin_strcmp (ident, tpn_any
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (ident); int __result = (((const unsigned
char *) (const char *) (tpn_any))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (tpn_any))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (tpn_any))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (tpn_any))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (ident, tpn_any)))); })
== 0)
4422 ident = NULL((void*)0);
4423
4424 if (tpn->tpn_host == NULL((void*)0))
4425 family = 0;
4426#if SU_HAVE_IN61
4427 else if (host_is_ip6_address(tpn->tpn_host))
4428 family = AF_INET610;
4429#endif
4430 else if (host_is_ip4_address(tpn->tpn_host))
4431 family = AF_INET2;
4432 else
4433 family = 0;
4434
4435 if (proto && strcmp(proto, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(proto) && __builtin_constant_p (tpn_any) &&
(__s1_len = __builtin_strlen (proto), __s2_len = __builtin_strlen
(tpn_any), (!((size_t)(const void *)((proto) + 1) - (size_t)
(const void *)(proto) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((tpn_any) + 1) - (size_t)(const void
*)(tpn_any) == 1) || __s2_len >= 4)) ? __builtin_strcmp (
proto, tpn_any) : (__builtin_constant_p (proto) && ((
size_t)(const void *)((proto) + 1) - (size_t)(const void *)(proto
) == 1) && (__s1_len = __builtin_strlen (proto), __s1_len
< 4) ? (__builtin_constant_p (tpn_any) && ((size_t
)(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) ? __builtin_strcmp (proto, tpn_any) : (__extension__ (
{ const unsigned char *__s2 = (const unsigned char *) (const char
*) (tpn_any); int __result = (((const unsigned char *) (const
char *) (proto))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (proto))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (proto))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (proto))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) && (__s2_len =
__builtin_strlen (tpn_any), __s2_len < 4) ? (__builtin_constant_p
(proto) && ((size_t)(const void *)((proto) + 1) - (size_t
)(const void *)(proto) == 1) ? __builtin_strcmp (proto, tpn_any
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (proto); int __result = (((const unsigned
char *) (const char *) (tpn_any))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (tpn_any))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (tpn_any))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (tpn_any))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (proto, tpn_any)))); })
== 0)
4436 proto = NULL((void*)0);
4437
4438 if (!ident && !proto && !family && !comp)
4439 return (tport_t *)self; /* Anything goes */
4440
4441 comp = tport_canonize_comp(comp);
4442
4443 for (; self; self = self->pri_next) {
4444 tp = self->pri_primary;
4445
4446 if (ident && strcmp(ident, tp->tp_ident)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(ident) && __builtin_constant_p (tp->tp_name->
tpn_ident) && (__s1_len = __builtin_strlen (ident), __s2_len
= __builtin_strlen (tp->tp_name->tpn_ident), (!((size_t
)(const void *)((ident) + 1) - (size_t)(const void *)(ident) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
((tp->tp_name->tpn_ident) + 1) - (size_t)(const void *)
(tp->tp_name->tpn_ident) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(ident, tp->tp_name->tpn_ident) : (__builtin_constant_p
(ident) && ((size_t)(const void *)((ident) + 1) - (size_t
)(const void *)(ident) == 1) && (__s1_len = __builtin_strlen
(ident), __s1_len < 4) ? (__builtin_constant_p (tp->tp_name
->tpn_ident) && ((size_t)(const void *)((tp->tp_name
->tpn_ident) + 1) - (size_t)(const void *)(tp->tp_name->
tpn_ident) == 1) ? __builtin_strcmp (ident, tp->tp_name->
tpn_ident) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (tp->tp_name->tpn_ident
); int __result = (((const unsigned char *) (const char *) (ident
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (ident
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (ident
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (ident)
)[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
tp->tp_name->tpn_ident) && ((size_t)(const void
*)((tp->tp_name->tpn_ident) + 1) - (size_t)(const void
*)(tp->tp_name->tpn_ident) == 1) && (__s2_len =
__builtin_strlen (tp->tp_name->tpn_ident), __s2_len <
4) ? (__builtin_constant_p (ident) && ((size_t)(const
void *)((ident) + 1) - (size_t)(const void *)(ident) == 1) ?
__builtin_strcmp (ident, tp->tp_name->tpn_ident) : (- (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (ident); int __result = (((const unsigned char
*) (const char *) (tp->tp_name->tpn_ident))[0] - __s2[
0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (tp->tp_name->
tpn_ident))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tp->tp_name->tpn_ident))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (tp->tp_name->tpn_ident))[3] - __s2[
3]); } } __result; })))) : __builtin_strcmp (ident, tp->tp_name
->tpn_ident)))); })
)
4447 continue;
4448 if (family) {
4449 if (family == AF_INET2 && !tport_has_ip4(tp))
4450 continue;
4451#if SU_HAVE_IN61
4452 if (family == AF_INET610 && !tport_has_ip6(tp))
4453 continue;
4454#endif
4455 }
4456 if (proto && !su_casematch(proto, tp->tp_protonametp_name->tpn_proto))
4457 continue;
4458
4459 if (comp && comp != tp->tp_name->tpn_comp) {
4460 if (tp->tp_name->tpn_comp == NULL((void*)0) && nocomp == NULL((void*)0))
4461 nocomp = self;
4462 continue;
4463 }
4464
4465 break;
4466 }
4467
4468 if (self)
4469 return (tport_t *)self;
4470 else
4471 return (tport_t *)nocomp;
4472}
4473
4474
4475/** Get transport by name. */
4476tport_t *tport_by_name(tport_t const *self, tp_name_t const *tpn)
4477{
4478 tport_t const *sub, *next;
4479 char const *canon, *host, *port, *comp;
4480#if SU_HAVE_IN61
4481 char *end, ipaddr[TPORT_HOSTPORTSIZE(55)];
4482#endif
4483
4484 assert(self)((self) ? (void) (0) : __assert_fail ("self", "tport.c", 4484
, __PRETTY_FUNCTION__))
; assert(tpn)((tpn) ? (void) (0) : __assert_fail ("tpn", "tport.c", 4484, __PRETTY_FUNCTION__
))
;
4485
4486 assert(tpn->tpn_proto)((tpn->tpn_proto) ? (void) (0) : __assert_fail ("tpn->tpn_proto"
, "tport.c", 4486, __PRETTY_FUNCTION__))
; assert(tpn->tpn_host)((tpn->tpn_host) ? (void) (0) : __assert_fail ("tpn->tpn_host"
, "tport.c", 4486, __PRETTY_FUNCTION__))
; assert(tpn->tpn_port)((tpn->tpn_port) ? (void) (0) : __assert_fail ("tpn->tpn_port"
, "tport.c", 4486, __PRETTY_FUNCTION__))
;
4487 assert(tpn->tpn_canon)((tpn->tpn_canon) ? (void) (0) : __assert_fail ("tpn->tpn_canon"
, "tport.c", 4487, __PRETTY_FUNCTION__))
;
4488
4489 if (!tport_is_primary(self))
4490 self = tport_primary_by_name(self, tpn);
4491
4492 host = strcmp(tpn->tpn_host, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tpn->tpn_host) && __builtin_constant_p (tpn_any)
&& (__s1_len = __builtin_strlen (tpn->tpn_host), __s2_len
= __builtin_strlen (tpn_any), (!((size_t)(const void *)((tpn
->tpn_host) + 1) - (size_t)(const void *)(tpn->tpn_host
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)((tpn_any) + 1) - (size_t)(const void *)(tpn_any) == 1) ||
__s2_len >= 4)) ? __builtin_strcmp (tpn->tpn_host, tpn_any
) : (__builtin_constant_p (tpn->tpn_host) && ((size_t
)(const void *)((tpn->tpn_host) + 1) - (size_t)(const void
*)(tpn->tpn_host) == 1) && (__s1_len = __builtin_strlen
(tpn->tpn_host), __s1_len < 4) ? (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) ? __builtin_strcmp (tpn
->tpn_host, tpn_any) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn_any); int
__result = (((const unsigned char *) (const char *) (tpn->
tpn_host))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn->tpn_host))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (tpn->tpn_host))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (tpn->tpn_host))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (tpn_any) && ((size_t)
(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) && (__s2_len = __builtin_strlen (tpn_any), __s2_len
< 4) ? (__builtin_constant_p (tpn->tpn_host) &&
((size_t)(const void *)((tpn->tpn_host) + 1) - (size_t)(const
void *)(tpn->tpn_host) == 1) ? __builtin_strcmp (tpn->
tpn_host, tpn_any) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn->tpn_host
); int __result = (((const unsigned char *) (const char *) (tpn_any
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tpn_any
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tpn_any
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (tpn_any
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (tpn
->tpn_host, tpn_any)))); })
? tpn->tpn_host : NULL((void*)0);
4493 port = strcmp(tpn->tpn_port, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tpn->tpn_port) && __builtin_constant_p (tpn_any)
&& (__s1_len = __builtin_strlen (tpn->tpn_port), __s2_len
= __builtin_strlen (tpn_any), (!((size_t)(const void *)((tpn
->tpn_port) + 1) - (size_t)(const void *)(tpn->tpn_port
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)((tpn_any) + 1) - (size_t)(const void *)(tpn_any) == 1) ||
__s2_len >= 4)) ? __builtin_strcmp (tpn->tpn_port, tpn_any
) : (__builtin_constant_p (tpn->tpn_port) && ((size_t
)(const void *)((tpn->tpn_port) + 1) - (size_t)(const void
*)(tpn->tpn_port) == 1) && (__s1_len = __builtin_strlen
(tpn->tpn_port), __s1_len < 4) ? (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) ? __builtin_strcmp (tpn
->tpn_port, tpn_any) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn_any); int
__result = (((const unsigned char *) (const char *) (tpn->
tpn_port))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn->tpn_port))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (tpn->tpn_port))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (tpn->tpn_port))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (tpn_any) && ((size_t)
(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) && (__s2_len = __builtin_strlen (tpn_any), __s2_len
< 4) ? (__builtin_constant_p (tpn->tpn_port) &&
((size_t)(const void *)((tpn->tpn_port) + 1) - (size_t)(const
void *)(tpn->tpn_port) == 1) ? __builtin_strcmp (tpn->
tpn_port, tpn_any) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn->tpn_port
); int __result = (((const unsigned char *) (const char *) (tpn_any
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tpn_any
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (tpn_any
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (tpn_any
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (tpn
->tpn_port, tpn_any)))); })
? tpn->tpn_port : NULL((void*)0);
4494 canon = tpn->tpn_canon;
4495 comp = tport_canonize_comp(tpn->tpn_comp);
4496
4497 if (self && host && port) {
4498 int resolved = 0, cmp;
4499 socklen_t sulen;
4500 su_sockaddr_t su[1];
4501
4502 sub = self->tp_pri->pri_open;
4503
4504 memset(su, 0, sizeof su);
4505
4506#if SU_HAVE_IN61
4507 if (host_is_ip6_reference(host)) {
4508 /* Remove [] around IPv6 address */
4509 host = strncpy(ipaddr, host + 1, sizeof(ipaddr) - 1)__builtin_strncpy (ipaddr, host + 1, sizeof(ipaddr) - 1);
4510 ipaddr[sizeof(ipaddr) - 1] = '\0';
4511 if ((end = strchr(host, ']')(__extension__ (__builtin_constant_p (']') && !__builtin_constant_p
(host) && (']') == '\0' ? (char *) __rawmemchr (host
, ']') : __builtin_strchr (host, ']')))
))
4512 *end = 0;
4513 su->su_lensu_array[0] = sulen = (socklen_t) sizeof (struct sockaddr_in6);
4514 su->su_familysu_sa.sa_family = AF_INET610;
4515 }
4516 else if (host_is_ip6_address(host)) {
4517 su->su_lensu_array[0] = sulen = (socklen_t) sizeof (struct sockaddr_in6);
4518 su->su_familysu_sa.sa_family = AF_INET610;
4519 }
4520 else
4521#endif
4522 {
4523 su->su_lensu_array[0] = sulen = (socklen_t) sizeof (struct sockaddr_in);
4524 su->su_familysu_sa.sa_family = AF_INET2;
4525 }
4526
4527 su->su_portsu_sin.sin_port = htons(strtoul(port, NULL, 10))(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (strtoul(port, ((void*)0), 10)); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; }))
;
4528
4529 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) {
4530 resolved = 1;
4531 next = NULL((void*)0);
4532
4533 /* Depth-first search */
4534 while (sub) {
4535 cmp = (int)((size_t)sub->tp_addrlentp_addrinfo->ai_addrlen - (size_t)sulen);
4536
4537 if (cmp == 0)
4538 cmp = memcmp(sub->tp_addr, su, sulen);
4539
4540 if (cmp == 0) {
4541 if (sub->tp_left) {
4542 next = sub;
4543 sub = sub->tp_left;
4544 continue;
4545 }
4546 break;
4547 }
4548 else if (next) {
4549 sub = next;
4550 break;
4551 }
4552 else if (cmp > 0) {
4553 sub = sub->tp_left;
4554 continue;
4555 }
4556 else /* if (cmp < 0) */ {
4557 sub = sub->tp_right;
4558 continue;
4559 }
4560 }
4561 }
4562 else {
4563 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__, 4564, "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)
4564 (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__, 4564, "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)
;
4565
4566 sub = tprb_first(sub);
4567 }
4568
4569 for (; sub; sub = tprb_succ(sub)) {
4570 if (!sub->tp_reusable)
4571 continue;
4572 if (!tport_is_registered(sub))
4573 continue;
4574 if (tport_is_shutdown(sub))
4575 continue;
4576
4577 if (comp != sub->tp_name->tpn_comp)
4578 continue;
4579
4580 if (resolved) {
4581 if ((socklen_t)sub->tp_addrlentp_addrinfo->ai_addrlen != sulen ||
4582 memcmp(sub->tp_addr, su, sulen)) {
4583 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__, 4584, "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)
4584 (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__, 4584, "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)
;
4585 break;
4586 }
4587 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__, 4588, "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)
4588 (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__, 4588, "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)
;
4589 }
4590 else if (!su_casematch(port, sub->tp_porttp_name->tpn_port))
4591 continue;
4592 else if (!su_casematch(canon, sub->tp_canontp_name->tpn_canon) &&
4593 !su_casematch(host, sub->tp_hosttp_name->tpn_host))
4594 continue;
4595
4596 return (tport_t *)sub;
4597 }
4598 }
4599
4600 return (tport_t *)self;
4601}
4602
4603/** Get transport from primary by addrinfo. */
4604tport_t *tport_by_addrinfo(tport_primary_t const *pri,
4605 su_addrinfo_t const *ai,
4606 tp_name_t const *tpn)
4607{
4608 tport_t const *sub, *maybe;
4609 struct sockaddr const *sa;
4610 int cmp;
4611 char const *comp;
4612
4613 assert(pri)((pri) ? (void) (0) : __assert_fail ("pri", "tport.c", 4613, __PRETTY_FUNCTION__
))
; assert(ai)((ai) ? (void) (0) : __assert_fail ("ai", "tport.c", 4613, __PRETTY_FUNCTION__
))
;
4614
4615 sa = ai->ai_addr;
4616
4617 sub = pri->pri_open, maybe = NULL((void*)0);
4618
4619 comp = tport_canonize_comp(tpn->tpn_comp);
4620
4621 /* Find leftmost (prevmost) matching tport */
4622 while (sub) {
4623 cmp = (int)(sub->tp_addrlentp_addrinfo->ai_addrlen - ai->ai_addrlen);
4624 if (cmp == 0)
4625 cmp = memcmp(sub->tp_addr, sa, ai->ai_addrlen);
4626
4627 if (cmp == 0) {
4628 if (sub->tp_left) {
4629 maybe = sub;
4630 sub = sub->tp_left;
4631 continue;
4632 }
4633 break;
4634 }
4635 else if (maybe) {
4636 sub = maybe;
4637 break;
4638 }
4639 else if (cmp > 0) {
4640 sub = sub->tp_left;
4641 continue;
4642 }
4643 else /* if (cmp < 0) */ {
4644 sub = sub->tp_right;
4645 continue;
4646 }
4647 }
4648
4649 for (; sub; sub = tprb_succ(sub)) {
4650 if (!sub->tp_reusable)
4651 continue;
4652 if (!tport_is_registered(sub))
4653 continue;
4654 if (tport_is_shutdown(sub))
4655 continue;
4656
4657 if (tport_has_tls(sub) && !su_casematch(tpn->tpn_canon, sub->tp_name->tpn_canon)) {
4658 if (!tport_is_verified(sub))
4659 continue;
4660 if (!tport_subject_search(tpn->tpn_canon, sub->tp_subjects))
4661 continue;
4662 }
4663
4664 if (comp != sub->tp_name->tpn_comp)
4665 continue;
4666
4667 if (sub->tp_addrlentp_addrinfo->ai_addrlen != ai->ai_addrlen
4668 || memcmp(sub->tp_addr, sa, ai->ai_addrlen)) {
4669 sub = NULL((void*)0);
4670 break;
4671 }
4672 break;
4673 }
4674
4675 if (sub)
4676 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__, 4677, "%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)
4677 __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__, 4677, "%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)
;
4678 else
4679 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__, 4680, "%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)
4680 __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__, 4680, "%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)
;
4681
4682 return (tport_t *)sub;
4683}
4684
4685
4686/** Get transport name from URL. */
4687int tport_name_by_url(su_home_t *home,
4688 tp_name_t *tpn,
4689 url_string_t const *us)
4690{
4691 size_t n;
4692 url_t url[1];
4693 char *b;
4694
4695 n = url_xtra(us->us_url);
4696 b = su_alloc(home, n);
4697
4698 if (b == NULL((void*)0) || url_dup(b, n, url, us->us_url) < 0) {
4699 su_free(home, b);
4700 return -1;
4701 }
4702
4703 tpn->tpn_proto = url_tport_default((enum url_type_e)url->url_type);
4704 tpn->tpn_canon = url->url_host;
4705 tpn->tpn_host = url->url_host;
4706 tpn->tpn_port = url_port(url);
4707
4708 if (tpn->tpn_host == NULL((void*)0) || tpn->tpn_host[0] == '\0' ||
4709 tpn->tpn_port == NULL((void*)0) || tpn->tpn_port[0] == '\0') {
4710 su_free(home, b);
4711 return -1;
4712 }
4713
4714 if (url->url_params) {
4715 for (b = (char *)url->url_params; b[0]; b += n) {
4716 n = strcspn(b, ";")__extension__ ({ char __r0, __r1, __r2; (__builtin_constant_p
(";") && ((size_t)(const void *)((";") + 1) - (size_t
)(const void *)(";") == 1) ? ((__builtin_constant_p (b) &&
((size_t)(const void *)((b) + 1) - (size_t)(const void *)(b)
== 1)) ? __builtin_strcspn (b, ";") : ((__r0 = ((const char *
) (";"))[0], __r0 == '\0') ? strlen (b) : ((__r1 = ((const char
*) (";"))[1], __r1 == '\0') ? __strcspn_c1 (b, __r0) : ((__r2
= ((const char *) (";"))[2], __r2 == '\0') ? __strcspn_c2 (b
, __r0, __r1) : (((const char *) (";"))[3] == '\0' ? __strcspn_c3
(b, __r0, __r1, __r2) : __builtin_strcspn (b, ";")))))) : __builtin_strcspn
(b, ";")); })
;
4717
4718 if (n > 10 && su_casenmatch(b, "transport=", 10))
4719 tpn->tpn_proto = b + 10;
4720 else if (n > 6 && su_casenmatch(b, "maddr=", 6))
4721 tpn->tpn_host = b + 6;
4722
4723 if (b[n])
4724 b[n++] = '\0';
4725 }
4726 }
4727
4728 return 0;
4729}
4730
4731/** Check if transport named is already resolved */
4732int tport_name_is_resolved(tp_name_t const *tpn)
4733{
4734 if (!tpn->tpn_host)
4735 return 0;
4736
4737 return host_is_ip_address(tpn->tpn_host);
4738}
4739
4740/** Duplicate name.
4741 *
4742 * The tport_name_dup() function copies strings belonging to the transport
4743 * name. It returns the copied strings via the @a dst transport name
4744 * structure. The memory block required for copies is allocated from the
4745 * memory @a home. Please note that only one memory block is allocated, so
4746 * the memory can be reclainmed only by deinitializing the memory home
4747 * itself.
4748 *
4749 * @retval 0 when successful
4750 * @retval -1 upon an error
4751 */
4752int tport_name_dup(su_home_t *home,
4753 tp_name_t *dst,
4754 tp_name_t const *src)
4755{
4756 size_t n_proto, n_host, n_port, n_canon, n_comp = 0;
4757 char *s;
4758
4759 if (!src->tpn_proto || !src->tpn_host || !src->tpn_port || !src->tpn_canon)
4760 return -1;
4761
4762 if (strcmp(src->tpn_proto, tpn_any)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(src->tpn_proto) && __builtin_constant_p (tpn_any
) && (__s1_len = __builtin_strlen (src->tpn_proto)
, __s2_len = __builtin_strlen (tpn_any), (!((size_t)(const void
*)((src->tpn_proto) + 1) - (size_t)(const void *)(src->
tpn_proto) == 1) || __s1_len >= 4) && (!((size_t)(
const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (src->tpn_proto
, tpn_any) : (__builtin_constant_p (src->tpn_proto) &&
((size_t)(const void *)((src->tpn_proto) + 1) - (size_t)(
const void *)(src->tpn_proto) == 1) && (__s1_len =
__builtin_strlen (src->tpn_proto), __s1_len < 4) ? (__builtin_constant_p
(tpn_any) && ((size_t)(const void *)((tpn_any) + 1) -
(size_t)(const void *)(tpn_any) == 1) ? __builtin_strcmp (src
->tpn_proto, tpn_any) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (tpn_any); int
__result = (((const unsigned char *) (const char *) (src->
tpn_proto))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
src->tpn_proto))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (src->tpn_proto))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (src->tpn_proto))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (tpn_any) && ((size_t)
(const void *)((tpn_any) + 1) - (size_t)(const void *)(tpn_any
) == 1) && (__s2_len = __builtin_strlen (tpn_any), __s2_len
< 4) ? (__builtin_constant_p (src->tpn_proto) &&
((size_t)(const void *)((src->tpn_proto) + 1) - (size_t)(
const void *)(src->tpn_proto) == 1) ? __builtin_strcmp (src
->tpn_proto, tpn_any) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (src->
tpn_proto); int __result = (((const unsigned char *) (const char
*) (tpn_any))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn_any))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tpn_any))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (tpn_any
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (src
->tpn_proto, tpn_any)))); })
)
4763 n_proto = strlen(src->tpn_proto) + 1;
4764 else
4765 n_proto = 0;
4766
4767 n_host = strlen(src->tpn_host) + 1;
4768
4769 n_port = strlen(src->tpn_port) + 1;
4770
4771 if (src->tpn_comp != NULL((void*)0))
4772 n_comp = strlen(src->tpn_comp) + 1;
4773
4774 if (src->tpn_canon != src->tpn_host &&
4775 strcmp(src->tpn_canon, src->tpn_host)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(src->tpn_canon) && __builtin_constant_p (src->
tpn_host) && (__s1_len = __builtin_strlen (src->tpn_canon
), __s2_len = __builtin_strlen (src->tpn_host), (!((size_t
)(const void *)((src->tpn_canon) + 1) - (size_t)(const void
*)(src->tpn_canon) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((src->tpn_host) + 1) - (size_t)(const
void *)(src->tpn_host) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(src->tpn_canon, src->tpn_host) : (__builtin_constant_p
(src->tpn_canon) && ((size_t)(const void *)((src->
tpn_canon) + 1) - (size_t)(const void *)(src->tpn_canon) ==
1) && (__s1_len = __builtin_strlen (src->tpn_canon
), __s1_len < 4) ? (__builtin_constant_p (src->tpn_host
) && ((size_t)(const void *)((src->tpn_host) + 1) -
(size_t)(const void *)(src->tpn_host) == 1) ? __builtin_strcmp
(src->tpn_canon, src->tpn_host) : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(src->tpn_host); int __result = (((const unsigned char *)
(const char *) (src->tpn_canon))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (src->tpn_canon))[1] - __s2[1]); if
(__s1_len > 1 && __result == 0) { __result = (((const
unsigned char *) (const char *) (src->tpn_canon))[2] - __s2
[2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (src->tpn_canon)
)[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
src->tpn_host) && ((size_t)(const void *)((src->
tpn_host) + 1) - (size_t)(const void *)(src->tpn_host) == 1
) && (__s2_len = __builtin_strlen (src->tpn_host),
__s2_len < 4) ? (__builtin_constant_p (src->tpn_canon)
&& ((size_t)(const void *)((src->tpn_canon) + 1) -
(size_t)(const void *)(src->tpn_canon) == 1) ? __builtin_strcmp
(src->tpn_canon, src->tpn_host) : (- (__extension__ ({
const unsigned char *__s2 = (const unsigned char *) (const char
*) (src->tpn_canon); int __result = (((const unsigned char
*) (const char *) (src->tpn_host))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (src->tpn_host))[1] - __s2[1]); if
(__s2_len > 1 && __result == 0) { __result = (((const
unsigned char *) (const char *) (src->tpn_host))[2] - __s2
[2]); if (__s2_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (src->tpn_host))
[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (src->
tpn_canon, src->tpn_host)))); })
)
4776 n_canon = strlen(src->tpn_canon) + 1;
4777 else
4778 n_canon = 0;
4779
4780 s = su_alloc(home, n_proto + n_canon + n_host + n_port + n_comp);
4781 if (s == NULL((void*)0))
4782 return -1;
4783
4784 if (n_proto)
4785 dst->tpn_proto = memcpy(s, src->tpn_proto, n_proto), s += n_proto;
4786 else
4787 dst->tpn_proto = tpn_any;
4788
4789 dst->tpn_host = memcpy(s, src->tpn_host, n_host), s += n_host;
4790 dst->tpn_port = memcpy(s, src->tpn_port, n_port), s += n_port;
4791
4792 if (n_canon)
4793 dst->tpn_canon = memcpy(s, src->tpn_canon, n_canon), s += n_canon;
4794 else
4795 dst->tpn_canon = dst->tpn_host;
4796
4797 if (n_comp)
4798 dst->tpn_comp = memcpy(s, src->tpn_comp, n_comp), s += n_comp;
4799 else
4800 dst->tpn_comp = NULL((void*)0);
4801
4802 return 0;
4803}
4804
4805/** Convert a sockaddr structure into printable form. */
4806char *tport_hostport(char buf[], isize_t bufsize,
4807 su_sockaddr_t const *su,
4808 int with_port_and_brackets)
4809{
4810 char *b = buf;
4811 size_t n;
4812
4813#if SU_HAVE_IN61
4814 if (with_port_and_brackets > 1 || su->su_familysu_sa.sa_family == AF_INET610) {
4815 *b++ = '['; bufsize--;
4816 }
4817#endif
4818
4819 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))
4820 return NULL((void*)0);
4821 n = strlen(b);
4822 if (bufsize < n + 2)
4823 return NULL((void*)0);
4824
4825 bufsize -= n; b += n;
4826
4827#if SU_HAVE_IN61
4828 if (with_port_and_brackets > 1 || su->su_familysu_sa.sa_family == AF_INET610) {
4829 *b++ = ']'; bufsize--;
4830 }
4831 if (with_port_and_brackets) {
4832 unsigned short port = ntohs(su->su_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (su->su_sin.sin_port); if (__builtin_constant_p (__x
)) __v = ((unsigned short int) ((((__x) >> 8) & 0xff
) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; }))
;
4833 if (port != 0) {
4834 n = snprintf(b, bufsize, ":%u", port);
4835 if (n <= 0)
4836 return NULL((void*)0);
4837 b += n;
4838 if (bufsize > n)
4839 bufsize -= n;
4840 else
4841 bufsize = 0;
4842 }
4843 }
4844#endif
4845
4846 if (bufsize)
4847 *b++ = 0;
4848
4849 return buf;
4850}
4851
4852/** @internal Update receive statistics. */
4853void tport_recv_bytes(tport_t *self, ssize_t bytes, ssize_t on_line)
4854{
4855 self->tp_stats.recv_bytes += bytes;
4856 self->tp_stats.recv_on_line += on_line;
4857
4858 if (self != self->tp_pri->pri_primary) {
4859 self = self->tp_pri->pri_primary;
4860 self->tp_stats.recv_bytes += bytes;
4861 self->tp_stats.recv_on_line += on_line;
4862 }
4863 self = self->tp_master->mr_master;
4864 self->tp_stats.recv_bytes += bytes;
4865 self->tp_stats.recv_on_line += on_line;
4866}
4867
4868/** @internal Update message-based receive statistics. */
4869void tport_recv_message(tport_t *self, msg_t *msg, int error)
4870{
4871 error = error != 0;
4872
4873 self->tp_stats.recv_msgs++;
4874 self->tp_stats.recv_errors += error;
4875
4876 if (self != self->tp_pri->pri_primary) {
4877 self = self->tp_pri->pri_primary;
4878 self->tp_stats.recv_msgs++;
4879 self->tp_stats.recv_errors += error;
4880 }
4881
4882 self = self->tp_master->mr_master;
4883
4884 self->tp_stats.recv_msgs++;
4885 self->tp_stats.recv_errors += error;
4886}
4887
4888/** @internal Update send statistics. */
4889void tport_sent_bytes(tport_t *self, ssize_t bytes, ssize_t on_line)
4890{
4891 self->tp_stats.sent_bytes += bytes;
4892 self->tp_stats.sent_on_line += on_line;
4893
4894 if (self != self->tp_pri->pri_primary) {
4895 self = self->tp_pri->pri_primary;
4896 self->tp_stats.sent_bytes += bytes;
4897 self->tp_stats.sent_on_line += on_line;
4898 }
4899
4900 self = self->tp_master->mr_master;
4901 self->tp_stats.sent_bytes += bytes;
4902 self->tp_stats.sent_on_line += on_line;
4903}
4904
4905/** @internal Update message-based send statistics. */
4906void tport_sent_message(tport_t *self, msg_t *msg, int error)
4907{
4908 self->tp_slogged = NULL((void*)0);
4909
4910 error = error != 0;
4911
4912 self->tp_stats.sent_msgs++;
4913 self->tp_stats.sent_errors += error;
4914
4915 if (self != self->tp_pri->pri_primary) {
4916 self = self->tp_pri->pri_primary;
4917 self->tp_stats.sent_msgs++;
4918 self->tp_stats.sent_errors += error;
4919 }
4920
4921 self = self->tp_master->mr_master;
4922
4923 self->tp_stats.sent_msgs++;
4924 self->tp_stats.sent_errors += error;
4925
4926}