5b532c7f |
/*
* $Id$
*
* Copyright (C) 2001-2003 Fhg Fokus
*
* This file is part of ser, a free SIP server.
*
* ser is free software; you can redistribute it and/or modify
* 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
*
* For a license to use the ser software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* ser 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 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
049f64c2 |
*
*
* history:
* --------
* 2003-01-29 tcp buffer size ++-ed to allow for 0-terminator
|
5b532c7f |
*/
#ifndef _tcp_conn_h
#define _tcp_conn_h
|
6ee62314 |
#include "ip_addr.h"
|
ab130758 |
#include "locking.h"
|
5b532c7f |
#define TCP_BUF_SIZE 65535
|
6bc40dea |
#define TCP_CON_TIMEOUT 60 /* in seconds */
|
ab130758 |
#define TCP_CON_SEND_TIMEOUT 30 /* timeout after a send */
|
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 */
|
f2f969dd |
enum tcp_req_errors { TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR,
TCP_REQ_OVERRUN, TCP_REQ_BAD_LEN };
|
c0c6207a |
enum tcp_req_states { H_SKIP_EMPTY, 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,
H_CONT_LEN_BODY, H_CONT_LEN_BODY_PARSE
};
|
5b532c7f |
|
0c5da34b |
/* fd communication commands */
|
f2f969dd |
enum conn_cmds { CONN_DESTROY=-3, CONN_ERROR=-2, CONN_EOF=-1, CONN_RELEASE,
CONN_GET_FD, CONN_NEW };
|
0c5da34b |
|
5b532c7f |
struct tcp_req{
struct tcp_req* next;
/* sockaddr ? */
|
049f64c2 |
char buf[TCP_BUF_SIZE+1]; /* bytes read so far (+0-terminator)*/
|
c0c6207a |
char* start; /* where the message starts, after alll the empty lines are
skipped*/
|
5b532c7f |
char* pos; /* current position in buf */
char* parsed; /* last parsed position */
char* body; /* body position */
|
6a157851 |
int content_len;
int has_content_len; /* 1 if content_length was parsed ok*/
int complete; /* 1 if one req has been fully read, 0 otherwise*/
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 |
};
|
6bc40dea |
struct tcp_connection{
int s; /*socket, used by "tcp main" */
|
e29d027b |
int fd; /* used only by "children", don't modify it! private data! */
|
ab130758 |
lock_t write_lock;
|
0c5da34b |
int id; /* id (unique!) used to retrieve a specific connection when
reply-ing*/
|
f2f969dd |
struct receive_info rcv; /* src & dst ip, ports, proto a.s.o*/
#if 0
|
6bc40dea |
struct ip_addr ip; /* peer ip */
|
0c5da34b |
int port; /* peer port */
|
6bc40dea |
int sock_idx; /* receiving socket index in the tcp_info array */
union sockaddr_union su;
|
f2f969dd |
#endif
|
6bc40dea |
struct tcp_req req; /* request data */
|
ab130758 |
volatile int refcnt;
int bad; /* if set this is a "bad" connection */
|
6bc40dea |
int timeout; /* connection timeout, after this it will be removed*/
|
ab130758 |
unsigned addr_hash; /* hash indexes in the 2 tables */
|
8aeb47e2 |
unsigned id_hash;
|
6ee62314 |
struct tcp_connection* next; /* next, prev in hash table, used by "main" */
|
6bc40dea |
struct tcp_connection* prev;
|
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;
|
6bc40dea |
};
#define init_tcp_req( r) \
|
5b532c7f |
do{ \
memset( (r), 0, sizeof(struct tcp_req)); \
|
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 |
|
8aeb47e2 |
#define TCP_ADDR_HASH_SIZE 1024
#define TCP_ID_HASH_SIZE 1024
static inline unsigned tcp_addr_hash(struct ip_addr* ip, unsigned short port)
{
if(ip->len==4) return (ip->u.addr32[0]^port)&(TCP_ADDR_HASH_SIZE-1);
else if (ip->len==16)
return (ip->u.addr32[0]^ip->u.addr32[1]^ip->u.addr32[2]^
ip->u.addr32[3]^port) & (TCP_ADDR_HASH_SIZE-1);
else{
LOG(L_CRIT, "tcp_addr_hash: BUG: bad len %d for an ip address\n",
ip->len);
return 0;
}
}
#define tcp_id_hash(id) (id&(TCP_ID_HASH_SIZE-1))
|
5b532c7f |
#endif
|