tport_internal.h 18.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2005 Nokia Corporation.
 *
 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

25
#ifndef TPORT_INTERNAL_H
26
/** Defined when <tport_internal.h> has been included. */
27
#define TPORT_INTERNAL_H
28

Pekka Pessi's avatar
Pekka Pessi committed
29 30 31
/**@internal
 * @file tport_internal.h
 * @brief Internal implementation of transport interface
32 33 34 35 36 37 38 39 40
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created: Thu Jun 29 15:58:06 2000 ppessi
 */

#ifndef SU_H
#include <sofia-sip/su.h>
#endif
41

42
#include <sofia-sip/su_uniqueid.h>
43
#include <sofia-sip/su_strlst.h>
44 45 46 47 48 49 50 51 52 53 54 55 56

#ifndef MSG_ADDR_H
#include <sofia-sip/msg_addr.h>
#endif
#ifndef TPORT_H
#include <sofia-sip/tport.h>
#endif

#if HAVE_SOFIA_STUN
#include "sofia-sip/stun.h"
#include "sofia-sip/stun_tag.h"
#endif

57 58
#include <sofia-sip/tport_plugins.h>

59 60 61 62 63 64 65
#ifndef SU_DEBUG
#define SU_DEBUG 3
#endif
#define SU_LOG   tport_log

#include <sofia-sip/su_debug.h>

66
#if !defined(MSG_NOSIGNAL) || defined(__CYGWIN__) || defined(SYMBIAN)
67 68 69 70
#undef MSG_NOSIGNAL
#define MSG_NOSIGNAL (0)
#endif

Michael Jerris's avatar
Michael Jerris committed
71 72 73 74 75 76
#if (_WIN32_WINNT >= 0x0600)
#ifndef HAVE_MSG_TRUNC
#define HAVE_MSG_TRUNC 1
#endif
#endif

77
#if !HAVE_MSG_TRUNC
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
#define MSG_TRUNC (0)
#endif

#ifndef NONE
#define NONE ((void *)-1)
#endif

SOFIA_BEGIN_DECLS

typedef struct tport_master tport_master_t;
typedef struct tport_pending_s tport_pending_t;
typedef struct tport_primary tport_primary_t;
typedef struct tport_vtable tport_vtable_t;

struct sigcomp_state_handler;
struct sigcomp_algorithm;
struct sigcomp_udvm;
struct sigcomp_magic;
struct sigcomp_compartment;

typedef long unsigned LU; 	/* for printf() and friends */

Pekka Pessi's avatar
Pekka Pessi committed
100
/** @internal Transport parameters */
101
typedef struct {
102
  unsigned tpp_mtu;		/**< Maximum packet size */
103 104
  unsigned tpp_idle;		/**< Allowed connection idle time. */
  unsigned tpp_timeout;		/**< Allowed idle time for message. */
105 106 107
  unsigned tpp_keepalive;	/**< Keepalive PING interval */
  unsigned tpp_pingpong;	/**< PONG-to-PING interval */

108 109 110 111 112 113 114
  unsigned tpp_sigcomp_lifetime;  /**< SigComp compartment lifetime  */
  unsigned tpp_thrpsize;	/**< Size of thread pool */

  unsigned tpp_thrprqsize;	/**< Length of per-thread recv queue */
  unsigned tpp_qsize;		/**< Size of queue */

  unsigned tpp_drop;		/**< Packet drop probablity */
115
  int      tpp_tos;         	/**< IP TOS */
116 117 118

  unsigned tpp_conn_orient:1;   /**< Connection-orienteded */
  unsigned tpp_sdwn_error:1;	/**< If true, shutdown is error. */
119
  unsigned tpp_stun_server:1;	/**< If true, use stun server */
120
  unsigned tpp_pong2ping:1;	/**< If true, respond with pong to ping */
121

122 123 124 125 126
  unsigned :0;

} tport_params_t;


Pekka Pessi's avatar
Pekka Pessi committed
127
/** @internal Transport object.
128 129 130 131 132 133 134 135 136
 *
 * A transport object can be used in three roles, to represent transport
 * list (aka master transport), to represent available transports (aka
 * primary transport) and to represent actual transport connections (aka
 * secondary transport).
 */
