Browse code

- fixed some tcp connections accounting bugs - tcp info available via fifo/rpc

Andrei Pelinescu-Onciul authored on 06/02/2006 16:47:31
Showing 3 changed files
... ...
@@ -36,6 +36,7 @@
36 36
 #include "globals.h"
37 37
 #include "pt.h"
38 38
 #include "ut.h"
39
+#include "tcp_info.h"
39 40
 #include "core_cmd.h"
40 41
 
41 42
 
... ...
@@ -252,6 +253,35 @@ static const char* core_shmmem_doc[] = {
252 253
 };
253 254
 
254 255
 
256
+static const char* core_tcpinfo_doc[] = {
257
+	"Returns tcp related info.",    /* Documentation string */
258
+	0                               /* Method signature(s) */
259
+};
260
+
261
+static void core_tcpinfo(rpc_t* rpc, void* c)
262
+{
263
+	void *handle;
264
+#ifdef USE_TCP
265
+	struct tcp_gen_info ti;
266
+	
267
+	if (!tcp_disable){
268
+		tcp_get_info(&ti);
269
+		rpc->add(c, "{", &handle);
270
+		rpc->struct_add(handle, "ddddd",
271
+			"readers", ti.tcp_readers,
272
+			"max_connections", ti.tcp_max_connections,
273
+			"opened_connections", ti.tcp_connections_no,
274
+			"inactive_connections", ti.tcp_inactive_connections,
275
+			"total_requests", ti.tcp_total_requests
276
+		);
277
+	}else{
278
+		rpc->fault(c, 500, "tcp support disabled");
279
+	}
280
+#else
281
+	rpc->fault(c, 500, "tcp support not compiled");
282
+#endif
283
+}
284
+
255 285
 /*
256 286
  * RPC Methods exported by this module
257 287
  */
... ...
@@ -267,6 +297,7 @@ rpc_export_t core_rpc_methods[] = {
267 297
 	{"core.arg",               core_arg,               core_arg_doc,               RET_ARRAY},
268 298
 	{"core.kill",              core_kill,              core_kill_doc,              0        },
269 299
 	{"core.shmmem",            core_shmmem,            core_shmmem_doc,            0	},
300
+	{"core.tcp_info",          core_tcpinfo,           core_tcpinfo_doc,          0	},
270 301
 	{0, 0, 0, 0}
271 302
 };
272 303
 
273 304
new file mode 100644
... ...
@@ -0,0 +1,48 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2006 iptelorg GmbH
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
+ * tcp various information
29
+ */
30
+
31
+#ifndef _tcp_info_h
32
+#define _tcp_info_h
33
+
34
+struct tcp_gen_info{
35
+	int tcp_readers;
36
+	int tcp_max_connections;
37
+	int tcp_connections_no; /* crt. number */
38
+	int tcp_inactive_connections;
39
+	unsigned int tcp_total_requests;
40
+};
41
+
42
+
43
+
44
+
45
+void tcp_get_info(struct tcp_gen_info* ti);
46
+
47
+
48
+#endif
... ...
@@ -66,6 +66,8 @@
66 66
  *  2006-02-03  timers are run only once per s (andrei)
67 67
  *              tcp children fds can be non-blocking; send fds are queued on
68 68
  *              EAGAIN; lots of bug fixes (andrei)
69
+ *  2006-02-06  better tcp_max_connections checks, tcp_connections_no moved to
70
+ *              shm (andrei)
69 71
  */
70 72
 
71 73
 
... ...
@@ -116,6 +118,7 @@
116 118
 #ifdef USE_TLS
117 119
 #include "tls/tls_server.h"
118 120
 #endif 
121
+#include "tcp_info.h"
119 122
 
120 123
 #define local_malloc pkg_malloc
121 124
 #define local_free   pkg_free
... ...
@@ -163,7 +166,7 @@ enum poll_types tcp_poll_method=0; /* by default choose the best method */
163 166
 int tcp_max_connections=DEFAULT_TCP_MAX_CONNECTIONS;
164 167
 int tcp_max_fd_no=0;
165 168
 
