tport_internal.h 15.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 25 26
/*
 * 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
 *
 */

#ifndef TPORT_INTERNAL_H /** Defined when <tport.h> has been included. */
#define TPORT_INTERNAL_H
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
/**@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
#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

53 54
#include <sofia-sip/tport_plugins.h>

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#ifndef SU_DEBUG
#define SU_DEBUG 3
#endif
#define SU_LOG   tport_log

#include <sofia-sip/su_debug.h>

#if !defined(MSG_NOSIGNAL) || defined(__CYGWIN__)
#undef MSG_NOSIGNAL
#define MSG_NOSIGNAL (0)
#endif

#if !defined(MSG_TRUNC) || defined(SU_HAVE_WINSOCK)
#undef MSG_TRUNC
#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_threadpool tport_threadpool_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 {
  unsigned tpp_mtu;		/**< Maximum packet size */
  unsigned tpp_idle;		/**< Allowed connection idle time. */
  unsigned tpp_timeout;		/**< Allowed idle time for message. */
  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 */

  unsigned tpp_conn_orient:1;   /**< Connection-orienteded */
  unsigned tpp_sdwn_error:1;	/**< If true, shutdown is error. */
107 108
  unsigned tpp_stun_server:1;	/**< If true, use stun server */

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
  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 */

  int                 tp_refs;		/**< Number of references to tport */

  unsigned            tp_black:1;       /**< Used by red-black-tree */
  
  unsigned            tp_accepted:1;    /**< Originally server? */
  unsigned            tp_conn_orient:1;	/**< Is connection-oriented */
  unsigned            tp_connected : 1;	/**< Has real connection */
  unsigned            tp_reusable:1;    /**< Can this connection be reused */
  unsigned            tp_closed : 1;    /**< This transport is closed */
  /**< Remote end has sent FIN (2) or we should not just read */
  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;
138
  unsigned            tp_has_stun_server:1;
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
  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 */

  msg_t const        *tp_rlogged;       /**< Last logged when receiving */
  msg_t const        *tp_slogged;       /**< Last logged when sending */

  unsigned            tp_time;	        /**< When this transport was last used */

  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 */

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

  tport_pending_t    *tp_pending;       /**< Pending requests */
  tport_pending_t    *tp_released;      /**< Released pends */
  unsigned            tp_plen;          /**< Size of tp_pending */
  unsigned            tp_pused;         /**< Used pends */
  unsigned            tp_reported;      /**< Report counter */

  /* ==== 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 */
  unsigned            tp_unsentlen;	/**< Number of unsent iovecs */

  msg_iovec_t        *tp_iov;		/**< Iovecs allocated for sending */
  unsigned            tp_iovlen;	/**< Number of allocated iovecs */

198 199
  /* ==== Extensions  ===================================================== */

200
  tport_compressor_t *tp_comp;
201

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
  /* ==== 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 */
#if DOX
  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. 
					 */

  char                pri_ident[16];
  tport_primary_t    *pri_next;	        /**< Next primary tport */

  tport_t            *pri_secondary;	/**< Secondary tports */

  tport_threadpool_t *pri_threadpool;   /**< Worker threads */
  unsigned            pri_thrpsize;

235
  unsigned            pri_updating:1;   /**< Currently updating address */
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
  unsigned            pri_natted:1;	/**< Using natted address  */
  unsigned            pri_has_tls:1;	/**< Supports tls  */
  unsigned:0;

  tport_params_t      pri_params[1];      /**< Transport parameters */

};

/** Master structure */
struct tport_master {
  tport_t             mr_master[1];
#if DOX
  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];
279
    tport_compressor_t   *d_comp;
280 281
  } mr_delivery[1];

282 283 284
  tport_stun_server_t *mr_stun_server;

#if 0
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
  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];
304
#endif
305 306 307 308 309 310 311 312 313 314
};

/** Virtual funtion table */
struct tport_vtable
{
  char const *vtp_name;
  enum tport_via vtp_public;

  int vtp_pri_size;		/* Size of primary tport */
  int (*vtp_init_primary)(tport_primary_t *pri,
315
			  tp_name_t tpn[1],
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
			  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);

  int vtp_secondary_size;	/* Size of secondary tport */

  int (*vtp_init_secondary)(tport_t *, int socket, int accepted);
  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);
  int (*vtp_send)(tport_t const *self, msg_t *msg,
		  msg_iovec_t iov[], int iovused);
  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);
338 339
  int (*vtp_keepalive)(tport_t *self, su_addrinfo_t const *ai,
		       tagi_t const *taglist);