struct tport_s {
  su_home_t           tp_home[1];       /**< Memory home */

137
  ssize_t             tp_refs;		/**< Number of references to tport */
138 139

  unsigned            tp_black:1;       /**< Used by red-black-tree */
140

141 142
  unsigned            tp_accepted:1;    /**< Originally server? */
  unsigned            tp_conn_orient:1;	/**< Is connection-oriented */
143
  unsigned            tp_has_connection:1; /**< Has real connection */
144
  unsigned            tp_reusable:1;    /**< Can this connection be reused */
145 146
  unsigned            tp_closed : 1;
  /**< This transport is closed.
147
   *
148 149 150 151
   * A closed transport is inserted into pri_closed list.
   */

  /** Remote end has sent FIN (2) or we should not just read */
152 153
  unsigned            tp_recv_close:2;
  /** We will send FIN (1) or have sent FIN (2) */
154
  unsigned            tp_send_close:2;
155
  unsigned            tp_has_keepalive:1;
156
  unsigned            tp_has_stun_server:1;
157
  unsigned            tp_trunc:1;
158
  unsigned            tp_is_connected:1; /**< Connection is established */
159
  unsigned            tp_verified:1;     /**< Certificate Chain was verified */
160 161 162 163 164 165 166 167 168 169 170
  unsigned:0;

  tport_t *tp_left, *tp_right, *tp_dad; /**< Links in tport tree */

  tport_master_t     *tp_master;        /**< Master transport */
  tport_primary_t    *tp_pri;           /**< Primary transport */

  tport_params_t     *tp_params;        /**< Transport parameters */

  tp_magic_t         *tp_magic; 	/**< Context provided by consumer */

171
  su_timer_t         *tp_timer;	        /**< Timer object */
172

173 174
  su_time_t           tp_ktime;	        /**< Keepalive timer updated */
  su_time_t           tp_ptime;	        /**< Ping sent */
175 176

  tp_name_t           tp_name[1];	/**< Transport name.
177
					 *
178 179 180 181
					 * This is either our name (if primary)
					 * or peer name (if secondary).
					 */

182 183 184 185 186 187
  su_strlst_t        *tp_subjects;      /**< Transport Subjects.
                                         *
                                         * Subject Name(s) provided by the 
                                         * peer in a TLS connection (if secondary).
                                         */

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
#define tp_protoname tp_name->tpn_proto
#define tp_canon     tp_name->tpn_canon
#define tp_host      tp_name->tpn_host
#define tp_port      tp_name->tpn_port
#define tp_ident     tp_name->tpn_ident

  su_socket_t  	      tp_socket;	/**< Socket of this tport*/
  int                 tp_index;		/**< Root registration index */
  int                 tp_events;        /**< Subscribed events */

  su_addrinfo_t       tp_addrinfo[1];   /**< Peer/own address info */
  su_sockaddr_t       tp_addr[1];	/**< Peer/own address */
#define tp_addrlen tp_addrinfo->ai_addrlen

  /* ==== Receive queue ================================================== */

  msg_t   	     *tp_msg;		/**< Message being received */
205 206 207
  msg_t const        *tp_rlogged;       /**< Last logged when receiving */
  su_time_t           tp_rtime;	        /**< Last time received data */
  unsigned short      tp_ping;	        /**< Whitespace ping being received */
208 209 210

  /* ==== Pending messages =============================================== */

211
  unsigned short      tp_reported;      /**< Report counter */
212 213
  unsigned            tp_plen;          /**< Size of tp_pending */
  unsigned            tp_pused;         /**< Used pends */
214 215
  tport_pending_t    *tp_pending;       /**< Pending requests */
  tport_pending_t    *tp_released;      /**< Released pends */
216

217 218 219 220 221 222
  /* ==== Send queue ===================================================== */

  msg_t             **tp_queue;		/**< Messages being sent */
  unsigned short      tp_qhead;		/**< Head of queue */