166
-static int tcp_connections_no=0; /* current open connections */
169
+static int* tcp_connections_no=0; /* current open connections */
167 170
 
168 171
 /* connection hash table (after ip&port) , includes also aliases */
169 172
 struct tcp_conn_alias** tcpconn_aliases_hash=0;
... ...
@@ -447,7 +450,6 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
447 450
 	}
448 451
 	c->flags|=F_CONN_REMOVED;
449 452
 	
450
-	tcp_connections_no++;
451 453
 	return c;
452 454
 	
453 455
 error:
... ...
@@ -466,6 +468,14 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
466 468
 	struct tcp_connection* con;
467 469
 	struct ip_addr ip;
468 470
 
471
+	s=-1;
472
+	
473
+	if (*tcp_connections_no >= tcp_max_connections){
474
+		LOG(L_ERR, "ERROR: tcpconn_connect: maximum number of connections"
475
+					" exceeded (%d/%d)\n",
476
+					*tcp_connections_no, tcp_max_connections);
477
+		goto error;
478
+	}
469 479
 	s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
470 480
 	if (s==-1){
471 481
 		LOG(L_ERR, "ERROR: tcpconn_connect: socket: (%d) %s\n",
... ...
@@ -970,7 +980,7 @@ static void tcpconn_destroy(struct tcp_connection* tcpconn)
970 980
 #endif
971 981
 		_tcpconn_rm(tcpconn);
972 982
 		close(fd);
973
-		tcp_connections_no--;
983
+		(*tcp_connections_no)--;
974 984
 	}else{
975 985
 		/* force timeout */
976 986
 		tcpconn->timeout=0;
... ...
@@ -1060,11 +1070,11 @@ inline static int send_fd_queue_add(	struct tcp_send_fd_q* q,
1060 1070
 		}else new_size=MAX_SEND_FD_QUEUE_SIZE;
1061 1071
 		if (q->crt>=&q->data[new_size]){
1062 1072
 			LOG(L_ERR, "ERROR: send_fd_queue_add: queue full: %ld/%ld\n",
1063
-					q->crt-&q->data[0]-1, new_size);
1073
+					(long)(q->crt-&q->data[0]-1), new_size);
1064 1074
 			goto error;
1065 1075
 		}
1066 1076
 		LOG(L_CRIT, "INFO: send_fd_queue: queue full: %ld, extending to %ld\n",
1067
-				q->end-&q->data[0], new_size);
1077
+				(long)(q->end-&q->data[0]), new_size);
1068 1078
 		tmp=pkg_realloc(q->data, new_size*sizeof(struct send_fd_info));
1069 1079
 		if (tmp==0){
1070 1080
 			LOG(L_ERR, "ERROR: send_fd_queue_add: out of memory\n");
... ...
@@ -1104,7 +1114,7 @@ inline static void send_fd_queue_run(struct tcp_send_fd_q* q)
1104 1114
 				LOG(L_ERR, "ERROR: run_send_fd_queue: send_fd failed"
1105 1115
 						   " on socket %d , queue entry %ld, retries %d,"
1106 1116
 						   " connection %p, tcp socket %d, errno=%d (%s) \n",
1107
-						   p->unix_sock, p-&q->data[0], p->retries,
1117
+						   p->unix_sock, (long)(p-&q->data[0]), p->retries,
1108 1118
 						   p->tcp_conn, p->tcp_conn->s, errno,
1109 1119
 						   strerror(errno));
1110 1120
 				tcpconn_destroy(p->tcp_conn);
... ...
@@ -1333,6 +1343,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
1333 1343
 							" no fd received\n");
1334 1344
 				break;
1335 1345
 			}
1346
+			(*tcp_connections_no)++;
1336 1347
 			tcpconn->s=fd;
1337 1348
 			/* add tcpconn to the list*/
1338 1349
 			tcpconn_add(tcpconn);
... ...
@@ -1453,12 +1464,13 @@ static inline int handle_new_connect(struct socket_info* si)
1453 1464
 				" connection(%d): %s\n", errno, strerror(errno));
1454 1465
 		return -1;
1455 1466
 	}
