5b532c7f |
/* |
53c7e0f1 |
* Copyright (C) 2001-2003 FhG Fokus |
5b532c7f |
* |
6806e46a |
* This file is part of Kamailio, a free SIP server. |
5b532c7f |
* |
6806e46a |
* Kamailio is free software; you can redistribute it and/or modify |
5b532c7f |
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
* |
6806e46a |
* Kamailio is distributed in the hope that it will be useful, |
5b532c7f |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software |
9e1ff448 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
049f64c2 |
* |
5b532c7f |
*/
#ifndef _tcp_conn_h
#define _tcp_conn_h
|
3dc4f620 |
#include "tcp_init.h" |
885b9f62 |
#include "tcp_options.h"
|
6ee62314 |
#include "ip_addr.h" |
ab130758 |
#include "locking.h" |
be7401cc |
#include "atomic_ops.h" |
ef9e3860 |
#include "timer_ticks.h" |
ccb7fda2 |
#include "timer.h" |
5b532c7f |
|
a288ee34 |
/* maximum number of port aliases x search wildcard possibilities */
#define TCP_CON_MAX_ALIASES (4*3) |
59653eb8 |
|
6bc40dea |
#define TCP_CHILD_TIMEOUT 5 /* after 5 seconds, the child "returns"
the connection to the tcp master process */
#define TCP_MAIN_SELECT_TIMEOUT 5 /* how often "tcp main" checks for timeout*/
#define TCP_CHILD_SELECT_TIMEOUT 2 /* the same as above but for children */
|
f6e50f08 |
/* tcp connection flags */ |
fc665070 |
#define F_CONN_READ_W 2 /* watched for READ ev. in main */
#define F_CONN_WRITE_W 4 /* watched for WRITE (main) */
#define F_CONN_READER 8 /* handled by a tcp reader */ |
19782e1c |
#define F_CONN_HASHED 16 /* in tcp_main hash */ |
d22b82a0 |
#define F_CONN_FD_CLOSED 32 /* fd was already closed */
#define F_CONN_PENDING 64 /* pending connect (fd not known yet in main) */
#define F_CONN_MAIN_TIMER 128 /* timer active in the tcp_main process */ |
7498b4dc |
#define F_CONN_EOF_SEEN 256 /* FIN or RST have been received */
#define F_CONN_FORCE_EOF 512 /* act as if an EOF was received */
#define F_CONN_OOB_DATA 1024 /* out of band data on the connection */
#define F_CONN_WR_ERROR 2048 /* write error on the fd */ |
92c0024c |
#define F_CONN_WANTS_RD 4096 /* conn. should be watched for READ */
#define F_CONN_WANTS_WR 8192 /* conn. should be watched for WRITE */ |
6d263c0c |
#define F_CONN_PASSIVE 16384 /* conn. created via accept() and not connect()*/ |
df875b53 |
#define F_CONN_CLOSE_EV 32768 /* explicitely call tcpops ev route when closed */ |
f6e50f08 |
|
2ad5ba6f |
#ifndef NO_READ_HTTP11
#define READ_HTTP11
#endif |
f6e50f08 |
|
122e01f3 |
#ifndef NO_READ_MSRP
#define READ_MSRP
#endif
|
3ec46961 |
#ifndef NO_READ_WS
#define READ_WS
#endif
|
f2f969dd |
enum tcp_req_errors { TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR,
TCP_REQ_OVERRUN, TCP_REQ_BAD_LEN }; |
122e01f3 |
enum tcp_req_states { H_SKIP_EMPTY, H_SKIP_EMPTY_CR_FOUND,
H_SKIP_EMPTY_CRLF_FOUND, H_SKIP_EMPTY_CRLFCR_FOUND,
H_SKIP, H_LF, H_LFCR, H_BODY, H_STARTWS, |
6a157851 |
H_CONT_LEN1, H_CONT_LEN2, H_CONT_LEN3, H_CONT_LEN4, H_CONT_LEN5,
H_CONT_LEN6, H_CONT_LEN7, H_CONT_LEN8, H_CONT_LEN9, H_CONT_LEN10,
H_CONT_LEN11, H_CONT_LEN12, H_CONT_LEN13, H_L_COLON, |
96227c65 |
H_CONT_LEN_BODY, H_CONT_LEN_BODY_PARSE, |
c7337a27 |
H_STUN_MSG, H_STUN_READ_BODY, H_STUN_FP, H_STUN_END, H_PING_CRLF |
b4fbd9f5 |
#ifdef READ_HTTP11
, H_HTTP11_CHUNK_START, H_HTTP11_CHUNK_SIZE,
H_HTTP11_CHUNK_BODY, H_HTTP11_CHUNK_END, H_HTTP11_CHUNK_FINISH
#endif |
122e01f3 |
#ifdef READ_MSRP
, H_MSRP_BODY, H_MSRP_BODY_LF, H_MSRP_BODY_END, H_MSRP_FINISH
#endif |
6a157851 |
}; |
5b532c7f |
|
efc23dce |
enum tcp_conn_states { S_CONN_ERROR=-2, S_CONN_BAD=-1,
S_CONN_OK=0, /* established (write or read) */
S_CONN_INIT, /* initial state (invalid) */
S_CONN_EOF,
S_CONN_ACCEPT, S_CONN_CONNECT
}; |
f6e50f08 |
|
0c5da34b |
/* fd communication commands */ |
3bcc0056 |
enum conn_cmds {
CONN_DESTROY=-3 /* destroy connection & auto-dec. refcnt */,
CONN_ERROR=-2 /* error on connection & auto-dec. refcnt */,
CONN_EOF=-1 /* eof received or conn. closed & auto-dec refcnt */,
CONN_NOP=0 /* do-nothing (invalid for tcp_main) */,
CONN_RELEASE /* release a connection from tcp_read back into tcp_main
& auto-dec refcnt */,
CONN_GET_FD /* request a fd from tcp_main */,
CONN_NEW /* update/set a fd int a new tcp connection; refcnts are
not touched */,
CONN_QUEUED_WRITE /* new write queue: start watching the fd for write &
auto-dec refcnt */,
CONN_NEW_PENDING_WRITE /* like CONN_NEW+CONN_QUEUED_WRITE: set fd and
start watching it for write (write queue
non-empty); refcnts are not touced */,
CONN_NEW_COMPLETE /* like CONN_NEW_PENDING_WRITE, but there is no
pending write (the write queue might be empty) */
}; |
06aaa54f |
/* CONN_RELEASE, EOF, ERROR, DESTROY can be used by "reader" processes |
3bcc0056 |
* CONN_GET_FD, CONN_NEW*, CONN_QUEUED_WRITE only by writers */ |
0c5da34b |
|
5b532c7f |
struct tcp_req{
struct tcp_req* next;
/* sockaddr ? */ |
827cd3be |
char* buf; /* bytes read so far (+0-terminator)*/ |
53c7e0f1 |
char* start; /* where the message starts, after all the empty lines are |
c0c6207a |
skipped*/ |
5b532c7f |
char* pos; /* current position in buf */
char* parsed; /* last parsed position */
char* body; /* body position */ |
827cd3be |
unsigned int b_size; /* buffer size-1 (extra space for 0-term)*/ |
6a157851 |
int content_len; |
b4fbd9f5 |
#ifdef READ_HTTP11
int chunk_size;
#endif |
0051630c |
unsigned short flags; /* F_TCP_REQ_HAS_CLEN | F_TCP_REQ_COMPLETE */ |
6a157851 |
int bytes_to_go; /* how many bytes we have still to read from the body*/ |
f2f969dd |
enum tcp_req_errors error;
enum tcp_req_states state; |
5b532c7f |
};
|
0051630c |
/* tcp_req flags */
#define F_TCP_REQ_HAS_CLEN 1
#define F_TCP_REQ_COMPLETE 2 |
b4fbd9f5 |
#ifdef READ_HTTP11
#define F_TCP_REQ_BCHUNKED 4
#endif |
122e01f3 |
#ifdef READ_MSRP
#define F_TCP_REQ_MSRP_NO 8
#define F_TCP_REQ_MSRP_FRAME 16
#define F_TCP_REQ_MSRP_BODY 32
#endif |
0051630c |
#define TCP_REQ_HAS_CLEN(tr) ((tr)->flags & F_TCP_REQ_HAS_CLEN)
#define TCP_REQ_COMPLETE(tr) ((tr)->flags & F_TCP_REQ_COMPLETE) |
b4fbd9f5 |
#ifdef READ_HTTP11
#define TCP_REQ_BCHUNKED(tr) ((tr)->flags & F_TCP_REQ_BCHUNKED)
#endif |
5b532c7f |
|
6bc40dea |
|
59653eb8 |
struct tcp_connection;
/* tcp port alias structure */
struct tcp_conn_alias{
struct tcp_connection* parent;
struct tcp_conn_alias* next;
struct tcp_conn_alias* prev;
unsigned short port; /* alias port */
unsigned short hash; /* hash index in the address hash */
};
|
76cb799e |
#ifdef TCP_ASYNC |
885b9f62 |
struct tcp_wbuffer{
struct tcp_wbuffer* next;
unsigned int b_size;
char buf[1];
};
struct tcp_wbuffer_queue{
struct tcp_wbuffer* first;
struct tcp_wbuffer* last; |
20863813 |
ticks_t wr_timeout; /* write timeout*/ |
885b9f62 |
unsigned int queued; /* total size */
unsigned int offset; /* offset in the first wbuffer were data
starts */
unsigned int last_used; /* how much of the last buffer is used */
};
#endif
|
6bc40dea |
struct tcp_connection{
int s; /*socket, used by "tcp main" */ |
e29d027b |
int fd; /* used only by "children", don't modify it! private data! */ |
0bd53297 |
gen_lock_t write_lock; |
0c5da34b |
int id; /* id (unique!) used to retrieve a specific connection when
reply-ing*/ |
5c5cd736 |
int reader_pid; /* pid of the active reader process */ |
f2f969dd |
struct receive_info rcv; /* src & dst ip, ports, proto a.s.o*/ |
6bc40dea |
struct tcp_req req; /* request data */ |
be7401cc |
atomic_t refcnt; |
1c93f767 |
enum sip_protos type; /* PROTO_TCP or a protocol over it, e.g. TLS */ |
340ce466 |
unsigned short flags; /* connection related flags */ |
8cf5dde5 |
snd_flags_t send_flags; /* special send flags */ |
1c93f767 |
enum tcp_conn_states state; /* connection state */ |
f6e50f08 |
void* extra_data; /* extra data associated to the connection, 0 for tcp*/ |
ccb7fda2 |
struct timer_ln timer; |
885b9f62 |
ticks_t timeout;/* connection timeout, after this it will be removed*/ |
2f14564f |
ticks_t lifetime;/* connection lifetime */ |
59653eb8 |
unsigned id_hash; /* hash index in the id_hash */ |
8aeb47e2 |
struct tcp_connection* id_next; /* next, prev in id hash table */
struct tcp_connection* id_prev; |
6ee62314 |
struct tcp_connection* c_next; /* child next prev (use locally) */
struct tcp_connection* c_prev; |
7564dcab |
struct tcp_conn_alias con_aliases[TCP_CON_MAX_ALIASES];
int aliases; /* aliases number, at least 1 */ |
76cb799e |
#ifdef TCP_ASYNC |
885b9f62 |
struct tcp_wbuffer_queue wbuf_q;
#endif |
6bc40dea |
};
|
f73a84d5 |
/* helper macros */
|
8cf5dde5 |
#define tcpconn_set_send_flags(c, snd_flags) \ |
5d6752dc |
SND_FLAGS_OR(&(c)->send_flags, &(c)->send_flags, &(snd_flags)) |
340ce466 |
|
8cf5dde5 |
#define tcpconn_close_after_send(c) ((c)->send_flags.f & SND_F_CON_CLOSE) |
340ce466 |
|
f73a84d5 |
#define TCP_RCV_INFO(c) (&(c)->rcv)
#define TCP_RCV_LADDR(r) (&((r).dst_ip))
#define TCP_RCV_LPORT(r) ((r).dst_port)
#define TCP_RCV_PADDR(r) (&((r).src_ip))
#define TCP_RCV_PPORT(r) ((r).src_port)
#define TCP_RCV_PSU(r) (&(r).src_su)
#define TCP_RCV_SOCK_INFO(r) ((r).bind_address)
#define TCP_RCV_PROTO(r) ((r).proto)
#ifdef USE_COMP
#define TCP_RCV_COMP(r) ((r).comp)
#else
#define TCP_RCV_COMP(r) 0
#endif /* USE_COMP */
#define TCP_LADDR(c) TCP_RCV_LADDR(c->rcv)
#define TCP_LPORT(c) TCP_RCV_LPORT(c->rcv)
#define TCP_PADDR(c) TCP_RCV_PADDR(c->rcv)
#define TCP_PPORT(c) TCP_RCV_PPORT(c->rcv)
#define TCP_PSU(c) TCP_RCV_PSU(c->rcv)
#define TCP_SOCK_INFO(c) TCP_RCV_SOCK_INFO(c->rcv)
#define TCP_PROTO(c) TCP_RCV_PROTO(c->rcv)
#define TCP_COMP(c) TCP_RCV_COMP(c->rcv) |
6bc40dea |
|
59653eb8 |
|
be7401cc |
#define tcpconn_ref(c) atomic_inc(&((c)->refcnt)) |
19782e1c |
#define tcpconn_put(c) atomic_dec_and_test(&((c)->refcnt)) |
be7401cc |
|
59653eb8 |
|
827cd3be |
#define init_tcp_req( r, rd_buf, rd_buf_size) \ |
5b532c7f |
do{ \
memset( (r), 0, sizeof(struct tcp_req)); \ |
827cd3be |
(r)->buf=(rd_buf) ;\
(r)->b_size=(rd_buf_size)-1; /* space for 0 term. */ \ |
c0c6207a |
(r)->parsed=(r)->pos=(r)->start=(r)->buf; \ |
5b532c7f |
(r)->error=TCP_REQ_OK;\ |
c0c6207a |
(r)->state=H_SKIP_EMPTY; \ |
5b532c7f |
}while(0)
|
6bc40dea |
/* add a tcpconn to a list*/ |
6ee62314 |
/* list head, new element, next member, prev member */
#define tcpconn_listadd(head, c, next, prev) \ |
6bc40dea |
do{ \
/* add it at the begining of the list*/ \
(c)->next=(head); \
(c)->prev=0; \
if ((head)) (head)->prev=(c); \
(head)=(c); \
} while(0)
|
5b532c7f |
|
6bc40dea |
/* remove a tcpconn from a list*/ |
6ee62314 |
#define tcpconn_listrm(head, c, next, prev) \ |
6bc40dea |
do{ \
if ((head)==(c)) (head)=(c)->next; \
if ((c)->next) (c)->next->prev=(c)->prev; \
if ((c)->prev) (c)->prev->next=(c)->next; \
}while(0) |
5b532c7f |
|
8aeb47e2 |
#define TCPCONN_LOCK lock_get(tcpconn_lock);
#define TCPCONN_UNLOCK lock_release(tcpconn_lock); |
5b532c7f |
|
a288ee34 |
#define TCP_ALIAS_HASH_SIZE 4096 |
8aeb47e2 |
#define TCP_ID_HASH_SIZE 1024
|
a288ee34 |
/* hash (dst_ip, dst_port, local_ip, local_port) */
static inline unsigned tcp_addr_hash( struct ip_addr* ip,
unsigned short port,
struct ip_addr* l_ip,
unsigned short l_port) |
8aeb47e2 |
{ |
a288ee34 |
unsigned h;
if(ip->len==4)
h=(ip->u.addr32[0]^port)^(l_ip->u.addr32[0]^l_port); |
8aeb47e2 |
else if (ip->len==16) |
a288ee34 |
h= (ip->u.addr32[0]^ip->u.addr32[1]^ip->u.addr32[2]^
ip->u.addr32[3]^port) ^
(l_ip->u.addr32[0]^l_ip->u.addr32[1]^l_ip->u.addr32[2]^
l_ip->u.addr32[3]^l_port); |
8aeb47e2 |
else{ |
2ee98a71 |
LM_CRIT("bad len %d for an ip address\n", ip->len); |
8aeb47e2 |
return 0;
} |
a288ee34 |
/* make sure the first bits are influenced by all 32
* (the first log2(TCP_ALIAS_HASH_SIZE) bits should be a mix of all
* 32)*/
h ^= h>>17;
h ^= h>>7;
return h & (TCP_ALIAS_HASH_SIZE-1); |
8aeb47e2 |
}
#define tcp_id_hash(id) (id&(TCP_ID_HASH_SIZE-1)) |
5b532c7f |
|
ef9e3860 |
struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port, |
a288ee34 |
union sockaddr_union* local_addr, |
ef9e3860 |
ticks_t timeout); |
5b532c7f |
|
51655771 |
typedef struct tcp_event_info {
int type;
char *buf;
unsigned int len;
struct receive_info *rcv;
struct tcp_connection *con;
} tcp_event_info_t;
|
1f139814 |
typedef struct ws_event_info {
int type;
char *buf;
unsigned int len;
int id;
} ws_event_info_t;
|
5b532c7f |
#endif
|