  msg_iovec_t        *tp_unsent;	/**< Pointer to first unsent iovec */
223
  size_t              tp_unsentlen;	/**< Number of unsent iovecs */
224 225

  msg_iovec_t        *tp_iov;		/**< Iovecs allocated for sending */
226
  size_t              tp_iovlen;	/**< Number of allocated iovecs */
227

228 229 230
  msg_t const        *tp_slogged;       /**< Last logged when sending */
  su_time_t           tp_stime;	        /**< Last time sent message */

231 232
  /* ==== Extensions  ===================================================== */

233
  tport_compressor_t *tp_comp;
234

235
  /* ==== Statistics  ===================================================== */
236

237
  struct {
Pekka Pessi's avatar
Pekka Pessi committed
238 239
    uint64_t sent_msgs, sent_errors, sent_bytes, sent_on_line;
    uint64_t recv_msgs, recv_errors, recv_bytes, recv_on_line;
240 241 242
  } tp_stats;
};

Pekka Pessi's avatar
Pekka Pessi committed
243
/** @internal Primary structure */
244 245
struct tport_primary {
  tport_t             pri_primary[1];   /**< Transport part */
246
#if DOXYGEN_ONLY
247 248 249 250 251 252 253 254
  su_home_t           pri_home[1];
#else
#define pri_home      pri_primary->tp_home
#define pri_master    pri_primary->tp_master
#define pri_protoname pri_primary->tp_name->tpn_proto
#endif
  tport_vtable_t const
                     *pri_vtable;
255
  int                 pri_public;       /**< Type of primary transport;
256
					 * tport_type_local,
257
					 * tport_type_stun, etc.
258 259 260 261
					 */

  tport_primary_t    *pri_next;	        /**< Next primary tport */

262 263
  tport_t            *pri_open;		/**< Open secondary tports */
  tport_t            *pri_closed;       /**< Closed secondary tports */
264

265
  unsigned            pri_updating:1;   /**< Currently updating address */
266 267 268 269
  unsigned            pri_natted:1;	/**< Using natted address  */
  unsigned            pri_has_tls:1;	/**< Supports tls  */
  unsigned:0;

270 271
  void               *pri_stun_handle;

272 273 274
  tport_params_t      pri_params[1];      /**< Transport parameters */
};

Pekka Pessi's avatar
Pekka Pessi committed
275
/** @internal Master structure */
276 277
struct tport_master {
  tport_t             mr_master[1];
278
#if DOXYGEN_ONLY
279 280 281 282 283 284 285 286
  su_home_t           mr_home[1];
#else
#define mr_home mr_master->tp_home
#endif

  int                 mr_stun_step_ready; /**< for stun's callback */

  tp_stack_t  	     *mr_stack;         /**< Transport consumer */
287
  tp_stack_class_t
288 289 290 291 292
               const *mr_tpac;		/**< Methods provided by stack */
  int                 mr_log;	        /**< Do logging of parsed messages */
  su_root_t    	     *mr_root;		/**< SU root pointer */

  /**< Timer reclaiming unused connections and compartment */
293
  su_timer_t         *mr_timer;
294
  /** FILE to dump received and sent data */
295
  FILE               *mr_dump_file;
296
  char               *mr_dump;	/**< Filename for dumping received/sent data */
297 298 299
  tport_primary_t    *mr_primaries;        /**< List of primary contacts */

  tport_params_t      mr_params[1];
300

301 302 303 304 305 306 307 308 309
  unsigned            mr_boundserver:1; /**< Server has been bound */
  unsigned            mr_bindv6only:1; /**< We can bind separately to IPv6/4 */
  unsigned :0;

