Browse code

- preliminary tcp support (it doesn't work, it's just for debugging, as long as you compile w/o -DUSE_TCP you should be safe) Note: sip + tcp really sucks

Andrei Pelinescu-Onciul authored on 29/11/2002 21:12:24
Showing 9 changed files
... ...
@@ -131,6 +131,9 @@ YACC := $(shell echo "$${YACC}")
131 131
 #  		if enabled, allows forking of the snmp agent just before child
132 132
 #  		forking (done at the top of main_loop). Needed if you want
133 133
 #  		to use the snmp module.
134
+# -DUSE_TCP
135
+#		compiles in tcp support (highly experimental for now, it will probably
136
+#		not work, use it only if you really now what you are doing)
134 137
 DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
135 138
 	 -DOS='"$(OS)"' -DCOMPILER='"$(CC_VER)"' -D__CPU_$(ARCH)\
136 139
 	 -DCFG_DIR='"$(cfg-target)"'\
... ...
@@ -140,6 +143,7 @@ DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
140 143
 	 -DDNS_IP_HACK \
141 144
 	 -DUSE_IPV6 \
142 145
 	 -DDBG_QM_MALLOC \
146
+	# -DUSE_TCP \
143 147
 	 #-DF_MALLOC \
144 148
 	 #-DNO_DEBUG \
145 149
 	 #-DNO_LOG
... ...
@@ -293,7 +297,7 @@ ifeq	($(ARCH), i386)
293 297
 		# if gcc 
294 298
 ifeq		($(CC_NAME), gcc)
295 299
 				#common stuff
296
-				CFLAGS=-O9 -funroll-loops  -Wcast-align $(PROFILE) \
300
+				CFLAGS=-g -O9 -funroll-loops  -Wcast-align $(PROFILE) \
297 301
 					-Wall   \
298 302
 			#if gcc 3.0
299 303
 ifeq			($(CC_SHORTVER), 3.0)
... ...
@@ -46,6 +46,7 @@
46 46
 extern char * cfg_file;
47 47
 extern char *stat_file;
48 48
 extern struct socket_info sock_info[]; /* all addresses we listen/send from*/
49
+extern struct socket_info tcp_info[]; /* all tcp sockets we listen on*/
49 50
 extern int sock_no; /* number of addresses/open sockets*/
50 51
 extern unsigned short port_no;
51 52
 /*
... ...
@@ -67,6 +68,9 @@ extern struct socket_info* sendipv6; /* same as above for ipv6 */
67 68
 
68 69
 extern unsigned int maxbuffer;
69 70
 extern int children_no;
71
+#ifdef USE_TCP
72
+extern int tcp_children_no;
73
+#endif
70 74
 extern int dont_fork;
71 75
 extern int check_via;
72 76
 extern int received_dns;
... ...
@@ -40,7 +40,8 @@
40 40
 
41 41
 #include "dprint.h"
42 42
 
43
-
43
+#define SOCKET_TCP	1
44
+#define SOCKET_UDP	0
44 45
 
45 46
 struct ip_addr{
46 47
 	unsigned int af; /* address family: AF_INET6 or AF_INET */
... ...
@@ -80,6 +81,7 @@ struct socket_info{
80 81
 	int is_ip; /* 1 if name is an ip address, 0 if not  -- optimization*/
81 82
 	int is_lo; /* 1 if is a loopback, 0 if not */
82 83
 	union sockaddr_union su; 
84
+	int proto; /* tcp or udp*/
83 85
 };
84 86
 
85 87
 
... ...
@@ -136,7 +138,7 @@ void print_net(struct net* net);
136 138
 	[ diff. adress fams ]) */
137 139
 inline static int matchnet(struct ip_addr* ip, struct net* net)
