tport_internal.h 17.8 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 43 44 45 46 47 48 49 50 51 52 53 54 55
#include <sofia-sip/su_uniqueid.h>

#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

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

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

#include <sofia-sip/su_debug.h>

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

70
#if !HAVE_MSG_TRUNC
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
#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
93
/** @internal Transport parameters */
94
typedef struct {
95
  unsigned tpp_mtu;		/**< Maximum packet size */
96 97
  unsigned tpp_idle;		/**< Allowed connection idle time. */
  unsigned tpp_timeout;		/**< Allowed idle time for message. */
98 99 100
  unsigned tpp_keepalive;	/**< Keepalive PING interval */
  unsigned tpp_pingpong;	/**< PONG-to-PING interval */

101 102 103 104 105 106 107
  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 */
108
  int      tpp_tos;         	/**< IP TOS */
109 110 111

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

115 116 117 118 119
  unsigned :0;

} tport_params_t;


Pekka Pessi's avatar
Pekka Pessi committed
120
/** @internal Transport object.
121 122 123 124 125 126 127 128 129
 *
 * 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 */

130
  ssize_t             tp_refs;		/**< Number of references to tport */
131 132 133 134 135

  unsigned            tp_black:1;       /**< Used by red-black-tree */
  
  unsigned            tp_accepted:1;    /**< Originally server? */
  unsigned            tp_conn_orient:1;	/**< Is connection-oriented */
136
  unsigned            tp_has_connection:1; /**< Has real connection */
137
  unsigned            tp_reusable:1;    /**< Can this connection be reused */
138 139 140 141 142 143 144
  unsigned            tp_closed : 1;
  /**< This transport is closed.
   * 
   * A closed transport is inserted into pri_closed list.
   */

  /** Remote end has sent FIN (2) or we should not just read */
145 146 147 148
  unsigned            tp_recv_close:2;
  /** We will send FIN (1) or have sent FIN (2) */
  unsigned            tp_send_close:2; 
  unsigned            tp_has_keepalive:1;
149
  unsigned            tp_has_stun_server:1;
150
  unsigned            tp_trunc:1;
151
  unsigned            tp_is_connected:1; /**< Connection is established */
152 153 154 155 156 157 158 159 160 161 162
  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 */

163
  su_timer_t         *tp_timer;	        /**< Timer object */
164

165 166
  su_time_t           tp_ktime;	        /**< Keepalive timer updated */
  su_time_t           tp_ptime;	        /**< Ping sent */
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190

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

#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 */
191 192 193
  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 */
194 195 196

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

197
  unsigned short      tp_reported;      /**< Report counter */
198 199
  unsigned            tp_plen;          /**< Size of tp_pending */
  unsigned            tp_pused;         /**< Used pends */
200 201 202
  tport_pending_t    *tp_pending;       /**< Pending requests */
  tport_pending_t    *tp_released;      /**< Released pends */
  
203 204 205 206 207 208
  /* ==== 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 */
209
  size_t              tp_unsentlen;	/**< Number of unsent iovecs */
210 211

  msg_iovec_t        *tp_iov;		/**< Iovecs allocated for sending */
212
  size_t              tp_iovlen;	/**< Number of allocated iovecs */
213

214 215 216
  msg_t const        *tp_slogged;       /**< Last logged when sending */
  su_time_t           tp_stime;	        /**< Last time sent message */

217 218
  /* ==== Extensions  ===================================================== */

219
  tport_compressor_t *tp_comp;
220

221 222 223 224 225 226 227 228
  /* ==== Statistics  ===================================================== */
  
  struct {
    uint64_t sent_bytes, sent_on_line, recv_bytes, recv_on_line;
    uint64_t sent_msgs, recv_msgs;
  } tp_stats;
};

Pekka Pessi's avatar
Pekka Pessi committed
229
/** @internal Primary structure */
230 231
struct tport_primary {
  tport_t             pri_primary[1];   /**< Transport part */
232
#if DOXYGEN_ONLY
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
  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;
  int                 pri_public;       /**< Type of primary transport; 
					 * tport_type_local,
					 * tport_type_stun, etc. 
					 */

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

248 249
  tport_t            *pri_open;		/**< Open secondary tports */
  tport_t            *pri_closed;       /**< Closed secondary tports */
250

251
  unsigned            pri_updating:1;   /**< Currently updating address */
252 253 254 255
  unsigned            pri_natted:1;	/**< Using natted address  */
  unsigned            pri_has_tls:1;	/**< Supports tls  */
  unsigned:0;

256 257
  void               *pri_stun_handle;

258 259 260
  tport_params_t      pri_params[1];      /**< Transport parameters */
};