  /* Delivery context */
  struct tport_delivery {
    tport_t              *d_tport;
    msg_t                *d_msg;
    tp_name_t             d_from[1];
310
    tport_compressor_t   *d_comp;
311 312
  } mr_delivery[1];

313 314 315
  tport_stun_server_t *mr_stun_server;

#if 0
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
  struct tport_nat_s {
    int initialized;
    int bound;
    int stun_enabled;
    char *external_ip_address;
#if HAVE_UPNP || HAVE_SOFIA_STUN
    int try_stun;
#endif
#if HAVE_UPNP
#endif
#if HAVE_SOFIA_STUN
    tport_master_t *tport;
    char *stun_server;
    /* stun_socket_t *stun_socket; */
    stun_handle_t *stun;
    su_socket_t stun_socket;
    su_sockaddr_t sockaddr;
#endif
  }                   mr_nat[1];
335
#endif
336 337
};

Pekka Pessi's avatar
Pekka Pessi committed
338
/** @internal Virtual function table for transports */
339 340 341 342 343
struct tport_vtable
{
  char const *vtp_name;
  enum tport_via vtp_public;

344
  size_t vtp_pri_size;		/* Size of primary tport */
345
  int (*vtp_init_primary)(tport_primary_t *pri,
346
			  tp_name_t tpn[1],
347 348 349 350
			  su_addrinfo_t *ai, tagi_t const *,
			  char const **return_culprit);
  void (*vtp_deinit_primary)(tport_primary_t *pri);
  int (*vtp_wakeup_pri)(tport_primary_t *pri, int events);
351
  tport_t *(*vtp_connect)(tport_primary_t *pri, su_addrinfo_t *ai,
352 353
			  tp_name_t const *tpn);

354
  size_t vtp_secondary_size;	/* Size of secondary tport */
355

356 357
  int (*vtp_init_secondary)(tport_t *, int socket, int accepted,
			    char const **return_reason);
358 359 360 361 362
  void (*vtp_deinit_secondary)(tport_t *);
  void (*vtp_shutdown)(tport_t *, int how);
  int (*vtp_set_events)(tport_t const *self);
  int (*vtp_wakeup)(tport_t *self, int events);
  int (*vtp_recv)(tport_t *self);
363 364
  ssize_t (*vtp_send)(tport_t const *self, msg_t *msg,
		      msg_iovec_t iov[], size_t iovused);
365
  void (*vtp_deliver)(tport_t *self,  msg_t *msg, su_time_t now);
366 367
  int (*vtp_prepare)(tport_t *self, msg_t *msg,
		     tp_name_t const *tpn,
368 369
		     struct sigcomp_compartment *cc,
		     unsigned mtu);
370 371
  int (*vtp_keepalive)(tport_t *self, su_addrinfo_t const *ai,
		       tagi_t const *taglist);
372 373 374
  int (*vtp_stun_response)(tport_t const *self,
			   void *msg, size_t msglen,
			   void *addr, socklen_t addrlen);
375
  int (*vtp_next_secondary_timer)(tport_t *self, su_time_t *,
376 377
				  char const **return_why);
  void (*vtp_secondary_timer)(tport_t *self, su_time_t);
378 379
};

380 381
int tport_register_type(tport_vtable_t const *vtp);

Pekka Pessi's avatar
Pekka Pessi committed
382
/** @internal Test if transport needs connect() before sending. */
383
su_inline int tport_is_connection_oriented(tport_t const *self)
384 385 386 387
{
  return self->tp_conn_orient;
}

Pekka Pessi's avatar
Pekka Pessi committed
388
/** @internal Test if transport involves connection. @NEW_1_12_5. */
389
su_inline int tport_has_connection(tport_t const *self)
390
{
391
  return self->tp_has_connection;
392 393
}

394 395
void tport_has_been_updated(tport_t *tport);

396 397 398
int tport_primary_compression(tport_primary_t *pri,
			      char const *compression,
			      tagi_t const *tl);
399

400 401
void tport_set_tos(su_socket_t socket, su_addrinfo_t *ai, int tos);

402
tport_t *tport_base_connect(tport_primary_t *pri,
403 404 405
			    su_addrinfo_t *ai,
			    su_addrinfo_t *name,
			    tp_name_t const *tpn);
406

407
int tport_stream_init_primary(tport_primary_t *pri,
408 409 410 411 412 413 414 415 416 417 418
			      su_socket_t socket,
			      tp_name_t tpn[1],
			      su_addrinfo_t *ai,
			      tagi_t const *tags,
			      char const **return_reason);