138 140
 {
139
-	int r;
141
+	unsigned int r;
140 142
 	int ret;
141 143
 	
142 144
 	ret=-1;
... ...
@@ -94,6 +94,9 @@ static char flags[]=
94 94
 #ifdef USE_IPV6
95 95
 ", USE_IPV6"
96 96
 #endif
97
+#ifdef USE_TCP
98
+", USE_TCP"
99
+#endif
97 100
 #ifdef NO_DEBUG
98 101
 ", NO_DEBUG"
99 102
 #endif
... ...
@@ -225,6 +228,9 @@ unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do
225 228
 												  auto-probing procedure; may 
226 229
 												  be re-configured */
227 230
 int children_no = 0;			/* number of children processing requests */
231
+#ifdef USE_TCP
232
+int tcp_children_no = 0;
233
+#endif
228 234
 struct process_table *pt=0;		/*array with childrens pids, 0= main proc,
229 235
 									alloc'ed in shared mem if possible*/
230 236
 int sig_flag = 0;              /* last signal received */
... ...
@@ -266,6 +272,9 @@ struct ip_addr addresses[MAX_LISTEN]; /* our ips */
266 272
 int addresses_no=0;                   /* number of names/ips */
267 273
 #endif
268 274
 struct socket_info sock_info[MAX_LISTEN];/*all addresses we listen/send from*/
275
+#ifdef USE_TCP
276
+struct socket_info tcp_info[MAX_LISTEN];/*all tcp addresses we listen on*/
277
+#endif
269 278
 int sock_no=0; /* number of addresses/open sockets*/
270 279
 struct socket_info* bind_address=0; /* pointer to the crt. proc.
271 280
 									 listening address*/
... ...
@@ -616,6 +625,21 @@ int main_loop()
616 625
 			/* all procs should have access to all the sockets (for sending)
617 626
 			 * so we open all first*/
618 627
 		}
