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 252
 };
253 253
 
254 254
 
255
+static const char* core_tcpinfo_doc[] = {
256
+	"Returns tcp related info.",    /* Documentation string */
257
+	0                               /* Method signature(s) */
258
+};
259
+
260
+static void core_tcpinfo(rpc_t* rpc, void* c)
261
+{
262
+	void *handle;
263
+#ifdef USE_TCP
264
+	struct tcp_gen_info ti;
265
+	
266
+	if (!tcp_disable){
267
+		tcp_get_info(&ti);
268
+		rpc->add(c, "{", &handle);
269
+		rpc->struct_add(handle, "ddddd",
270
+			"readers", ti.tcp_readers,
271
+			"max_connections", ti.tcp_max_connections,
272
+			"opened_connections", ti.tcp_connections_no,
273
+			"inactive_connections", ti.tcp_inactive_connections,
274
+			"total_requests", ti.tcp_total_requests
275
+		);
276
+	}else{
277
+		rpc->fault(c, 500, "tcp support disabled");
278
+	}
279
+#else
280
+	rpc->fault(c, 500, "tcp support not compiled");
281
+#endif
282
+}
283
+
255 284
 /*
256 285
  * RPC Methods exported by this module
257 286
  */
... ...
@@ -267,6 +297,7 @@ rpc_export_t core_rpc_methods[] = {
267 267
 	{"core.arg",               core_arg,               core_arg_doc,               RET_ARRAY},
268 268
 	{"core.kill",              core_kill,              core_kill_doc,              0        },
269 269
 	{"core.shmmem",            core_shmmem,            core_shmmem_doc,            0	},
270
+	{"core.tcp_info",          core_tcpinfo,           core_tcpinfo_doc,          0	},
270 271
 	{0, 0, 0, 0}
271 272
 };
272 273
 
273 274
new file mode 100644
... ...
@@ -0,0 +1,48 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2006 iptelorg GmbH
4
+ *
5
+ * This file is part of ser, a free SIP server.
6
+ *
7
+ * ser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * For a license to use the ser software under conditions
13
+ * other than those described here, or to purchase support for this
14
+ * software, please contact iptel.org by e-mail at the following addresses:
15
+ *    info@iptel.org
16
+ *
17
+ * ser is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program; if not, write to the Free Software
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
+ */
26
+/*
27
+ * tcp various information
28
+ */
29
+
30
+#ifndef _tcp_info_h
31
+#define _tcp_info_h
32
+
33
+struct tcp_gen_info{
34
+	int tcp_readers;
35
+	int tcp_max_connections;
36
+	int tcp_connections_no; /* crt. number */
37
+	int tcp_inactive_connections;
38
+	unsigned int tcp_total_requests;
39
+};
40
+
41
+
42
+
43
+
44
+void tcp_get_info(struct tcp_gen_info* ti);
45
+
46
+
47
+#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 116
 #ifdef USE_TLS
117 117
 #include "tls/tls_server.h"
118 118
 #endif 
119
+#include "tcp_info.h"
119 120
 
120 121
 #define local_malloc pkg_malloc
121 122
 #define local_free   pkg_free
... ...
@@ -163,7 +166,7 @@ enum poll_types tcp_poll_method=0; /* by default choose the best method */
163 163
 int tcp_max_connections=DEFAULT_TCP_MAX_CONNECTIONS;
164 164
 int tcp_max_fd_no=0;
165 165
 
166
-static int tcp_connections_no=0; /* current open connections */
166
+static int* tcp_connections_no=0; /* current open connections */
167 167
 
168 168
 /* connection hash table (after ip&port) , includes also aliases */
169 169
 struct tcp_conn_alias** tcpconn_aliases_hash=0;
... ...
@@ -447,7 +450,6 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
447 447
 	}
448 448
 	c->flags|=F_CONN_REMOVED;
449 449
 	
450
-	tcp_connections_no++;
451 450
 	return c;
452 451
 	
453 452
 error:
... ...
@@ -466,6 +468,14 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type)
466 466
 	struct tcp_connection* con;
467 467
 	struct ip_addr ip;
468 468
 
469
+	s=-1;
470
+	
471
+	if (*tcp_connections_no >= tcp_max_connections){
472
+		LOG(L_ERR, "ERROR: tcpconn_connect: maximum number of connections"
473
+					" exceeded (%d/%d)\n",
474
+					*tcp_connections_no, tcp_max_connections);
475
+		goto error;
476
+	}
469 477
 	s=socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
470 478
 	if (s==-1){
471 479
 		LOG(L_ERR, "ERROR: tcpconn_connect: socket: (%d) %s\n",
... ...
@@ -970,7 +980,7 @@ static void tcpconn_destroy(struct tcp_connection* tcpconn)
970 970
 #endif
971 971
 		_tcpconn_rm(tcpconn);
972 972
 		close(fd);
973
-		tcp_connections_no--;
973
+		(*tcp_connections_no)--;
974 974
 	}else{
975 975
 		/* force timeout */
976 976
 		tcpconn->timeout=0;
... ...
@@ -1060,11 +1070,11 @@ inline static int send_fd_queue_add(	struct tcp_send_fd_q* q,
1060 1060
 		}else new_size=MAX_SEND_FD_QUEUE_SIZE;
1061 1061
 		if (q->crt>=&q->data[new_size]){
1062 1062
 			LOG(L_ERR, "ERROR: send_fd_queue_add: queue full: %ld/%ld\n",
1063
-					q->crt-&q->data[0]-1, new_size);
1063
+					(long)(q->crt-&q->data[0]-1), new_size);
1064 1064
 			goto error;
1065 1065
 		}
1066 1066
 		LOG(L_CRIT, "INFO: send_fd_queue: queue full: %ld, extending to %ld\n",
1067
-				q->end-&q->data[0], new_size);
1067
+				(long)(q->end-&q->data[0]), new_size);
1068 1068
 		tmp=pkg_realloc(q->data, new_size*sizeof(struct send_fd_info));