tport_t *tport_alloc_secondary(tport_primary_t *pri,
			       int socket,
			       int accepted,
			       char const **return_reason);

419
int tport_accept(tport_primary_t *pri, int events);
420
int tport_register_secondary(tport_t *self, su_wakeup_f wakeup, int events);
421 422
void tport_zap_secondary(tport_t *self);

423 424 425
int tport_set_secondary_timer(tport_t *self);
void tport_base_timer(tport_t *self, su_time_t now);

426 427 428 429
int tport_bind_socket(int socket,
		      su_addrinfo_t *ai,
		      char const **return_culprit);
void tport_close(tport_t *self);
430
int tport_shutdown0(tport_t *self, int how);
431

432
int tport_has_queued(tport_t const *self);
433

434 435 436 437
int tport_error_event(tport_t *self);
void tport_recv_event(tport_t *self);
void tport_send_event(tport_t *self);
void tport_hup_event(tport_t *self);
438 439 440
int tport_setname(tport_t *, char const *, su_addrinfo_t const *, char const *);

int tport_wakeup(su_root_magic_t *magic, su_wait_t *w, tport_t *self);
441

442
ssize_t tport_recv_iovec(tport_t const *self,
443
			 msg_t **mmsg,
444
			 msg_iovec_t iovec[msg_n_fragments], size_t N,
445
			 int exact);
446

447
msg_t *tport_msg_alloc(tport_t const *self, usize_t size);
448

449 450
int tport_prepare_and_send(tport_t *self, msg_t *msg,
			   tp_name_t const *tpn,
451 452
			   struct sigcomp_compartment *cc,
			   unsigned mtu);
453 454
int tport_send_msg(tport_t *self, msg_t *msg,
		   tp_name_t const *tpn,
455 456
		   struct sigcomp_compartment *cc);

457 458
void tport_send_queue(tport_t *self);

459
void tport_deliver(tport_t *self, msg_t *msg, msg_t *next,
460
		   tport_compressor_t *comp,
461 462 463 464
		   su_time_t now);
void tport_base_deliver(tport_t *self, msg_t *msg, su_time_t now);

int tport_recv_error_report(tport_t *self);
465
void tport_error_report(tport_t *self, int errcode,
466 467
			su_sockaddr_t const *addr);

468
int tport_open_log(tport_master_t *mr, tagi_t *tags);
469
void tport_log_msg(tport_t *tp, msg_t *msg, char const *what,
470
		   char const *via, su_time_t now);
471
void tport_dump_iovec(tport_t const *self, msg_t *msg,
472
		      size_t n, su_iovec_t const iov[], size_t iovused,
473 474
		      char const *what, char const *how);

475 476 477
int tport_tcp_ping(tport_t *self, su_time_t now);
int tport_tcp_pong(tport_t *self);

478 479
extern tport_vtable_t const tport_udp_vtable;
extern tport_vtable_t const tport_udp_client_vtable;
480

481 482 483
int tport_udp_init_primary(tport_primary_t *,
			   tp_name_t tpn[1],
			   su_addrinfo_t *,
484 485
			   tagi_t const *,
			   char const **return_culprit);
486
void tport_udp_deinit_primary(tport_primary_t *);
487
int tport_recv_dgram(tport_t *self);
488 489
ssize_t tport_send_dgram(tport_t const *self, msg_t *msg,
			 msg_iovec_t iov[], size_t iovused);
490 491
int tport_udp_error(tport_t const *self, su_sockaddr_t name[1]);

492 493
extern tport_vtable_t const tport_tcp_vtable;
extern tport_vtable_t const tport_tcp_client_vtable;
494

495 496
int tport_tcp_init_primary(tport_primary_t *,
 			  tp_name_t  tpn[1],
497 498
 			  su_addrinfo_t *, tagi_t const *,
 			  char const **return_culprit);
499 500
int tport_tcp_init_client(tport_primary_t *,
 			 tp_name_t tpn[1],
501 502
 			 su_addrinfo_t *, tagi_t const *,
 			 char const **return_culprit);
