tport_internal.h 17.7 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

29 30 31 32 33 34 35 36 37 38 39
/**@file tport_internal.h
 * @brief Transport interface
 *
 * @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
40

41 42 43 44 45 46 47 48 49 50 51 52 53 54
#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

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

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

#include <sofia-sip/su_debug.h>

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

69
#if !HAVE_MSG_TRUNC
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#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 */

/** Transport parameters */
typedef struct {
94
  unsigned tpp_mtu;		/**< Maximum packet size */
95 96
  unsigned tpp_idle;		/**< Allowed connection idle time. */
  unsigned tpp_timeout;		/**< Allowed idle time for message. */
97 98 99
  unsigned tpp_keepalive;	/**< Keepalive PING interval */
  unsigned tpp_pingpong;	/**< PONG-to-PING interval */

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

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

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
  unsigned :0;

} tport_params_t;


/** Transport object.
 *
 * 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 */

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

  unsigned            tp_black:1;       /**< Used by red-black-tree */
  
  unsigned            tp_accepted:1;    /**< Originally server? */
  unsigned            tp_conn_orient:1;	/**< Is connection-oriented */
135
  unsigned            tp_has_connection:1; /**< Has real connection */
136
  unsigned            tp_reusable:1;    /**< Can this connection be reused */
137 138 139 140 141 142 143
  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 */
144 145 146 147
  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;
148
  unsigned            tp_has_stun_server:1;
149
  unsigned            tp_trunc:1;
150
  unsigned            tp_is_connected:1; /**< Connection is established */
151 152 153 154 155 156 157 158 159 160 161
  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 */

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

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

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

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

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

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

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

216 217
  /* ==== Extensions  ===================================================== */

218
  tport_compressor_t *tp_comp;
219

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

/** Primary structure */
struct tport_primary {
  tport_t             pri_primary[1];   /**< Transport part */
231
#if DOXYGEN_ONLY
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
  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 */

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

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

255 256
  void               *pri_stun_handle;

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

/** Master structure */
struct tport_master {
  tport_t             mr_master[1];
263
#if DOXYGEN_ONLY
264 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
  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];
295
    tport_compressor_t   *d_comp;
296 297
  } mr_delivery[1];

298 299 300
  tport_stun_server_t *mr_stun_server;

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

323
/** Virtual function table for transports */
324 325 326 327 328
struct tport_vtable
{
  char const *vtp_name;
  enum tport_via vtp_public;

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

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

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

365 366
int tport_register_type(tport_vtable_t const *vtp);

367
/** Test if transport is needs connect() before sending. */
368
su_inline int tport_is_connection_oriented(tport_t const *self)
369 370 371 372
{
  return self->tp_conn_orient;
}

373
/** Test if transport involves connection. @NEW_1_12_5 */
374
su_inline int tport_has_connection(tport_t const *self)
375
{
376
  return self->tp_has_connection;
377 378
}

379 380
void tport_has_been_updated(tport_t *tport);

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

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

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

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

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

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

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

416
int tport_has_queued(tport_t const *self);
417

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

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

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

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

438 439
void tport_send_queue(tport_t *self);

440
void tport_deliver(tport_t *self, msg_t *msg, msg_t *next, 
441
		   tport_compressor_t *comp,
442 443 444 445 446 447 448 449 450
		   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, 
451
		   char const *via, su_time_t now);
452
void tport_dump_iovec(tport_t const *self, msg_t *msg, 
453
		      size_t n, su_iovec_t const iov[], size_t iovused,
454 455
		      char const *what, char const *how);

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

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

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

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

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

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

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

507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
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);
524 525
int tport_recv_stun_dgram(tport_t const *self, msg_t **in_out_msg,
			  su_sockaddr_t *from, socklen_t fromlen);
526 527 528 529

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

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

char const *tport_canonize_comp(char const *comp);

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

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

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

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

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

562 563 564
SOFIA_END_DECLS

#endif /* TPORT_INTERNAL_H */