628
+#ifdef USE_TCP
629
+			/* start tcp master proc */
630
+		process_no++;
631
+		if ((pid=fork())<0){
632
+			LOG(L_CRIT, "main_loop: cannot fork tcp main process\n");
633
+			goto error;
634
+		}else if (pid==0){
635
+			/* child */
636
+			/* is_main=0; */
637
+			tcp_main();
638
+		}else{
639
+			pt[process_no].pid=pid;
640
+			strncpy(pt[process_no].desc, "tcp main process", MAX_PT_DESC );
641
+		}
642
+#endif
619 643
 		for(r=0; r<sock_no;r++){
620 644
 			for(i=0;i<children_no;i++){
621 645
 				process_no++;
... ...
@@ -1165,6 +1189,9 @@ try_again:
1165 1189
 
1166 1190
 	
1167 1191
 	if (children_no<=0) children_no=CHILD_NO;
1192
+#ifdef USE_TCP
1193
+	tcp_children_no=children_no;
1194
+#endif
1168 1195
 #ifdef _OBSOLETED
1169 1196
 	else if (children_no >= MAX_PROCESSES ) {
1170 1197
 		fprintf(stderr, "ERROR: too many children processes configured;"
1171 1198
new file mode 100644
... ...
@@ -0,0 +1,124 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2001-2003 Fhg Fokus
5
+ *
6
+ * This file is part of ser, a free SIP server.
7
+ *
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
12
+ *
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:
16
+ *    info@iptel.org
17
+ *
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.
22
+ *
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
26
+ */
27
+
28
+#ifdef USE_TCP
29
+
30
+#include <sys/types.h>
31
+#include <sys/socket.h>
32
+
33
+/* remove this after replacing fprintf*/
34
+#include <stdio.h>
35
+
36
+
37
+/* at least 1 byte must be sent! */
38
+int send_fd(int unix_socket, void* data, int data_len, int fd)
39
+{
40
+	struct msghdr msg;
41
+	struct iovec iov[1];
42
+	struct cmsghdr* cmsg;
43
+	int ret;
44
+	union {
45
+		struct cmsghdr cm;
46
+		char control[CMSG_SPACE(sizeof(fd))];
47
+	}control_un;
48
+	
49
+	msg.msg_control=control_un.control;
50
+	msg.msg_controllen=sizeof(control_un.control);
51
+	
52
+	msg.msg_name=0;
53
+	msg.msg_namelen=0;
54
+	
55
+	iov[0].iov_base=data;
56
+	iov[0].iov_len=data_len;
57
+	msg.msg_iov=iov;
58
+	msg.msg_iovlen=1;
59
+	
60
+	cmsg=CMSG_FIRSTHDR(&msg);
61
+	cmsg->cmsg_level = SOL_SOCKET;
62
+	cmsg->cmsg_type = SCM_RIGHTS;
63
+	cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
64
+	*(int*)CMSG_DATA(cmsg)=fd;
65
+	msg.msg_flags=0;
66
+	
67
+	ret=sendmsg(unix_socket, &msg, 0);
68
+	
69
+	return ret;
70
+}
71
+
72
+
73
+
74
+int receive_fd(int unix_socket, void* data, int data_len, int* fd)
75
+{
76
+	struct msghdr msg;
77
+	struct iovec iov[1];
78
+	struct cmsghdr* cmsg;
79
+	int new_fd;
80
+	int ret;
81
+	union{
82
+		struct cmsghdr cm;
83
+		char control[CMSG_SPACE(sizeof(new_fd))];
84
+	}control_un;
85
+	
86
+	msg.msg_control=control_un.control;
87
+	msg.msg_controllen=sizeof(control_un.control);
88
+	
89
+	msg.msg_name=0;
90
+	msg.msg_namelen=0;
91
+	
92
+	iov[0].iov_base=data;
93
+	iov[0].iov_len=data_len;
94
+	msg.msg_iov=iov;
95
+	msg.msg_iovlen=1;
96
+	
97
+	ret=recvmsg(unix_socket, &msg, 0);
98
+	if (ret<=0) goto error;
99
+	
100
+	cmsg=CMSG_FIRSTHDR(&msg);
101
+	if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){
102
+		if (cmsg->cmsg_type!= SCM_RIGHTS){
103
+			fprintf(stderr, " msg control type != SCM_RIGHTS\n");
104
+			ret=-1;
105
+			goto error;
106
+		}
107
+		if (cmsg->cmsg_level!= SOL_SOCKET){
108
+			fprintf(stderr, " msg level != SOL_SOCKET\n");
109
+			ret=-1;
110
+			goto error;
111
+		}
112
+		*fd=*((int*) CMSG_DATA(cmsg));
113
+	}else{
114
+		fprintf(stderr, " no descriptor passed, cmsg=%p, len=%d\n",
115
+				cmsg, cmsg->cmsg_len);
116
+		*fd=-1;
117
+		/* it's not really an error */
118
+	}
119
+	
120
+error:
121
+	return ret;
122
+}
123
+
124
+#endif
0 125
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2001-2003 Fhg Fokus
5
+ *
6
+ * This file is part of ser, a free SIP server.
7
+ *
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
12
+ *
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:
16
+ *    info@iptel.org
17
+ *
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.
22
+ *
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
26
+ */
27
+
28
+#ifndef _pass_fd_h
29
+#define _pass_fd_h
30
+
31
+
32
+int send_fd(int unix_socket, void* data, int data_len, int fd);
33
+int receive_fd(int unix_socket, void* data, int data_len, int* fd);
34
+
35
+
36
+
37
+#endif
0 38
new file mode 100644
... ...
@@ -0,0 +1,71 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2001-2003 Fhg Fokus
5
+ *
6
+ * This file is part of ser, a free SIP server.
7
+ *
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
12
+ *
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:
16
+ *    info@iptel.org
17
+ *
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.
22
+ *
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
26
+ */
27
+
28
+
29
+
30
+#ifndef _tcp_conn_h
31
+#define _tcp_conn_h
32
+
33
+
34
+
35
+#define TCP_BUF_SIZE 65535
36
+enum {TCP_REQ_INIT, TCP_REQ_OK, TCP_READ_ERROR, TCP_REQ_OVERRUN };
37
+enum {H_PARSING, H_LF, H_LFCR,  H_BODY };
38
+
39
+struct tcp_req{
40
+	struct tcp_req* next;
41
+	int fd;
42
+	/* sockaddr ? */
43
+	char buf[TCP_BUF_SIZE]; /* bytes read so far*/
44
+	char* pos; /* current position in buf */
45
+	char* parsed; /* last parsed position */
46
+	char* body; /* body position */
47
+	int error;
48
+	int state;
49
+};
50
+
51
+
52
+#define init_tcp_req( r, f) \
53
+	do{ \
54
+		memset( (r), 0, sizeof(struct tcp_req)); \
55
+		(r)->fd=(f); \
56
+		(r)->parsed=(r)->pos=(r)->buf; \
57
+		(r)->error=TCP_REQ_OK;\
58
+		(r)->state=H_PARSING; \
59
+	}while(0)
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+#endif
70
+
71
+
0 72
new file mode 100644
... ...
@@ -0,0 +1,357 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2001-2003 Fhg Fokus
5
+ *
6
+ * This file is part of ser, a free SIP server.
7
+ *
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
12
+ *
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:
16
+ *    info@iptel.org
17
+ *
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.
22
+ *
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
26
+ */
27
+
28
+
29
+#ifdef USE_TCP
30
+
31
+#include <sys/select.h>
32
+
33
+#include <sys/time.h>
34
+#include <sys/types.h>
35
+#include <sys/socket.h>
36
+
37
+#include <unistd.h>
38
+
39
+#include <errno.h>
40
+#include <string.h>
41
+
42
+
43
+
44
+#include "ip_addr.h"
45
+#include "pass_fd.h"
46
+#include "globals.h"
47
+#include "mem/mem.h"
48
+
49
+
50
+#define local_malloc pkg_malloc
51
+#define local_free   pkg_free
52
+
53
+#define MAX_TCP_CHILDREN 100
54
+
55
+struct tcp_child{
56
+	pid_t pid;
57
+	int s; /* unix socket for comm*/
58
+	int busy;
59
+	int n_reqs; /* number of requests serviced so far */
60
+};
61
+
62
+
63
+enum { CONN_OK, CONN_ERROR };
64
+
65
+struct tcp_connection{
66
+	int s; /*socket */
67
+	struct ip_addr ip;
68
+	union sockaddr_union su;
69
+	int refcnt;
70
+	struct tcp_connection* next;
71
+	struct tcp_connection* prev;
72
+};
73
+
74
+
75
+
76
+struct tcp_connection* conn_list=0;
77
+struct tcp_child tcp_children[MAX_TCP_CHILDREN];
78
+
79
+
80
+
81
+struct tcp_connection*  tcpconn_add(int sock, union sockaddr_union* su)
82
+{
83
+	struct tcp_connection *c;
84
+	
85
+
86
+	c=(struct tcp_connection*)local_malloc(sizeof(struct tcp_connection));
87
+	if (c==0){
88
+		LOG(L_ERR, "ERROR: tcpconn_add: mem. allocation failure\n");
89
+		goto error;
90
+	}
91
+	c->s=sock;
92
+	c->su=*su;
93
+	c->refcnt=0;
94
+	su2ip_addr(&c->ip, su);
95
+
96
+	/* add it at the begining of the list*/
97
+	c->next=conn_list;
98
+	c->prev=0;
99
+	if (conn_list) conn_list->prev=c;
100
+	conn_list=c;
101
+	return c;
102
+	
103
+error:
104
+	return 0;
105
+}
106
+
107
+
108
+
109
+void tcpconn_rm(struct tcp_connection* c)
110
+{
111
+	
112
+	if (conn_list==c) conn_list=c->next;
113
+	if (c->next) c->next->prev=c->prev;
114
+	if (c->prev) c->prev->next=c->next;
115
+	local_free(c);
116
+}
117
+
118
+
119
+
120
+int tcp_init_sock(struct socket_info* sock_info)
121
+{
122
+	union sockaddr_union* addr;
123
+	
124
+	addr=&sock_info->su;
125
+	sock_info->proto=SOCKET_TCP;
126
+	if (init_su(addr, &sock_info->address, htons(sock_info->port_no))<0){
127
+		LOG(L_ERR, "ERROR: tcp_init: could no init sockaddr_union\n");
128
+		goto error;
129
+	}
130
+	sock_info->socket=socket(AF2PF(addr->s.sa_family), SOCK_STREAM, 0);
131
+	if (sock_info->socket==-1){
132
+		LOG(L_ERR, "ERROR: tcp_init: socket: %s\n", strerror(errno));
133
+		goto error;
134
+	}
135
+	if (bind(sock_info->socket, &addr->s, sockaddru_len(*addr))==-1){
136
+		LOG(L_ERR, "ERROR: tcp_init: bind(%x, %p, %d) on %s: %s\n",
137
+				sock_info->socket, &addr->s, 
138
+				sockaddru_len(*addr),
139
+				sock_info->address_str.s,
140
+				strerror(errno));
141
+		goto error;
142
+	}
143
+	if (listen(sock_info->socket, 10)==-1){
144
+		LOG(L_ERR, "ERROR: tcp_init: listen(%x, %p, %d) on %s: %s\n",
145
+				sock_info->socket, &addr->s, 
146
+				sockaddru_len(*addr),
147
+				sock_info->address_str.s,
148
+				strerror(errno));
149
+		goto error;
150
+	}
151
+	
152
+	return 0;
153
+error:
154
+	if (sock_info->socket!=-1){
155
+		close(sock_info->socket);
156
+		sock_info->socket=-1;
157
+	}
158
+	return -1;
159
+}
160
+
161
+
162
+
163
+static int send2child(struct tcp_connection* tcpconn)
164
+{
165
+	int i;
166
+	
167
+	for (i=0; i<tcp_children_no; i++){
168
+		if (!tcp_children[i].busy){
169
+			tcp_children[i].busy=1;
170
+			tcp_children[i].n_reqs++;
171
+			tcpconn->refcnt++;
172
+			DBG("send2child: to child %d, %ld\n", i, (long)tcpconn);
173
+			send_fd(tcp_children[i].s, &tcpconn, sizeof(tcpconn), tcpconn->s);
174
+			return 0;
175
+		}
176
+	}
177
+	if (i==tcp_children_no){
178
+		return -1;
179
+	}
180
+	return 0; /* just to fix a warning*/
181
+}
182
+
183
+
184
+void tcp_main_loop()
185
+{
186
+	int r;
187
+	int n;
188
+	fd_set master_set;
189
+	fd_set sel_set;
190
+	int maxfd;
191
+	int new_sock;
192
+	union sockaddr_union su;
193
+	struct tcp_connection* tcpconn;
194
+	long response[2];
195
+	int state;
196
+	socklen_t su_len;
197
+
198
+	/*init */
199
+	maxfd=0;
200
+	FD_ZERO(&master_set);
201
+	/* set all the listen addresses */
202
+	for (r=0; r<sock_no; r++){
203
+		if ((tcp_info[r].proto==SOCKET_TCP) &&(tcp_info[r].socket!=-1)){
204
+			FD_SET(tcp_info[r].socket, &master_set);
205
+			if (tcp_info[r].socket>maxfd) maxfd=tcp_info[r].socket;
206
+		}
207
+	}
208
+	/* set all the unix sockets used for child comm */
209
+	for (r=0; r<tcp_children_no; r++){
210
+		if (tcp_children[r].s>=0){
211
+			FD_SET(tcp_children[r].s, &master_set);
212
+			if (tcp_children[r].s>maxfd) maxfd=tcp_children[r].s;
213
+		}
214
+	}
215
+	
216
+	
217
+	/* main loop*/
218
+	
219
+	while(1){
220
+		sel_set=master_set;
221
+		n=select(maxfd+1, &sel_set, 0 ,0 , 0);
222
+		if (n<0){
223
+			/* errors */
224
+		}
225
+		
226
+		for (r=0; r<sock_no && n; r++){
227
+			if ((tcp_info[r].proto==SOCKET_TCP) &&
228
+					(FD_ISSET(tcp_info[r].socket, &sel_set))){
229
+				/* got a connection on r */
230
+				su_len=sizeof(su);
231
+				new_sock=accept(tcp_info[r].socket, &(su.s), &su_len);
232
+				n--;
233
+				if (new_sock<0){
234
+					LOG(L_ERR,  "WARNING: tcp_main_loop: error while accepting"
235
+							" connection(%d): %s\n", errno, strerror(errno));
236
+					continue;
237
+				}
238
+				
239
+				/* add socket to list */
240
+				tcpconn=tcpconn_add(new_sock, &su);
241
+				DBG("tcp_main_loop: new connection: %p %d\n",
242
+						tcpconn, tcpconn->s);
243
+				/* pass it to a child */
244
+				if(send2child(tcpconn)<0){
245
+					LOG(L_ERR,"ERROR: tcp_main_loop: no children available\n");
246
+					close(tcpconn->s);
247
+					tcpconn_rm(tcpconn);
248
+				}
249
+			}
250
+		}
251
+		
252
+		/* check all the read fds (from the tcpconn list) */
253
+		
254
+		for(tcpconn=conn_list; tcpconn && n; tcpconn=tcpconn->next){
255
+			if ((tcpconn->refcnt==0)&&(FD_ISSET(tcpconn->s, &sel_set))){
256
+				/* new data available */
257
+				n--;
258
+				/* pass it to child, so remove it from select list */
259
+				DBG("tcp_main_loop: data available on %p %d\n",
260
+						tcpconn, tcpconn->s);
261
+				FD_CLR(tcpconn->s, &master_set);
262
+				if (send2child(tcpconn)<0){
263
+					LOG(L_ERR,"ERROR: tcp_main_loop: no children available\n");
264
+					close(tcpconn->s);
265
+					tcpconn_rm(tcpconn);
266
+				}
267
+			}
268
+		}
269
+		
270
+		/* check unix sockets & listen | destroy connections */
271
+		for (r=0; r<tcp_children_no && n; r++){
272
+			if (FD_ISSET(tcp_children[r].s, &sel_set)){
273
+				n--;
274
+				/* errno==EINTR !!! todo*/
275
+				read(tcp_children[r].s, response, sizeof(response));
276
+				DBG("tcp__main_loop: read response= %lx, %ld\n",
277
+						response[0], response[1]);
278
+				tcp_children[r].busy=0;
279
+				tcpconn=(struct tcp_connection*)response[0];
280
+				state=response[1];
281
+				if (tcpconn){
282
+					tcpconn->refcnt--;
283
+					if (state>=0){
284
+						/* listen on this too */
285
+						if (tcpconn->refcnt==0){
286
+							FD_SET(tcpconn->s, &master_set);
287
+							if (maxfd<tcpconn->s) maxfd=tcpconn->s;
288
+						}
289
+					}else{
290
+						/*error, we should destroy it */
291
+						if (tcpconn->refcnt==0){
292
+							DBG("tcp_main_loop: destroying connection\n");
293
+							close(tcpconn->s);
294
+							tcpconn_rm(tcpconn);
295
+						}else{
296
+							DBG("tcp_main_loop: delaying ...\n");
297
+						}
298
+					}
299
+				}else{
300
+					LOG(L_CRIT, "BUG: tcp_main_loop: null tcp conn pointer\n");
301
+				}
302
+			}
303
+		}
304
+	
305
+	}
306
+}
307
+
308
+
309
+
310
+/* starts the tcp processes */
311
+int tcp_main()
312
+{
313
+	int r;
314
+	int sockfd[2];
315
+	pid_t pid;
316
+	
317
+	
318
+	/* create the tcp sock_info structures */
319
+	/* copy the sockets*/
320
+	for (r=0; r<sock_no ; r++){
321
+		tcp_info[r]=sock_info[r];
322
+		tcp_init_sock(&tcp_info[r]);
323
+	}
324
+	
325
+	/* fork children & create the socket pairs*/
326
+	for(r=0; r<tcp_children_no; r++){
327
+		if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd)<0){
328
+			LOG(L_ERR, "ERROR: tcp_main: socketpair failed: %s\n",
329
+					strerror(errno));
330
+			goto error;
331
+		}
332
+		
333
+		pid=fork();
334
+		if (pid<0){
335
+			LOG(L_ERR, "ERROR: tcp_main: fork failed: %s\n",
336
+					strerror(errno));
337
+			goto error;
338
+		}else if (pid>0){
339
+			/* parent */
340
+			close(sockfd[1]);
341
+			tcp_children[r].pid=pid;
342
+			tcp_children[r].s=sockfd[0];
343
+			tcp_children[r].busy=0;
344
+			tcp_children[r].n_reqs=0;
345
+		}else{
346
+			/* child */
347
+			close(sockfd[0]);
348
+			tcp_receive_loop(sockfd[1]);
349
+		}
350
+	}
351
+	
352
+	tcp_main_loop();
353
+error:
354
+	return -1;
355
+}
356
+
357
+#endif
0 358
new file mode 100644
... ...
@@ -0,0 +1,253 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2001-2003 Fhg Fokus
5
+ *
6
+ * This file is part of ser, a free SIP server.
7
+ *
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
12
+ *
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:
16
+ *    info@iptel.org
17
+ *
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.
22
+ *
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
26
+ */
27
+
28
+#ifdef USE_TCP
29
+
30
+#include <stdio.h>
31
+#include <errno.h>
32
+#include <string.h>
33
+
34
+#include <sys/select.h>
35
+
36
+#include <sys/time.h>
37
+#include <sys/types.h>
38
+#include <sys/socket.h>
39
+
40
+#include <unistd.h>
41
+
42
+
43
+#include "tcp_conn.h"
44
+#include "pass_fd.h"
45
+
46
+
47
+#define q_memchr memchr
48
+
49
+/* reads next available bytes
50
+ * return number of bytes read, 0 on EOF or -1 on error,
51
+ * sets also r->error */
52
+int tcp_read(struct tcp_req *r)
53
+{
54
+	int bytes_free, bytes_read;
55
+	
56
+	bytes_free=TCP_BUF_SIZE- (int)(r->pos - r->buf);
57
+	
58
+	if (bytes_free==0){
59
+		fprintf(stderr, "buffer overrun, dropping\n");
60
+		r->error=TCP_REQ_OVERRUN;
61
+		return -1;
62
+	}
63
+again:
64
+	bytes_read=read(r->fd, r->pos, bytes_free);
65
+
66
+	if(bytes_read==-1){
67
+		if (errno == EWOULDBLOCK || errno == EAGAIN){
68
+			return 0; /* nothing has been read */
69
+		}else if (errno == EINTR) goto again;
70
+		else{
71
+			fprintf(stderr, "error reading: %s\n", strerror(errno));
72
+			r->error=TCP_READ_ERROR;
73
+			return -1;
74
+		}
75
+	}
76
+	
77
+	r->pos+=bytes_read;
78
+	return bytes_read;
79
+}
80
+
81
+
82
+
83
+/* reads all headers (until double crlf),
84
+ * returns number of bytes read & sets r->state & r->body
85
+ * when either r->body!=0 or r->state==H_BODY =>
86
+ * all headers have been read. It should be called in a while loop.
87
+ * returns < 0 if error or 0 if EOF */
88
+int tcp_read_headers(struct tcp_req *r)
89
+{
90
+	int bytes;
91
+	char *p;
92
+	
93
+	bytes=tcp_read(r);
94
+	if (bytes<=0) return bytes;
95
+	p=r->parsed;
96
+	
97
+	while(p<r->pos && r->state!=H_BODY){
98
+		switch(r->state){
99
+			case H_PARSING:
100
+				/* find lf */
101
+				p=q_memchr(p, '\n', r->pos-r->parsed);
102
+				if (p){
103
+					p++;
104
+					r->state=H_LF;
105
+				}else{
106
+					p=r->pos;
107
+				}
108
+				break;
109
+				
110
+			case H_LF:
111
+				/* terminate on LF CR LF or LF LF */
112
+				if (*p=='\r'){
113
+					r->state=H_LFCR;
114
+				}else if (*p=='\n'){
115
+					/* found LF LF */
116
+					r->state=H_BODY;
117
+					r->body=p+1;
118
+				}else r->state=H_PARSING;
119
+				p++;
120
+				break;
121
+			
122
+			case H_LFCR:
123
+				if (*p=='\n'){
124
+					/* found LF CR LF */
125
+					r->state=H_BODY;
126
+					r->body=p+1;
127
+				}else r->state=H_PARSING;
128
+				p++;
129
+				break;
130
+				
131
+			default:
132
+				fprintf(stderr, "BUG: unexpected state %d\n", r->state);
133
+				abort();
134
+		}
135
+	}
136
+	
137
+	r->parsed=p;
138
+	return bytes;
139
+}
140
+
141
+
142
+
143
+
144
+void tcp_receive_loop(int unix_sock)
145
+{
146
+	struct tcp_req req;
147
+	int bytes;
148
+	long size;
149
+	int n;
150
+	long id;
151
+	int s;
152
+	long state;
153
+	long response[2];
154
+	
155
+	
156
+	
157
+	
158
+	/* listen on the unix socket for the fd */
159
+	for(;;){
160
+			n=receive_fd(unix_sock, &id, sizeof(id), &s);
161
+			if (n<0){
162
+				if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR){
163
+					continue;
164
+				}else{
165
+					fprintf(stderr, "ERROR: tcp_receive_loop: read_fd: %s\n",
166
+							strerror(errno));
167
+					abort(); /* big error*/
168
+				}
169
+			}
170
+			if (n==0){
171
+					fprintf(stderr, 
172
+							"WARNING: tcp_receive_loop: 0 bytes read\n");
173
+					continue;
174
+			}
175
+			fprintf(stderr, "received n=%d id=%ld, fd=%d\n", n, id, s);
176
+			if (s==-1) {
177
+					fprintf(stderr, "ERROR: tcp_receive_loop: read_fd:"
178
+									"no fd read\n");
179
+					state=-1;
180
+					goto end_req; /* ?*/
181
+			}
182
+		
183
+		init_tcp_req(&req, s);
184
+		
185
+		
186
+	again:
187
+		while(req.body==0){
188
+			bytes=tcp_read_headers(&req);
189
+			/* if timeout state=0; goto end__req; */
190
+			fprintf(stderr, "read= %d bytes, parsed=%d, state=%d, error=%d\n",
191
+					bytes, req.parsed-req.buf, req.state, req.error );
192
+			if (bytes==-1){
193
+				fprintf(stderr, "ERROR!\n");
194
+				state=-1;
195
+				goto end_req;
196
+			}
197
+			if (bytes==0){
198
+				fprintf(stderr, "EOF!\n");
199
+				state=-1;
200
+				goto end_req;
201
+			}
202
+
203
+		}
204
+		fprintf(stderr, "end of header part\n");
205
+		fprintf(stderr, "headers:\n%.*s.\n",req.body-req.buf, req.buf);
206
+
207
+		/* just debugging*/
208
+		state=0;
209
+		goto end_req;
210
+		/* parse headers ... */
211
+		
212
+		/* get body */
213
+		
214
+		/* copy request */
215
+
216
+		/* prepare for next request */
217
+		size=req.pos-req.body;
218
+		if (size) memmove(req.buf, req.body, size);
219
+		fprintf(stderr, "\npreparing for new request, kept %ld bytes\n", size);
220
+		req.pos=req.buf+size;
221
+		req.parsed=req.buf;
222
+		req.body=0;
223
+		req.error=TCP_REQ_OK;
224
+		req.state=H_PARSING;
225
+	
226
+		/* process last req. */
227
+		
228
+		goto again;
229
+		
230
+	end_req:
231
+			fprintf(stderr, "end req\n");
232
+		/* release req & signal the parent */
233
+		if (s!=-1) close(s);
234
+		/* errno==EINTR, EWOULDBLOCK a.s.o todo */
235
+		response[0]=id;
236
+		response[1]=state;
237
+		write(unix_sock, response, sizeof(response));
238
+		
239
+	
240
+	}
241
+}
242
+
243
+
244
+#if 0
245
+int main(int argv, char** argc )
246
+{
247
+	printf("starting tests\n");
248
+	tcp_receive_loop();
249
+}
250
+
251
+#endif
252
+
253
+#endif