1456
-	if (tcp_connections_no>=tcp_max_connections){
1467
+	if (*tcp_connections_no>=tcp_max_connections){
1457 1468
 		LOG(L_ERR, "ERROR: maximum number of connections exceeded: %d/%d\n",
1458
-					tcp_connections_no, tcp_max_connections);
1469
+					*tcp_connections_no, tcp_max_connections);
1459 1470
 		close(new_sock);
1460 1471
 		return 1; /* success, because the accept was succesfull */
1461 1472
 	}
1473
+	(*tcp_connections_no)++;
1462 1474
 	if (init_sock_opt(new_sock)<0){
1463 1475
 		LOG(L_ERR, "ERROR: handle_new_connect: init_sock_opt failed\n");
1464 1476
 		close(new_sock);
... ...
@@ -1633,7 +1645,7 @@ static inline void tcpconn_timeout(int force)
1633 1645
 					}
1634 1646
 					close(fd);
1635 1647
 				}
1636
-				tcp_connections_no--;
1648
+				(*tcp_connections_no)--;
1637 1649
 			}
1638 1650
 			c=next;
1639 1651
 		}
... ...
@@ -1803,6 +1815,10 @@ void destroy_tcp()
1803 1815
 			shm_free(tcpconn_id_hash);
1804 1816
 			tcpconn_id_hash=0;
1805 1817
 		}
1818
+		if (tcp_connections_no){
1819
+			shm_free(tcp_connections_no);
1820
+			tcp_connections_no=0;
1821
+		}
1806 1822
 		if (connection_id){
1807 1823
 			shm_free(connection_id);
1808 1824
 			connection_id=0;
... ...
@@ -1841,7 +1857,13 @@ int init_tcp()
1841 1857
 		goto error;
1842 1858
 	}
1843 1859
 	/* init globals */
1844
-	connection_id=(int*)shm_malloc(sizeof(int));
1860
+	tcp_connections_no=shm_malloc(sizeof(int));
1861
+	if (tcp_connections_no==0){
1862
+		LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
1863
+		goto error;
1864
+	}
1865
+	*tcp_connections_no=0;
1866
+	connection_id=shm_malloc(sizeof(int));
1845 1867
 	if (connection_id==0){
1846 1868
 		LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
1847 1869
 		goto error;
... ...
@@ -1938,7 +1960,10 @@ int tcp_init_children()
1938 1960
 #endif
1939 1961
 	
1940 1962
 	tcp_max_fd_no=process_count*2 +r-1 /* timer */ +3; /* stdin/out/err*/
1941
-	tcp_max_fd_no+=tcp_max_connections;
1963
+	/* max connections can be temporarily exceeded with process_count
1964
+	 * - tcp_main (tcpconn_connect called simultaneously in all all the 
1965
+	 *  processes) */
1966
+	tcp_max_fd_no+=tcp_max_connections+process_count-1 /* tcp main */;
1942 1967
 	
1943 1968
 	/* alloc the children array */
1944 1969
 	tcp_children=pkg_malloc(sizeof(struct tcp_child)*tcp_children_no);
... ...
@@ -2012,4 +2037,27 @@ error:
2012 2037
 	return -1;
2013 2038
 }
2014 2039
 
2040
+
2041
+
2042
+void tcp_get_info(struct tcp_gen_info *ti)
2043
+{
2044
+	int r;
2045
+	int active_connections;
2046
+	unsigned int total_reqs;
2047
+	
2048
+	
2049
+	ti->tcp_readers=tcp_children_no;
2050
+	ti->tcp_max_connections=tcp_max_connections;
2051
+	ti->tcp_connections_no=*tcp_connections_no;
2052
+	
2053
+	active_connections=0;
2054
+	total_reqs=0;
2055
+	for (r=0; r<tcp_children_no; r++){
2056
+		active_connections*=tcp_children[r].busy;
2057
+		total_reqs+=tcp_children[r].n_reqs;
2058
+	}
2059
+	ti->tcp_inactive_connections=*tcp_connections_no-active_connections;
2060
+	ti->tcp_total_requests=total_reqs;
2061
+}
2062
+
2015 2063
 #endif