340 341 342
  int (*vtp_stun_response)(tport_t const *self,
			   void *msg, size_t msglen,
			   void *addr, socklen_t addrlen);
343 344
};

345 346
int tport_register_type(tport_vtable_t const *vtp);

347 348 349 350 351 352 353 354 355 356 357 358
/** Test if transport is needs connect() before sending. */
static inline int tport_is_connection_oriented(tport_t const *self)
{
  return self->tp_conn_orient;
}

/** Test if transport has actual connection. */
static inline int tport_is_connected(tport_t const *self)
{
  return self->tp_connected;
}

359 360
void tport_has_been_updated(tport_t *tport);

361 362 363
int tport_primary_compression(tport_primary_t *pri,
			      char const *compression,
			      tagi_t const *tl);
364 365 366 367 368 369 370 371 372 373 374 375 376 377

tport_t *tport_alloc_secondary(tport_primary_t *pri, int socket, int accepted);
tport_t *tport_base_connect(tport_primary_t *pri, 
			    su_addrinfo_t *ai,
			    su_addrinfo_t *name,
			    tp_name_t const *tpn);
int tport_accept(tport_primary_t *pri, int events);
void tport_zap_secondary(tport_t *self);

int tport_bind_socket(int socket,
		      su_addrinfo_t *ai,
		      char const **return_culprit);
void tport_close(tport_t *self);

378

379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
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);

int tport_recv_iovec(tport_t const *self, 
		     msg_t **mmsg,
		     msg_iovec_t iovec[msg_n_fragments], int N, 
		     int exact);

msg_t *tport_msg_alloc(tport_t const *self, unsigned size);

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

void tport_deliver(tport_t *self, msg_t *msg, msg_t *next, 
400
		   tport_compressor_t *comp,
401 402 403 404 405 406 407 408 409 410 411 412 413 414
		   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, 
		   char const *via, char const *indent, su_time_t now);
void tport_dump_iovec(tport_t const *self, msg_t *msg, 
		      int n, su_iovec_t const iov[], int iovused,
		      char const *what, char const *how);

415 416
extern tport_vtable_t const tport_udp_vtable;
extern tport_vtable_t const tport_udp_client_vtable;
417 418

int tport_udp_init_primary(tport_primary_t *, 
419
			   tp_name_t tpn[1], 
420 421 422
			   su_addrinfo_t *, 
			   tagi_t const *,
			   char const **return_culprit);
423
void tport_udp_deinit_primary(tport_primary_t *);
424 425 426 427 428 429
int tport_recv_dgram(tport_t *self);
int tport_recv_dgram_r(tport_t const *self, msg_t **mmsg, int N);
int tport_send_dgram(tport_t const *self, msg_t *msg,
		     msg_iovec_t iov[], int iovused);
int tport_udp_error(tport_t const *self, su_sockaddr_t name[1]);

430 431
extern tport_vtable_t const tport_tcp_vtable;
extern tport_vtable_t const tport_tcp_client_vtable;
432 433

int tport_tcp_init_primary(tport_primary_t *, 
434
 			  tp_name_t  tpn[1], 
435 436 437
 			  su_addrinfo_t *, tagi_t const *,
 			  char const **return_culprit);
int tport_tcp_init_client(tport_primary_t *, 
438
 			 tp_name_t tpn[1], 
439 440 441 442 443 444 445
 			 su_addrinfo_t *, tagi_t const *,
 			 char const **return_culprit);
int tport_tcp_init_secondary(tport_t *self, int socket, int accepted);
int tport_recv_stream(tport_t *self);
int tport_send_stream(tport_t const *self, msg_t *msg,
		      msg_iovec_t iov[], int iovused);

446 447 448 449 450 451 452
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;
453

454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
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);
int tport_recv_stun_dgram(tport_t const *self, int N);

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

476 477
/* ---------------------------------------------------------------------- */
/* Compressor plugin */
478 479 480 481
extern tport_comp_vtable_t const *tport_comp_vtable;

char const *tport_canonize_comp(char const *comp);

482 483 484 485
int tport_init_compressor(tport_t *,
			  char const *comp_name,
			  tagi_t const *tags);
void tport_deinit_compressor(tport_t *);
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501

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

void tport_try_accept_sigcomp(tport_t *self, msg_t *msg);

int tport_recv_comp_dgram(tport_t *self, int N);

int tport_send_comp(tport_t const *self,
		    msg_t *msg, 
		    msg_iovec_t iov[], 
		    int iovused,
		    struct sigcomp_compartment *cc,
502
		    tport_compressor_t *sc);
503

504 505 506
SOFIA_END_DECLS

#endif /* TPORT_INTERNAL_H */