1069 1069
 		if (tmp==0){
1070 1070
 			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 1104
 				LOG(L_ERR, "ERROR: run_send_fd_queue: send_fd failed"
1105 1105
 						   " on socket %d , queue entry %ld, retries %d,"
1106 1106
 						   " connection %p, tcp socket %d, errno=%d (%s) \n",
1107
-						   p->unix_sock, p-&q->data[0], p->retries,
1107
+						   p->unix_sock, (long)(p-&q->data[0]), p->retries,
1108 1108
 						   p->tcp_conn, p->tcp_conn->s, errno,
1109 1109
 						   strerror(errno));
1110 1110
 				tcpconn_destroy(p->tcp_conn);
... ...
@@ -1333,6 +1343,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
1333 1333
 							" no fd received\n");
1334 1334
 				break;
1335 1335
 			}
1336
+			(*tcp_connections_no)++;
1336 1337
 			tcpconn->s=fd;
1337 1338
 			/* add tcpconn to the list*/
1338 1339
 			tcpconn_add(tcpconn);
... ...
@@ -1453,12 +1464,13 @@ static inline int handle_new_connect(struct socket_info* si)
1453 1453
 				" connection(%d): %s\n", errno, strerror(errno));
1454 1454
 		return -1;
1455 1455
 	}
1456
-	if (tcp_connections_no>=tcp_max_connections){
1456
+	if (*tcp_connections_no>=tcp_max_connections){
1457 1457
 		LOG(L_ERR, "ERROR: maximum number of connections exceeded: %d/%d\n",
1458
-					tcp_connections_no, tcp_max_connections);
1458
+					*tcp_connections_no, tcp_max_connections);
1459 1459
 		close(new_sock);
1460 1460
 		return 1; /* success, because the accept was succesfull */
1461 1461
 	}
1462
+	(*tcp_connections_no)++;
1462 1463
 	if (init_sock_opt(new_sock)<0){
1463 1464
 		LOG(L_ERR, "ERROR: handle_new_connect: init_sock_opt failed\n");
1464 1465
 		close(new_sock);
... ...
@@ -1633,7 +1645,7 @@ static inline void tcpconn_timeout(int force)
1633 1633
 					}
1634 1634
 					close(fd);
1635 1635
 				}
1636
-				tcp_connections_no--;
1636
+				(*tcp_connections_no)--;
1637 1637
 			}
1638 1638
 			c=next;
1639 1639
 		}
... ...
@@ -1803,6 +1815,10 @@ void destroy_tcp()
1803 1803
 			shm_free(tcpconn_id_hash);
1804 1804
 			tcpconn_id_hash=0;
1805 1805
 		}
1806
+		if (tcp_connections_no){
1807
+			shm_free(tcp_connections_no);
1808
+			tcp_connections_no=0;
1809
+		}
1806 1810
 		if (connection_id){
1807 1811
 			shm_free(connection_id);
1808 1812
 			connection_id=0;
... ...
@@ -1841,7 +1857,13 @@ int init_tcp()
1841 1841
 		goto error;
1842 1842
 	}
1843 1843
 	/* init globals */
1844
-	connection_id=(int*)shm_malloc(sizeof(int));
1844
+	tcp_connections_no=shm_malloc(sizeof(int));
1845
+	if (tcp_connections_no==0){
1846
+		LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
1847
+		goto error;
1848
+	}
1849
+	*tcp_connections_no=0;
1850
+	connection_id=shm_malloc(sizeof(int));
1845 1851
 	if (connection_id==0){
1846 1852
 		LOG(L_CRIT, "ERROR: init_tcp: could not alloc globals\n");
1847 1853
 		goto error;
... ...
@@ -1938,7 +1960,10 @@ int tcp_init_children()
1938 1938
 #endif
1939 1939
 	
1940 1940
 	tcp_max_fd_no=process_count*2 +r-1 /* timer */ +3; /* stdin/out/err*/
1941
-	tcp_max_fd_no+=tcp_max_connections;
1941
+	/* max connections can be temporarily exceeded with process_count
1942
+	 * - tcp_main (tcpconn_connect called simultaneously in all all the 
1943
+	 *  processes) */
1944
+	tcp_max_fd_no+=tcp_max_connections+process_count-1 /* tcp main */;
1942 1945
 	
1943 1946
 	/* alloc the children array */
1944 1947
 	tcp_children=pkg_malloc(sizeof(struct tcp_child)*tcp_children_no);
... ...
@@ -2012,4 +2037,27 @@ error:
2012 2012
 	return -1;
2013 2013
 }
2014 2014
 
2015
+
2016
+
2017
+void tcp_get_info(struct tcp_gen_info *ti)
2018
+{
2019
+	int r;
2020
+	int active_connections;
2021
+	unsigned int total_reqs;
2022
+	
2023
+	
2024
+	ti->tcp_readers=tcp_children_no;
2025
+	ti->tcp_max_connections=tcp_max_connections;
2026
+	ti->tcp_connections_no=*tcp_connections_no;
2027
+	
2028
+	active_connections=0;
2029
+	total_reqs=0;
2030
+	for (r=0; r<tcp_children_no; r++){
2031
+		active_connections*=tcp_children[r].busy;
2032
+		total_reqs+=tcp_children[r].n_reqs;
2033
+	}
2034
+	ti->tcp_inactive_connections=*tcp_connections_no-active_connections;
2035
+	ti->tcp_total_requests=total_reqs;
2036
+}
2037
+
2015 2038
 #endif