Bug Summary

File:libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c
Location:line 515, column 5
Description:Value stored to 'why' is never read

Annotated Source Code

1/*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2006 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_type_tcp.c TCP Transport
26 *
27 * See tport.docs for more detailed description of tport interface.
28 *
29 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
30 * @author Martti Mela <Martti.Mela@nokia.com>
31 *
32 * @date Created: Fri Mar 24 08:45:49 EET 2006 ppessi
33 */
34
35#include "config.h"
36
37#include "tport_internal.h"
38
39#if HAVE_NETINET_TCP_H1
40#include <netinet/tcp.h>
41#endif
42
43#ifndef SOL_TCP6
44#define SOL_TCP6 IPPROTO_TCPIPPROTO_TCP
45#endif
46
47#include <stdlib.h>
48#include <string.h>
49#include <time.h>
50#include <assert.h>
51#include <errno(*__errno_location ()).h>
52#include <limits.h>
53
54#if HAVE_FUNC1
55#elif HAVE_FUNCTION1
56#define __func__ __FUNCTION__
57#else
58static char const __func__[] = "tport_type_tcp";
59#endif
60
61/* ---------------------------------------------------------------------- */
62/* TCP */
63
64tport_vtable_t const tport_tcp_vtable =
65{
66 /* vtp_name */ "tcp",
67 /* vtp_public */ tport_type_local,
68 /* vtp_pri_size */ sizeof (tport_primary_t),
69 /* vtp_init_primary */ tport_tcp_init_primary,
70 /* vtp_deinit_primary */ NULL((void*)0),
71 /* vtp_wakeup_pri */ tport_accept,
72 /* vtp_connect */ NULL((void*)0),
73 /* vtp_secondary_size */ sizeof (tport_t),
74 /* vtp_init_secondary */ tport_tcp_init_secondary,
75 /* vtp_deinit_secondary */ NULL((void*)0),
76 /* vtp_shutdown */ NULL((void*)0),
77 /* vtp_set_events */ NULL((void*)0),
78 /* vtp_wakeup */ NULL((void*)0),
79 /* vtp_recv */ tport_recv_stream,
80 /* vtp_send */ tport_send_stream,
81 /* vtp_deliver */ NULL((void*)0),
82 /* vtp_prepare */ NULL((void*)0),
83 /* vtp_keepalive */ NULL((void*)0),
84 /* vtp_stun_response */ NULL((void*)0),
85 /* vtp_next_secondary_timer*/ tport_tcp_next_timer,
86 /* vtp_secondary_timer */ tport_tcp_timer,
87};
88
89tport_vtable_t const tport_tcp_client_vtable =
90{
91 /* vtp_name */ "tcp",
92 /* vtp_public */ tport_type_client,
93 /* vtp_pri_size */ sizeof (tport_primary_t),
94 /* vtp_init_primary */ tport_tcp_init_client,
95 /* vtp_deinit_primary */ NULL((void*)0),
96 /* vtp_wakeup_pri */ NULL((void*)0),
97 /* vtp_connect */ NULL((void*)0),
98 /* vtp_secondary_size */ sizeof (tport_t),
99 /* vtp_init_secondary */ tport_tcp_init_secondary,
100 /* vtp_deinit_secondary */ NULL((void*)0),
101 /* vtp_shutdown */ NULL((void*)0),
102 /* vtp_set_events */ NULL((void*)0),
103 /* vtp_wakeup */ NULL((void*)0),
104 /* vtp_recv */ tport_recv_stream,
105 /* vtp_send */ tport_send_stream,
106 /* vtp_deliver */ NULL((void*)0),
107 /* vtp_prepare */ NULL((void*)0),
108 /* vtp_keepalive */ NULL((void*)0),
109 /* vtp_stun_response */ NULL((void*)0),
110 /* vtp_next_secondary_timer*/ tport_tcp_next_timer,
111 /* vtp_secondary_timer */ tport_tcp_timer,
112};
113
114static int tport_tcp_setsndbuf(int socket, int atleast);
115
116int tport_tcp_init_primary(tport_primary_t *pri,
117 tp_name_t tpn[1],
118 su_addrinfo_t *ai,
119 tagi_t const *tags,
120 char const **return_culprit)
121{
122 int socket;
123
124 socket = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
125
126 if (socket == INVALID_SOCKET((su_socket_t)INVALID_SOCKET))
127 return *return_culprit = "socket", -1;
128
129 tport_tcp_setsndbuf(socket, 64 * 1024);
130
131 return tport_stream_init_primary(pri, socket, tpn, ai, tags, return_culprit);
132}
133
134int tport_stream_init_primary(tport_primary_t *pri,
135 su_socket_t socket,
136 tp_name_t tpn[1],
137 su_addrinfo_t *ai,
138 tagi_t const *tags,
139 char const **return_culprit)
140{
141 pri->pri_primary->tp_socket = socket;
142
143 /* Set IP TOS if set */
144 tport_set_tos(socket, ai, pri->pri_params->tpp_tos);
145
146#if defined(__linux__1)
147 /* Linux does not allow reusing TCP port while this one is open,
148 so we can safely call su_setreuseaddr() before bind(). */
149 su_setreuseaddr(socket, 1);
150#endif
151
152 if (tport_bind_socket(socket, ai, return_culprit) == -1)
153 return -1;
154
155 if (listen(socket, pri->pri_params->tpp_qsize) == SOCKET_ERRORSOCKET_ERROR)
156 return *return_culprit = "listen", -1;
157
158#if !defined(__linux__1)
159 /* Allow reusing TCP sockets
160 *
161 * On Solaris & BSD, call setreuseaddr() after bind in order to avoid
162 * binding to a port owned by an existing server.
163 */
164 su_setreuseaddr(socket, 1);
165#endif
166
167 pri->pri_primary->tp_events = SU_WAIT_ACCEPT(0x001);
168 pri->pri_primary->tp_conn_orient = 1;
169
170 return 0;
171}
172
173int tport_tcp_init_client(tport_primary_t *pri,
174 tp_name_t tpn[1],
175 su_addrinfo_t *ai,
176 tagi_t const *tags,
177 char const **return_culprit)
178{
179 pri->pri_primary->tp_conn_orient = 1;
180
181 return 0;
182}
183
184int tport_tcp_init_secondary(tport_t *self, int socket, int accepted,
185 char const **return_reason)
186{
187 int val = 1;
188
189 self->tp_has_connection = 1;
190
191 self->tp_params->tpp_idle = UINT_MAX(2147483647 *2U +1U);
192
193 if (setsockopt(socket, SOL_TCP6, TCP_NODELAY1, (void *)&val, sizeof val) == -1)
194 return *return_reason = "TCP_NODELAY", -1;
195
196#if defined(SO_KEEPALIVE9)
197 setsockopt(socket, SOL_SOCKET1, SO_KEEPALIVE9, (void *)&val, sizeof val);
198#endif
199 val = (int)(self->tp_params->tpp_socket_keepalive);
200#if defined(TCP_KEEPIDLE4)
201 if (val != 0 && val != UINT_MAX(2147483647 *2U +1U)) {
202 SU_DEBUG_3(("%s(%p): Setting TCP_KEEPIDLE to %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)) >= 3 ? (_su_llog(tport_log, 3, "tport_type_tcp.c"
, (const char *)__func__, 203, "%s(%p): Setting TCP_KEEPIDLE to %d\n"
, __func__, (void *)self, val)) : (void)0)
203 __func__, (void *)self, val))(((tport_log != ((void*)0) && 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_type_tcp.c"
, (const char *)__func__, 203, "%s(%p): Setting TCP_KEEPIDLE to %d\n"
, __func__, (void *)self, val)) : (void)0)
;
204 setsockopt(socket, SOL_TCP6, TCP_KEEPIDLE4, (void *)&val, sizeof val);}
205#endif
206#if defined(TCP_KEEPINTVL5)
207 if (val != 0 && val != UINT_MAX(2147483647 *2U +1U)) {
208 SU_DEBUG_3(("%s(%p): Setting TCP_KEEPINTVL to %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)) >= 3 ? (_su_llog(tport_log, 3, "tport_type_tcp.c"
, (const char *)__func__, 209, "%s(%p): Setting TCP_KEEPINTVL to %d\n"
, __func__, (void *)self, val)) : (void)0)
209 __func__, (void *)self, val))(((tport_log != ((void*)0) && 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_type_tcp.c"
, (const char *)__func__, 209, "%s(%p): Setting TCP_KEEPINTVL to %d\n"
, __func__, (void *)self, val)) : (void)0)
;
210 setsockopt(socket, SOL_TCP6, TCP_KEEPINTVL5, (void *)&val, sizeof val);}
211#endif
212
213 if (!accepted)
214 tport_tcp_setsndbuf(socket, 64 * 1024);
215
216 return 0;
217}
218
219static int tport_tcp_setsndbuf(int socket, int atleast)
220{
221#if SU_HAVE_WINSOCK2
222 /* Set send buffer size to something reasonable on windows */
223 int size = 0;
224 socklen_t sizelen = sizeof size;
225
226 if (getsockopt(socket, SOL_SOCKET1, SO_SNDBUF7, (void *)&size, &sizelen) < 0)
227 return -1;
228
229 if (sizelen != sizeof size)
230 return su_seterrno(EINVAL22);
231
232 if (size >= atleast)
233 return 0; /* OK */
234
235 return setsockopt(socket, SOL_SOCKET1, SO_SNDBUF7,
236 (void *)&atleast, sizeof atleast);
237#else
238 return 0;
239#endif
240}
241
242/** Return span of whitespace from buffer */
243static inline size_t ws_span(void *buffer, size_t len)
244{
245 size_t i;
246 char const *b = buffer;
247
248 for (i = 0; i < len; i++) {
249 if (b[i] != '\r' && b[i] != '\n' && b[i] != ' ' && b[i] != '\t')
250 break;
251 }
252
253 return i;
254}
255
256/** Receive from stream.
257 *
258 * @retval -1 error
259 * @retval 0 end-of-stream
260 * @retval 1 normal receive
261 * @retval 2 incomplete recv, recv again
262 *
263 */
264int tport_recv_stream(tport_t *self)
265{
266 msg_t *msg;
267 ssize_t n, N, veclen;
268 int err, initial;
269 msg_iovec_t iovec[msg_n_fragments] = {{ 0 }};
270
271 N = su_getmsgsize(self->tp_socket);
272 if (N == 0) {
273 if (self->tp_msg)
274 msg_recv_commit(self->tp_msg, 0, 1);
275 return 0; /* End of stream */
276 }
277 if (N == -1) {
278 err = su_errno();
279 SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\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)) >= 1 ? (_su_llog(tport_log, 1, "tport_type_tcp.c"
, (const char *)__func__, 280, "%s(%p): su_getmsgsize(): %s (%d)\n"
, __func__, (void *)self, su_strerror(err), err)) : (void)0)
280 su_strerror(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)) >= 1 ? (_su_llog(tport_log, 1, "tport_type_tcp.c"
, (const char *)__func__, 280, "%s(%p): su_getmsgsize(): %s (%d)\n"
, __func__, (void *)self, su_strerror(err), err)) : (void)0)
;
281 return -1;
282 }
283
284 initial = self->tp_msg == NULL((void*)0);
285 memset(&self->tp_ptime, 0, sizeof self->tp_ptime);
286
287 while (initial && N <= 8) { /* Check for whitespace */
288 char crlf[9];
289 size_t i;
290
291 n = su_recv(self->tp_socket, crlf, N, MSG_PEEK)recv((self->tp_socket),(crlf),(N),(MSG_PEEK));
292
293 i = ws_span(crlf, n);
294 if (i == 0)
295 break;
296
297 n = su_recv(self->tp_socket, crlf, i, 0)recv((self->tp_socket),(crlf),(i),(0));
298 if (n <= 0)
299 return (int)n;
300
301 SU_DEBUG_7(("%s(%p): received keepalive (total %u)\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)) >= 7 ? (_su_llog(tport_log, 7, "tport_type_tcp.c"
, (const char *)__func__, 302, "%s(%p): received keepalive (total %u)\n"
, __func__, (void *)self, self->tp_ping)) : (void)0)
302 (void *)self, self->tp_ping))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport_type_tcp.c"
, (const char *)__func__, 302, "%s(%p): received keepalive (total %u)\n"
, __func__, (void *)self, self->tp_ping)) : (void)0)
;
303
304 N -= n, self->tp_ping += n;
305
306 tport_recv_bytes(self, n, n);
307
308 if (N == 0) {
309 /* outbound-10 section 3.5.1 - send pong */
310 if (self->tp_ping >= 4)
311 tport_tcp_pong(self);
312
313 return 1;
314 }
315 }
316
317 veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0);
318 if (veclen == -1)
319 return -1;
320
321 msg = self->tp_msg;
322
323 msg_set_address(msg, self->tp_addr, (socklen_t)(self->tp_addrlentp_addrinfo->ai_addrlen));
324
325 n = su_vrecv(self->tp_socket, iovec, veclen, 0, NULL((void*)0), NULL((void*)0));
326
327 if (n == SOCKET_ERRORSOCKET_ERROR)
328 return tport_recv_error_report(self);
329
330 assert(n <= N)((n <= N) ? (void) (0) : __assert_fail ("n <= N", "tport_type_tcp.c"
, 330, __PRETTY_FUNCTION__))
;
331
332 tport_recv_bytes(self, n, n);
333
334 /* Check if message contains only whitespace */
335 /* This can happen if multiple PINGs are received at once */
336 if (initial) {
337 size_t i = ws_span(iovec->siv_base, iovec->siv_len);
338
339 if (i + self->tp_ping >= 4)
340 tport_tcp_pong(self);
341 else
342
343 self->tp_ping += (unsigned short)i;
344
345 if (i == iovec->siv_len && veclen == 1) {
346 SU_DEBUG_7(("%s(%p): received %u bytes of keepalive\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_type_tcp.c"
, (const char *)__func__, 347, "%s(%p): received %u bytes of keepalive\n"
, __func__, (void *)self, (unsigned)i)) : (void)0)
347 __func__, (void *)self, (unsigned)i))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport_type_tcp.c"
, (const char *)__func__, 347, "%s(%p): received %u bytes of keepalive\n"
, __func__, (void *)self, (unsigned)i)) : (void)0)
;
348 msg_destroy(self->tp_msg), self->tp_msg = NULL((void*)0);
349 return 1;
350 }
351 }
352
353 /* Write the received data to the message dump file */
354 if (self->tp_master->mr_dump_file)
355 tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from");
356
357 if (self->tp_master->mr_capt_sock)
358 tport_capt_msg(self, msg, n, iovec, veclen, "recv");
359
360
361 /* Mark buffer as used */
362 msg_recv_commit(msg, n, n == 0);
363
364 if (n > 0)
365 self->tp_ping = 0;
366
367 return n != 0;
368}
369
370/** Send to stream */
371ssize_t tport_send_stream(tport_t const *self, msg_t *msg,
372 msg_iovec_t iov[],
373 size_t iovused)
374{
375#if __sun__ /* XXX - there must be a better way... */
376 if (iovused > 16)
377 iovused = 16;
378#endif
379 return su_vsend(self->tp_socket, iov, iovused, MSG_NOSIGNALMSG_NOSIGNAL, NULL((void*)0), 0);
380}
381
382/** Calculate timeout if receive is incomplete. */
383int tport_next_recv_timeout(tport_t *self,
384 su_time_t *return_target,
385 char const **return_why)
386{
387 unsigned timeout = self->tp_params->tpp_timeout;
388
389 if (timeout < INT_MAX2147483647) {
390 /* Recv timeout */
391 if (self->tp_msg) {
392 su_time_t ntime = su_time_add(self->tp_rtime, timeout);
393 if (su_time_cmp(ntime, *return_target) < 0)
394 *return_target = ntime, *return_why = "recv timeout";
395 }
396
397#if 0
398 /* Send timeout */
399 if (tport_has_queued(self)) {
400 su_time_t ntime = su_time_add(self->tp_stime, timeout);
401 if (su_time_cmp(ntime, *return_target) < 0)
402 *return_target = ntime, *return_why = "send timeout";
403 }
404#endif
405 }
406
407 return 0;
408}
409
410/** Timeout timer if receive is incomplete */
411void tport_recv_timeout_timer(tport_t *self, su_time_t now)
412{
413 unsigned timeout = self->tp_params->tpp_timeout;
414
415 if (timeout < INT_MAX2147483647) {
416 if (self->tp_msg &&
417 su_time_cmp(su_time_add(self->tp_rtime, timeout), now) < 0) {
418 msg_t *msg = self->tp_msg;
419 msg_set_streaming(msg, (enum msg_streaming_status)0);
420 msg_set_flags(msg, MSG_FLG_ERROR | MSG_FLG_TRUNC | MSG_FLG_TIMEOUT);
421 tport_deliver(self, msg, NULL((void*)0), NULL((void*)0), now);
422 self->tp_msg = NULL((void*)0);
423 }
424
425#if 0
426 /* Send timeout */
427 if (tport_has_queued(self) &&
428 su_time_cmp(su_time_add(self->tp_stime, timeout), now) < 0) {
429 stime = su_time_add(self->tp_stime, self->tp_params->tpp_timeout);
430 if (su_time_cmp(stime, target) < 0)
431 target = stime;
432 }
433#endif
434 }
435}
436
437/** Calculate next timeout for keepalive */
438int tport_next_keepalive(tport_t *self,
439 su_time_t *return_target,
440 char const **return_why)
441{
442 /* Keepalive timer */
443 unsigned timeout = self->tp_params->tpp_keepalive;
444
445 if (timeout != 0 && timeout != UINT_MAX(2147483647 *2U +1U)) {
446 if (!tport_has_queued(self)) {
447 su_time_t ntime = su_time_add(self->tp_ktime, timeout);
448 if (su_time_cmp(ntime, *return_target) < 0)
449 *return_target = ntime, *return_why = "keepalive";
450 }
451 }
452
453 timeout = self->tp_params->tpp_pingpong;
454 if (timeout != 0) {
455 if (self->tp_ptime.tv_sec && !self->tp_recv_close) {
456 su_time_t ntime = su_time_add(self->tp_ptime, timeout);
457 if (su_time_cmp(ntime, *return_target) < 0)
458 *return_target = ntime, *return_why = "waiting for pong";
459 }
460 }
461
462 return 0;
463}
464
465
466/** Keepalive timer. */
467void tport_keepalive_timer(tport_t *self, su_time_t now)
468{
469 unsigned timeout = self->tp_params->tpp_pingpong;
470
471 if (timeout != 0) {
472 if (self->tp_ptime.tv_sec && !self->tp_recv_close &&
473 su_time_cmp(su_time_add(self->tp_ptime, timeout), now) < 0) {
474 SU_DEBUG_3(("%s(%p): %s to " TPN_FORMAT "%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_type_tcp.c"
, (const char *)__func__, 477, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "closing connection", (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 : "", " because of PONG timeout")) : (void)0)
475 __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_type_tcp.c"
, (const char *)__func__, 477, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "closing connection", (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 : "", " because of PONG timeout")) : (void)0)
476 "closing connection", 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_type_tcp.c"
, (const char *)__func__, 477, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "closing connection", (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 : "", " because of PONG timeout")) : (void)0)
477 " because of PONG timeout"))(((tport_log != ((void*)0) && 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_type_tcp.c"
, (const char *)__func__, 477, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "closing connection", (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 : "", " because of PONG timeout")) : (void)0)
;
478 tport_error_report(self, EPIPE32, NULL((void*)0));
479 if (!self->tp_closed)
480 tport_close(self);
481 return;
482 }
483 }
484
485 timeout = self->tp_params->tpp_keepalive;
486
487 if (timeout != 0 && timeout != UINT_MAX(2147483647 *2U +1U)) {
488 if (su_time_cmp(su_time_add(self->tp_ktime, timeout), now) < 0) {
489 tport_tcp_ping(self, now);
490 }
491 }
492}
493
494/** Send PING */
495int tport_tcp_ping(tport_t *self, su_time_t now)
496{
497 ssize_t n;
498 char *why = "";
499
500 if (tport_has_queued(self))
501 return 0;
502
503 n = send(self->tp_socket, "\r\n\r\n", 4, 0);
504
505 if (n > 0)
506 self->tp_ktime = now;
507
508 if (n == 4) {
509 if (self->tp_ptime.tv_sec == 0)
510 self->tp_ptime = now;
511 }
512 else if (n == -1) {
513 int error = su_errno();
514
515 why = " failed";
Value stored to 'why' is never read
516
517 if (!su_is_blocking(error)((error) == 115 || (error) == 11 || (error) == 11 || (error) ==
4)
)
518 tport_error_report(self, error, NULL((void*)0));
519 else
520 why = " blocking";
521
522 return -1;
523 }
524
525 SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%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_type_tcp.c"
, (const char *)__func__, 527, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "sending PING", (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 : ""
, why)) : (void)0)
526 __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_type_tcp.c"
, (const char *)__func__, 527, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "sending PING", (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 : ""
, why)) : (void)0)
527 "sending PING", TPN_ARGS(self->tp_name), 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_type_tcp.c"
, (const char *)__func__, 527, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "sending PING", (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 : ""
, why)) : (void)0)
;
528
529 return n == -1 ? -1 : 0;
530}
531
532/** Send pong */
533int tport_tcp_pong(tport_t *self)
534{
535 self->tp_ping = 0;
536
537 if (tport_has_queued(self) || !self->tp_params->tpp_pong2ping)
538 return 0;
539
540 SU_DEBUG_7(("%s(%p): %s to " TPN_FORMAT "%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_type_tcp.c"
, (const char *)__func__, 542, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "sending PONG", (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)
541 __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_type_tcp.c"
, (const char *)__func__, 542, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "sending PONG", (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)
542 "sending PONG", 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)) >= 7 ? (_su_llog(tport_log, 7, "tport_type_tcp.c"
, (const char *)__func__, 542, "%s(%p): %s to " "%s/%s:%s%s%s%s%s"
"%s\n", __func__, (void *)self, "sending PONG", (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)
;
543
544 return send(self->tp_socket, "\r\n", 2, 0);
545}
546
547/** Calculate next timer for TCP. */
548int tport_tcp_next_timer(tport_t *self,
549 su_time_t *return_target,
550 char const **return_why)
551{
552 return
553 tport_next_recv_timeout(self, return_target, return_why) |
554 tport_next_keepalive(self, return_target, return_why);
555}
556
557/** TCP timer. */
558void tport_tcp_timer(tport_t *self, su_time_t now)
559{
560 tport_recv_timeout_timer(self, now);
561 tport_keepalive_timer(self, now);
562 tport_base_timer(self, now);
563}