Pekka Pessi's avatar
Pekka Pessi committed
261
/** @internal Master structure */
262 263
struct tport_master {
  tport_t             mr_master[1];
264
#if DOXYGEN_ONLY
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
  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 */
  tp_stack_class_t 
               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 */
  su_timer_t         *mr_timer;		
  /** File to dump received and sent data */
  FILE               *mr_dump_file;	

  tport_primary_t    *mr_primaries;        /**< List of primary contacts */

  tport_params_t      mr_params[1];
  
  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];
296
    tport_compressor_t   *d_comp;
297 298
  } mr_delivery[1];

299 300 301
  tport_stun_server_t *mr_stun_server;

#if 0
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
  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];
321
#endif
322 323
};

Pekka Pessi's avatar
Pekka Pessi committed
324
/** @internal Virtual function table for transports */
325 326 327 328 329
struct tport_vtable
{
  char const *vtp_name;
  enum tport_via vtp_public;

330
  size_t vtp_pri_size;		/* Size of primary tport */
331
  int (*vtp_init_primary)(tport_primary_t *pri,
332
			  tp_name_t tpn[1],
333 334 335 336 337 338 339
			  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);
  tport_t *(*vtp_connect)(tport_primary_t *pri, su_addrinfo_t *ai, 
			  tp_name_t const *tpn);

340
  size_t vtp_secondary_size;	/* Size of secondary tport */
341

342 343
  int (*vtp_init_secondary)(tport_t *, int socket, int accepted,
			    char const **return_reason);
344 345 346 347 348
  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);
349 350
  ssize_t (*vtp_send)(tport_t const *self, msg_t *msg,
		      msg_iovec_t iov[], size_t iovused);
351 352 353 354 355
  void (*vtp_deliver)(tport_t *self,  msg_t *msg, su_time_t now);
  int (*vtp_prepare)(tport_t *self, msg_t *msg, 
		     tp_name_t const *tpn, 
		     struct sigcomp_compartment *cc,
		     unsigned mtu);
356 357
  int (*vtp_keepalive)(tport_t *self, su_addrinfo_t const *ai,
		       tagi_t const *taglist);
358 359 360
  int (*vtp_stun_response)(tport_t const *self,
			   void *msg, size_t msglen,
			   void *addr, socklen_t addrlen);
361 362 363
  int (*vtp_next_secondary_timer)(tport_t *self, su_time_t *, 
				  char const **return_why);
  void (*vtp_secondary_timer)(tport_t *self, su_time_t);
364 365
};

366 367
int tport_register_type(tport_vtable_t const *vtp);

Pekka Pessi's avatar
Pekka Pessi committed
368
/** @internal Test if transport is needs connect() before sending. */
369
su_inline int tport_is_connection_oriented(tport_t const *self)
370 371 372 373
{
  return self->tp_conn_orient;
}

Pekka Pessi's avatar
Pekka Pessi committed
374
/** @internal Test if transport involves connection. @NEW_1_12_5. */
375
su_inline int tport_has_connection(tport_t const *self)
376
{
377
  return self->tp_has_connection;
378 379
}

380 381
void tport_has_been_updated(tport_t *tport);

382 383 384
int tport_primary_compression(tport_primary_t *pri,
			      char const *compression,
			      tagi_t const *tl);
385

386 387
void tport_set_tos(su_socket_t socket, su_addrinfo_t *ai, int tos);

388 389 390 391
tport_t *tport_base_connect(tport_primary_t *pri, 
			    su_addrinfo_t *ai,
			    su_addrinfo_t *name,
			    tp_name_t const *tpn);
392 393 394 395 396 397 398 399 400 401 402 403 404

int tport_stream_init_primary(tport_primary_t *pri, 
			      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);

405 406 407
int tport_accept(tport_primary_t *pri, int events);
void tport_zap_secondary(tport_t *self);

408 409 410
int tport_set_secondary_timer(tport_t *self);
void tport_base_timer(tport_t *self, su_time_t now);

411 412 413 414
int tport_bind_socket(int socket,
		      su_addrinfo_t *ai,
		      char const **return_culprit);
void tport_close(tport_t *self);
415
int tport_shutdown0(tport_t *self, int how);
416

417
int tport_has_queued(tport_t const *self);
418

419 420 421 422 423
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);