503 504
int tport_tcp_init_secondary(tport_t *self, int socket, int accepted,
			     char const **return_reason);
505
int tport_recv_stream(tport_t *self);
506 507
ssize_t tport_send_stream(tport_t const *self, msg_t *msg,
			  msg_iovec_t iov[], size_t iovused);
508

509 510 511 512 513 514 515 516 517
int tport_tcp_next_timer(tport_t *self, su_time_t *, char const **);
void tport_tcp_timer(tport_t *self, su_time_t);

int tport_next_recv_timeout(tport_t *, su_time_t *, char const **);
void tport_recv_timeout_timer(tport_t *self, su_time_t now);

int tport_next_keepalive(tport_t *self, su_time_t *, char const **);
void tport_keepalive_timer(tport_t *self, su_time_t now);

518 519 520 521 522 523 524
extern tport_vtable_t const tport_sctp_vtable;
extern tport_vtable_t const tport_sctp_client_vtable;
extern tport_vtable_t const tport_tls_vtable;
extern tport_vtable_t const tport_tls_client_vtable;
extern tport_vtable_t const tport_stun_vtable;
extern tport_vtable_t const tport_http_connect_vtable;
extern tport_vtable_t const tport_threadpool_vtable;
525

526 527 528 529 530 531 532
typedef struct tport_descriptor_s {
  char const *tpd_name;
  tport_vtable_t *tpd_vtable;
  su_addrinfo_t *tpd_hints;
  int tpd_is_client_only;
} tport_descriptor_t;

533
typedef int const *(tport_set_f)(tport_master_t *mr,
534 535 536 537 538 539 540 541 542
				 tp_name_t const *tpn,
				 tagi_t const *taglist,
				 tport_descriptor_t **return_set,
				 int return_set_size);

/* STUN plugin */

int tport_init_stun_server(tport_master_t *mr, tagi_t const *tags);
void tport_deinit_stun_server(tport_master_t *mr);
543 544
int tport_recv_stun_dgram(tport_t const *self, msg_t **in_out_msg,
			  su_sockaddr_t *from, socklen_t fromlen);
545 546 547 548

int tport_stun_server_add_socket(tport_t *tp);
int tport_stun_server_remove_socket(tport_t *tp);

Pekka Pessi's avatar
Pekka Pessi committed
549 550 551 552 553 554
void tport_recv_bytes(tport_t *self, ssize_t bytes, ssize_t on_line);
void tport_recv_message(tport_t *self, msg_t *msg, int error);

void tport_sent_bytes(tport_t *self, ssize_t bytes, ssize_t on_line);
void tport_sent_message(tport_t *self, msg_t *msg, int error);

555 556
/* ---------------------------------------------------------------------- */
/* Compressor plugin */
557 558 559 560
extern tport_comp_vtable_t const *tport_comp_vtable;

char const *tport_canonize_comp(char const *comp);

561 562 563 564
int tport_init_compressor(tport_t *,
			  char const *comp_name,
			  tagi_t const *tags);
void tport_deinit_compressor(tport_t *);
565 566 567 568 569 570 571

struct sigcomp_compartment *
tport_sigcomp_assign_if_needed(tport_t *self,
			       struct sigcomp_compartment *cc);

struct sigcomp_udvm **tport_get_udvm_slot(tport_t *self);

572
void tport_sigcomp_accept_incomplete(tport_t *self, msg_t *msg);
573

574 575
int tport_recv_comp_dgram(tport_t const *self,
			  tport_compressor_t *sc,
576 577 578
			  msg_t **in_out_msg,
			  su_sockaddr_t *from,
			  socklen_t fromlen);
579

580
ssize_t tport_send_comp(tport_t const *self,
581 582
		    msg_t *msg,
		    msg_iovec_t iov[],
583
		    size_t iovused,
584
		    struct sigcomp_compartment *cc,
585
		    tport_compressor_t *sc);
586

587 588 589
SOFIA_END_DECLS

#endif /* TPORT_INTERNAL_H */