4 * Copyright (C) 2001-2003 FhG Fokus
6 * This file is part of ser, a free SIP server.
8 * ser is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * For a license to use the ser software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
18 * ser is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 * 2003-01-29 tcp buffer size ++-ed to allow for 0-terminator
31 * 2003-06-30 added tcp_connection flags & state (andrei)
32 * 2003-10-27 tcp port aliases support added (andrei)
33 * 2006-10-13 added tcp_req_states for STUN (vlada)
34 * 2007-07-26 improved tcp connection hash function; increased aliases
36 * 2007-11-26 switched to local_timer (andrei)
37 * 2007-11-30 buffered write support (andrei)
46 #include "tcp_options.h"
50 #include "atomic_ops.h"
51 #include "timer_ticks.h"
54 /* maximum number of port aliases x search wildcard possibilities */
55 #define TCP_CON_MAX_ALIASES (4*3)
57 #define TCP_CHILD_TIMEOUT 5 /* after 5 seconds, the child "returns"
58 the connection to the tcp master process */
59 #define TCP_MAIN_SELECT_TIMEOUT 5 /* how often "tcp main" checks for timeout*/
60 #define TCP_CHILD_SELECT_TIMEOUT 2 /* the same as above but for children */
63 /* tcp connection flags */
64 #define F_CONN_NON_BLOCKING 1
65 #define F_CONN_READ_W 2 /* watched for READ ev. in main */
66 #define F_CONN_WRITE_W 4 /* watched for WRITE (main) */
67 #define F_CONN_READER 8 /* handled by a tcp reader */
68 #define F_CONN_HASHED 16 /* in tcp_main hash */
69 #define F_CONN_FD_CLOSED 32 /* fd was already closed */
70 #define F_CONN_PENDING 64 /* pending connect (fd not known yet in main) */
71 #define F_CONN_MAIN_TIMER 128 /* timer active in the tcp_main process */
72 #define F_CONN_EOF_SEEN 256 /* FIN or RST have been received */
73 #define F_CONN_FORCE_EOF 512 /* act as if an EOF was received */
74 #define F_CONN_OOB_DATA 1024 /* out of band data on the connection */
75 #define F_CONN_WR_ERROR 2048 /* write error on the fd */
76 #define F_CONN_WANTS_RD 4096 /* conn. should be watched for READ */
77 #define F_CONN_WANTS_WR 8192 /* conn. should be watched for WRITE */
80 enum tcp_req_errors { TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR,
81 TCP_REQ_OVERRUN, TCP_REQ_BAD_LEN };
82 enum tcp_req_states { H_SKIP_EMPTY, H_SKIP_EMPTY_CR_FOUND, H_SKIP_EMPTY_CRLF_FOUND, H_SKIP_EMPTY_CRLFCR_FOUND,
83 H_SKIP, H_LF, H_LFCR, H_BODY, H_STARTWS,
84 H_CONT_LEN1, H_CONT_LEN2, H_CONT_LEN3, H_CONT_LEN4, H_CONT_LEN5,
85 H_CONT_LEN6, H_CONT_LEN7, H_CONT_LEN8, H_CONT_LEN9, H_CONT_LEN10,
86 H_CONT_LEN11, H_CONT_LEN12, H_CONT_LEN13, H_L_COLON,
87 H_CONT_LEN_BODY, H_CONT_LEN_BODY_PARSE,
88 H_STUN_MSG, H_STUN_READ_BODY, H_STUN_FP, H_STUN_END, H_PING_CRLF
91 enum tcp_conn_states { S_CONN_ERROR=-2, S_CONN_BAD=-1,
92 S_CONN_OK=0, /* established (write or read) */
93 S_CONN_INIT, /* initial state (invalid) */
95 S_CONN_ACCEPT, S_CONN_CONNECT
99 /* fd communication commands */
100 enum conn_cmds { CONN_DESTROY=-3, CONN_ERROR=-2, CONN_EOF=-1, CONN_RELEASE,
101 CONN_GET_FD, CONN_NEW, CONN_QUEUED_WRITE,
102 CONN_NEW_PENDING_WRITE, CONN_NEW_COMPLETE };
103 /* CONN_RELEASE, EOF, ERROR, DESTROY can be used by "reader" processes
104 * CONN_GET_FD, NEW, ERROR only by writers */
107 struct tcp_req* next;
109 char* buf; /* bytes read so far (+0-terminator)*/
110 char* start; /* where the message starts, after all the empty lines are
112 char* pos; /* current position in buf */
113 char* parsed; /* last parsed position */
114 char* body; /* body position */
115 unsigned int b_size; /* buffer size-1 (extra space for 0-term)*/
117 int has_content_len; /* 1 if content_length was parsed ok*/
118 int complete; /* 1 if one req has been fully read, 0 otherwise*/
119 int bytes_to_go; /* how many bytes we have still to read from the body*/
120 enum tcp_req_errors error;
121 enum tcp_req_states state;
126 struct tcp_connection;
128 /* tcp port alias structure */
129 struct tcp_conn_alias{
130 struct tcp_connection* parent;
131 struct tcp_conn_alias* next;
132 struct tcp_conn_alias* prev;
133 unsigned short port; /* alias port */
134 unsigned short hash; /* hash index in the address hash */
140 struct tcp_wbuffer* next;
145 struct tcp_wbuffer_queue{
146 struct tcp_wbuffer* first;
147 struct tcp_wbuffer* last;
148 ticks_t wr_timeout; /* write timeout*/
149 unsigned int queued; /* total size */
150 unsigned int offset; /* offset in the first wbuffer were data
152 unsigned int last_used; /* how much of the last buffer is used */
157 struct tcp_connection{
158 int s; /*socket, used by "tcp main" */
159 int fd; /* used only by "children", don't modify it! private data! */
160 gen_lock_t write_lock;
161 int id; /* id (unique!) used to retrieve a specific connection when
163 int reader_pid; /* pid of the active reader process */
164 struct receive_info rcv; /* src & dst ip, ports, proto a.s.o*/
165 struct tcp_req req; /* request data */
167 enum sip_protos type; /* PROTO_TCP or a protocol over it, e.g. TLS */
168 int flags; /* connection related flags */
169 enum tcp_conn_states state; /* connection state */
170 void* extra_data; /* extra data associated to the connection, 0 for tcp*/
171 struct timer_ln timer;
172 ticks_t timeout;/* connection timeout, after this it will be removed*/
173 unsigned id_hash; /* hash index in the id_hash */
174 struct tcp_connection* id_next; /* next, prev in id hash table */
175 struct tcp_connection* id_prev;
176 struct tcp_connection* c_next; /* child next prev (use locally) */
177 struct tcp_connection* c_prev;
178 struct tcp_conn_alias con_aliases[TCP_CON_MAX_ALIASES];
179 int aliases; /* aliases number, at least 1 */
181 struct tcp_wbuffer_queue wbuf_q;
189 #define tcpconn_ref(c) atomic_inc(&((c)->refcnt))
190 #define tcpconn_put(c) atomic_dec_and_test(&((c)->refcnt))
193 #define init_tcp_req( r, rd_buf, rd_buf_size) \
195 memset( (r), 0, sizeof(struct tcp_req)); \
197 (r)->b_size=(rd_buf_size)-1; /* space for 0 term. */ \
198 (r)->parsed=(r)->pos=(r)->start=(r)->buf; \
199 (r)->error=TCP_REQ_OK;\
200 (r)->state=H_SKIP_EMPTY; \
204 /* add a tcpconn to a list*/
205 /* list head, new element, next member, prev member */
206 #define tcpconn_listadd(head, c, next, prev) \
208 /* add it at the begining of the list*/ \
211 if ((head)) (head)->prev=(c); \
216 /* remove a tcpconn from a list*/
217 #define tcpconn_listrm(head, c, next, prev) \
219 if ((head)==(c)) (head)=(c)->next; \
220 if ((c)->next) (c)->next->prev=(c)->prev; \
221 if ((c)->prev) (c)->prev->next=(c)->next; \
225 #define TCPCONN_LOCK lock_get(tcpconn_lock);
226 #define TCPCONN_UNLOCK lock_release(tcpconn_lock);
228 #define TCP_ALIAS_HASH_SIZE 4096
229 #define TCP_ID_HASH_SIZE 1024
231 /* hash (dst_ip, dst_port, local_ip, local_port) */
232 static inline unsigned tcp_addr_hash( struct ip_addr* ip,
234 struct ip_addr* l_ip,
235 unsigned short l_port)
240 h=(ip->u.addr32[0]^port)^(l_ip->u.addr32[0]^l_port);
241 else if (ip->len==16)
242 h= (ip->u.addr32[0]^ip->u.addr32[1]^ip->u.addr32[2]^
243 ip->u.addr32[3]^port) ^
244 (l_ip->u.addr32[0]^l_ip->u.addr32[1]^l_ip->u.addr32[2]^
245 l_ip->u.addr32[3]^l_port);
247 LOG(L_CRIT, "tcp_addr_hash: BUG: bad len %d for an ip address\n",
251 /* make sure the first bits are influenced by all 32
252 * (the first log2(TCP_ALIAS_HASH_SIZE) bits should be a mix of all
256 return h & (TCP_ALIAS_HASH_SIZE-1);
259 #define tcp_id_hash(id) (id&(TCP_ID_HASH_SIZE-1))
261 struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port,
262 union sockaddr_union* local_addr,