424 425
ssize_t tport_recv_iovec(tport_t const *self, 
			 msg_t **mmsg,
426
			 msg_iovec_t iovec[msg_n_fragments], size_t N, 
427
			 int exact);
428

429
msg_t *tport_msg_alloc(tport_t const *self, usize_t size);
430 431 432 433 434 435 436 437 438

int tport_prepare_and_send(tport_t *self, msg_t *msg, 
			   tp_name_t const *tpn, 
			   struct sigcomp_compartment *cc,
			   unsigned mtu);
int tport_send_msg(tport_t *self, msg_t *msg, 
		   tp_name_t const *tpn, 
		   struct sigcomp_compartment *cc);

439 440
void tport_send_queue(tport_t *self);

441
void tport_deliver(tport_t *self, msg_t *msg, msg_t *next, 
442
		   tport_compressor_t *comp,
443 444 445 446 447 448 449 450 451
		   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);
void tport_error_report(tport_t *self, int errcode, 
			su_sockaddr_t const *addr);

void tport_open_log(tport_master_t *mr, tagi_t *tags);
void tport_log_msg(tport_t *tp, msg_t *msg, char const *what, 
452
		   char const *via, su_time_t now);
453
void tport_dump_iovec(tport_t const *self, msg_t *msg, 
454
		      size_t n, su_iovec_t const iov[], size_t iovused,
455 456
		      char const *what, char const *how);

457 458 459
int tport_tcp_ping(tport_t *self, su_time_t now);
int tport_tcp_pong(tport_t *self);

460 461
extern tport_vtable_t const tport_udp_vtable;
extern tport_vtable_t const tport_udp_client_vtable;
462 463

int tport_udp_init_primary(tport_primary_t *, 
464
			   tp_name_t tpn[1], 
465 466 467
			   su_addrinfo_t *, 
			   tagi_t const *,
			   char const **return_culprit);
468
void tport_udp_deinit_primary(tport_primary_t *);
469
int tport_recv_dgram(tport_t *self);
470 471
ssize_t tport_send_dgram(tport_t const *self, msg_t *msg,
			 msg_iovec_t iov[], size_t iovused);
472 473
int tport_udp_error(tport_t const *self, su_sockaddr_t name[1]);

474 475
extern tport_vtable_t const tport_tcp_vtable;
extern tport_vtable_t const tport_tcp_client_vtable;
476 477

int tport_tcp_init_primary(tport_primary_t *, 
478
 			  tp_name_t  tpn[1], 
479 480 481
 			  su_addrinfo_t *, tagi_t const *,
 			  char const **return_culprit);
int tport_tcp_init_client(tport_primary_t *, 
482
 			 tp_name_t tpn[1], 
483 484
 			 su_addrinfo_t *, tagi_t const *,
 			 char const **return_culprit);
485 486
int tport_tcp_init_secondary(tport_t *self, int socket, int accepted,
			     char const **return_reason);
487
int tport_recv_stream(tport_t *self);
488 489
ssize_t tport_send_stream(tport_t const *self, msg_t *msg,
			  msg_iovec_t iov[], size_t iovused);
490

491 492 493 494 495 496 497 498 499
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);

500 501 502 503 504 505 506
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;
507

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
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;

typedef int const *(tport_set_f)(tport_master_t *mr, 
				 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);
525 526
int tport_recv_stun_dgram(tport_t const *self, msg_t **in_out_msg,
			  su_sockaddr_t *from, socklen_t fromlen);
527 528 529 530

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

531 532
/* ---------------------------------------------------------------------- */
/* Compressor plugin */
533 534 535 536
extern tport_comp_vtable_t const *tport_comp_vtable;

char const *tport_canonize_comp(char const *comp);

537 538 539 540
int tport_init_compressor(tport_t *,
			  char const *comp_name,
			  tagi_t const *tags);
void tport_deinit_compressor(tport_t *);
541 542 543 544 545 546 547

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);

548
void tport_sigcomp_accept_incomplete(tport_t *self, msg_t *msg);
549

550 551
int tport_recv_comp_dgram(tport_t const *self,
			  tport_compressor_t *sc,
552 553 554
			  msg_t **in_out_msg,
			  su_sockaddr_t *from,
			  socklen_t fromlen);
555

556
ssize_t tport_send_comp(tport_t const *self,
557 558
		    msg_t *msg, 
		    msg_iovec_t iov[], 
559
		    size_t iovused,
560
		    struct sigcomp_compartment *cc,
561
		    tport_compressor_t *sc);
562

563 564 565
SOFIA_END_DECLS

#endif /* TPORT_INTERNAL_H */