• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

tcp_conn.h

00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  *
00028  * History:
00029  * --------
00030  *  2003-01-29  tcp buffer size ++-ed to allow for 0-terminator
00031  *  2003-06-30  added tcp_connection flags & state (andrei) 
00032  *  2003-10-27  tcp port aliases support added (andrei)
00033  *  2006-10-13  added tcp_req_states for STUN (vlada)
00034  *  2007-07-26  improved tcp connection hash function; increased aliases
00035  *               hash size (andrei)
00036  *  2007-11-26  switched to local_timer (andrei)
00037  *  2007-11-30  buffered write support (andrei)
00038  */
00039 
00040 
00041 
00042 #ifndef _tcp_conn_h
00043 #define _tcp_conn_h
00044 
00045 #include "tcp_init.h"
00046 #include "tcp_options.h"
00047 
00048 #include "ip_addr.h"
00049 #include "locking.h"
00050 #include "atomic_ops.h"
00051 #include "timer_ticks.h"
00052 #include "timer.h"
00053 
00054 /* maximum number of port aliases x search wildcard possibilities */
00055 #define TCP_CON_MAX_ALIASES (4*3) 
00056 
00057 #define TCP_CHILD_TIMEOUT 5 /* after 5 seconds, the child "returns" 
00058                                                          the connection to the tcp master process */
00059 #define TCP_MAIN_SELECT_TIMEOUT 5 /* how often "tcp main" checks for timeout*/
00060 #define TCP_CHILD_SELECT_TIMEOUT 2 /* the same as above but for children */
00061 
00062 
00063 /* tcp connection flags */
00064 #define F_CONN_READ_W       2 /* watched for READ ev. in main */
00065 #define F_CONN_WRITE_W      4 /* watched for WRITE (main) */
00066 #define F_CONN_READER       8 /* handled by a tcp reader */
00067 #define F_CONN_HASHED      16 /* in tcp_main hash */
00068 #define F_CONN_FD_CLOSED   32 /* fd was already closed */
00069 #define F_CONN_PENDING     64 /* pending connect  (fd not known yet in main) */
00070 #define F_CONN_MAIN_TIMER 128 /* timer active in the tcp_main process */
00071 #define F_CONN_EOF_SEEN   256 /* FIN or RST have been received */
00072 #define F_CONN_FORCE_EOF  512 /* act as if an EOF was received */
00073 #define F_CONN_OOB_DATA  1024 /* out of band data on the connection */
00074 #define F_CONN_WR_ERROR  2048 /* write error on the fd */
00075 #define F_CONN_WANTS_RD  4096  /* conn. should be watched for READ */
00076 #define F_CONN_WANTS_WR  8192  /* conn. should be watched for WRITE */
00077 #define F_CONN_PASSIVE  16384 /* conn. created via accept() and not connect()*/
00078 
00079 #ifndef NO_READ_HTTP11
00080 #define READ_HTTP11
00081 #endif
00082 
00083 #ifndef NO_READ_MSRP
00084 #define READ_MSRP
00085 #endif
00086 
00087 enum tcp_req_errors {   TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR,
00088                                                 TCP_REQ_OVERRUN, TCP_REQ_BAD_LEN };
00089 enum tcp_req_states {   H_SKIP_EMPTY, H_SKIP_EMPTY_CR_FOUND,
00090                 H_SKIP_EMPTY_CRLF_FOUND, H_SKIP_EMPTY_CRLFCR_FOUND,
00091                 H_SKIP, H_LF, H_LFCR,  H_BODY, H_STARTWS,
00092                 H_CONT_LEN1, H_CONT_LEN2, H_CONT_LEN3, H_CONT_LEN4, H_CONT_LEN5,
00093                 H_CONT_LEN6, H_CONT_LEN7, H_CONT_LEN8, H_CONT_LEN9, H_CONT_LEN10,
00094                 H_CONT_LEN11, H_CONT_LEN12, H_CONT_LEN13, H_L_COLON, 
00095                 H_CONT_LEN_BODY, H_CONT_LEN_BODY_PARSE,
00096                 H_STUN_MSG, H_STUN_READ_BODY, H_STUN_FP, H_STUN_END, H_PING_CRLF
00097 #ifdef READ_HTTP11
00098                 , H_HTTP11_CHUNK_START, H_HTTP11_CHUNK_SIZE,
00099                 H_HTTP11_CHUNK_BODY, H_HTTP11_CHUNK_END, H_HTTP11_CHUNK_FINISH
00100 #endif
00101 #ifdef READ_MSRP
00102                 , H_MSRP_BODY, H_MSRP_BODY_LF, H_MSRP_BODY_END, H_MSRP_FINISH
00103 #endif
00104         };
00105 
00106 enum tcp_conn_states { S_CONN_ERROR=-2, S_CONN_BAD=-1,
00107                                                 S_CONN_OK=0, /* established (write or read) */
00108                                                 S_CONN_INIT, /* initial state (invalid) */
00109                                                 S_CONN_EOF,
00110                                                 S_CONN_ACCEPT, S_CONN_CONNECT
00111                                         };
00112 
00113 
00114 /* fd communication commands */
00115 enum conn_cmds {
00116         CONN_DESTROY=-3 /* destroy connection & auto-dec. refcnt */,
00117         CONN_ERROR=-2   /* error on connection & auto-dec. refcnt */,
00118         CONN_EOF=-1     /* eof received or conn. closed & auto-dec refcnt */,
00119         CONN_NOP=0      /* do-nothing (invalid for tcp_main) */,
00120         CONN_RELEASE    /* release a connection from tcp_read back into tcp_main
00121                                            & auto-dec refcnt */,
00122         CONN_GET_FD     /* request a fd from tcp_main */,
00123         CONN_NEW        /* update/set a fd int a new tcp connection; refcnts are
00124                                           not touched */,
00125         CONN_QUEUED_WRITE /* new write queue: start watching the fd for write &
00126                                                  auto-dec refcnt */,
00127         CONN_NEW_PENDING_WRITE /* like CONN_NEW+CONN_QUEUED_WRITE: set fd and
00128                                                           start watching it for write (write queue
00129                                                           non-empty); refcnts are not touced */,
00130         CONN_NEW_COMPLETE  /* like CONN_NEW_PENDING_WRITE, but there is no
00131                                                   pending write (the write queue might be empty) */
00132 };
00133 /* CONN_RELEASE, EOF, ERROR, DESTROY can be used by "reader" processes
00134  * CONN_GET_FD, CONN_NEW*, CONN_QUEUED_WRITE only by writers */
00135 
00136 struct tcp_req{
00137         struct tcp_req* next;
00138         /* sockaddr ? */
00139         char* buf; /* bytes read so far (+0-terminator)*/
00140         char* start; /* where the message starts, after all the empty lines are
00141                                         skipped*/
00142         char* pos; /* current position in buf */
00143         char* parsed; /* last parsed position */
00144         char* body; /* body position */
00145         unsigned int b_size; /* buffer size-1 (extra space for 0-term)*/
00146         int content_len;
00147 #ifdef READ_HTTP11
00148         int chunk_size;
00149 #endif
00150         unsigned short flags; /* F_TCP_REQ_HAS_CLEN | F_TCP_REQ_COMPLETE */
00151         int bytes_to_go; /* how many bytes we have still to read from the body*/
00152         enum tcp_req_errors error;
00153         enum tcp_req_states state;
00154 };
00155 
00156 /* tcp_req flags */
00157 #define F_TCP_REQ_HAS_CLEN 1
00158 #define F_TCP_REQ_COMPLETE 2
00159 #ifdef READ_HTTP11
00160 #define F_TCP_REQ_BCHUNKED 4
00161 #endif
00162 #ifdef READ_MSRP
00163 #define F_TCP_REQ_MSRP_NO     8
00164 #define F_TCP_REQ_MSRP_FRAME  16
00165 #define F_TCP_REQ_MSRP_BODY   32
00166 #endif
00167 
00168 #define TCP_REQ_HAS_CLEN(tr)  ((tr)->flags & F_TCP_REQ_HAS_CLEN)
00169 #define TCP_REQ_COMPLETE(tr)  ((tr)->flags & F_TCP_REQ_COMPLETE)
00170 #ifdef READ_HTTP11
00171 #define TCP_REQ_BCHUNKED(tr)  ((tr)->flags & F_TCP_REQ_BCHUNKED)
00172 #endif
00173 
00174 
00175 struct tcp_connection;
00176 
00177 /* tcp port alias structure */
00178 struct tcp_conn_alias{
00179         struct tcp_connection* parent;
00180         struct tcp_conn_alias* next;
00181         struct tcp_conn_alias* prev;
00182         unsigned short port; /* alias port */
00183         unsigned short hash; /* hash index in the address hash */
00184 };
00185 
00186 
00187 #ifdef TCP_ASYNC
00188         struct tcp_wbuffer{
00189                 struct tcp_wbuffer* next;
00190                 unsigned int b_size;
00191                 char buf[1];
00192         };
00193 
00194         struct tcp_wbuffer_queue{
00195                 struct tcp_wbuffer* first;
00196                 struct tcp_wbuffer* last;
00197                 ticks_t wr_timeout; /* write timeout*/
00198                 unsigned int queued; /* total size */
00199                 unsigned int offset; /* offset in the first wbuffer were data
00200                                                                 starts */
00201                 unsigned int last_used; /* how much of the last buffer is used */
00202         };
00203 #endif
00204 
00205 
00206 struct tcp_connection{
00207         int s; /*socket, used by "tcp main" */
00208         int fd; /* used only by "children", don't modify it! private data! */
00209         gen_lock_t write_lock;
00210         int id; /* id (unique!) used to retrieve a specific connection when
00211                    reply-ing*/
00212         int reader_pid; /* pid of the active reader process */
00213         struct receive_info rcv; /* src & dst ip, ports, proto a.s.o*/
00214         struct tcp_req req; /* request data */
00215         atomic_t refcnt;
00216         enum sip_protos type; /* PROTO_TCP or a protocol over it, e.g. TLS */
00217         unsigned short flags; /* connection related flags */
00218         snd_flags_t send_flags; /* special send flags */
00219         enum tcp_conn_states state; /* connection state */
00220         void* extra_data; /* extra data associated to the connection, 0 for tcp*/
00221         struct timer_ln timer;
00222         ticks_t timeout;/* connection timeout, after this it will be removed*/
00223         unsigned id_hash; /* hash index in the id_hash */
00224         struct tcp_connection* id_next; /* next, prev in id hash table */
00225         struct tcp_connection* id_prev;
00226         struct tcp_connection* c_next; /* child next prev (use locally) */
00227         struct tcp_connection* c_prev;
00228         struct tcp_conn_alias con_aliases[TCP_CON_MAX_ALIASES];
00229         int aliases; /* aliases number, at least 1 */
00230 #ifdef TCP_ASYNC
00231         struct tcp_wbuffer_queue wbuf_q;
00232 #endif
00233 };
00234 
00235 
00236 /* helper macros */
00237 
00238 #define tcpconn_set_send_flags(c, snd_flags) \
00239         SND_FLAGS_OR(&(c)->send_flags, &(c)->send_flags, &(snd_flags))
00240 
00241 #define tcpconn_close_after_send(c)     ((c)->send_flags.f & SND_F_CON_CLOSE)
00242 
00243 #define TCP_RCV_INFO(c) (&(c)->rcv)
00244 
00245 #define TCP_RCV_LADDR(r) (&((r).dst_ip))
00246 #define TCP_RCV_LPORT(r) ((r).dst_port)
00247 #define TCP_RCV_PADDR(r)  (&((r).src_ip))
00248 #define TCP_RCV_PPORT(r)  ((r).src_port)
00249 #define TCP_RCV_PSU(r)   (&(r).src_su)
00250 #define TCP_RCV_SOCK_INFO(r)  ((r).bind_address)
00251 #define TCP_RCV_PROTO(r)      ((r).proto)
00252 #ifdef USE_COMP
00253 #define TCP_RCV_COMP(r)       ((r).comp)
00254 #else
00255 #define TCP_RCV_COMP(r)  0
00256 #endif /* USE_COMP */
00257 
00258 #define TCP_LADDR(c) TCP_RCV_LADDR(c->rcv)
00259 #define TCP_LPORT(c) TCP_RCV_LPORT(c->rcv)
00260 #define TCP_PADDR(c) TCP_RCV_PADDR(c->rcv)
00261 #define TCP_PPORT(c) TCP_RCV_PPORT(c->rcv)
00262 #define TCP_PSU(c)   TCP_RCV_PSU(c->rcv)
00263 #define TCP_SOCK_INFO(c) TCP_RCV_SOCK_INFO(c->rcv)
00264 #define TCP_PROTO(c) TCP_RCV_PROTO(c->rcv)
00265 #define TCP_COMP(c) TCP_RCV_COMP(c->rcv)
00266 
00267 
00268 
00269 #define tcpconn_ref(c) atomic_inc(&((c)->refcnt))
00270 #define tcpconn_put(c) atomic_dec_and_test(&((c)->refcnt))
00271 
00272 
00273 #define init_tcp_req( r, rd_buf, rd_buf_size) \
00274         do{ \
00275                 memset( (r), 0, sizeof(struct tcp_req)); \
00276                 (r)->buf=(rd_buf) ;\
00277                 (r)->b_size=(rd_buf_size)-1; /* space for 0 term. */ \
00278                 (r)->parsed=(r)->pos=(r)->start=(r)->buf; \
00279                 (r)->error=TCP_REQ_OK;\
00280                 (r)->state=H_SKIP_EMPTY; \
00281         }while(0)
00282 
00283 
00284 /* add a tcpconn to a list*/
00285 /* list head, new element, next member, prev member */
00286 #define tcpconn_listadd(head, c, next, prev) \
00287         do{ \
00288                 /* add it at the begining of the list*/ \
00289                 (c)->next=(head); \
00290                 (c)->prev=0; \
00291                 if ((head)) (head)->prev=(c); \
00292                 (head)=(c); \
00293         } while(0)
00294 
00295 
00296 /* remove a tcpconn from a list*/
00297 #define tcpconn_listrm(head, c, next, prev) \
00298         do{ \
00299                 if ((head)==(c)) (head)=(c)->next; \
00300                 if ((c)->next) (c)->next->prev=(c)->prev; \
00301                 if ((c)->prev) (c)->prev->next=(c)->next; \
00302         }while(0)
00303 
00304 
00305 #define TCPCONN_LOCK lock_get(tcpconn_lock);
00306 #define TCPCONN_UNLOCK lock_release(tcpconn_lock);
00307 
00308 #define TCP_ALIAS_HASH_SIZE 4096
00309 #define TCP_ID_HASH_SIZE 1024
00310 
00311 /* hash (dst_ip, dst_port, local_ip, local_port) */
00312 static inline unsigned tcp_addr_hash(   struct ip_addr* ip, 
00313                                                                                 unsigned short port,
00314                                                                                 struct ip_addr* l_ip,
00315                                                                                 unsigned short l_port)
00316 {
00317         unsigned h;
00318 
00319         if(ip->len==4)
00320                 h=(ip->u.addr32[0]^port)^(l_ip->u.addr32[0]^l_port);
00321         else if (ip->len==16) 
00322                 h= (ip->u.addr32[0]^ip->u.addr32[1]^ip->u.addr32[2]^
00323                                 ip->u.addr32[3]^port) ^
00324                         (l_ip->u.addr32[0]^l_ip->u.addr32[1]^l_ip->u.addr32[2]^
00325                                 l_ip->u.addr32[3]^l_port);
00326         else{
00327                 LOG(L_CRIT, "tcp_addr_hash: BUG: bad len %d for an ip address\n",
00328                                 ip->len);
00329                 return 0;
00330         }
00331         /* make sure the first bits are influenced by all 32
00332          * (the first log2(TCP_ALIAS_HASH_SIZE) bits should be a mix of all
00333          *  32)*/
00334         h ^= h>>17;
00335         h ^= h>>7;
00336         return h & (TCP_ALIAS_HASH_SIZE-1);
00337 }
00338 
00339 #define tcp_id_hash(id) (id&(TCP_ID_HASH_SIZE-1))
00340 
00341 struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port,
00342                                                                         union sockaddr_union* local_addr,
00343                                                                         ticks_t timeout);
00344 
00345 typedef struct tcp_event_info {
00346         int type;
00347         char *buf;
00348         unsigned int len;
00349         struct receive_info *rcv;
00350         struct tcp_connection *con;
00351 } tcp_event_info_t;
00352 
00353 #endif
00354 
00355 

Generated on Tue May 22 2012 13:10:16 for SIP Router by  doxygen 1.7.1