Kaynağa Gözat

tcp: use dynamic config framework, part 1

- all tcp config variables from tcp_options.h migrated to the
  dynamic configuration framework. For now all are read only, but
  write support will come soon where it makes sense.
  E.g.: (with the cfg_rpc module loaded)
  $ sercmd cfg.help tcp async
  async mode for writes and connects
  (parameter type is integer)

  $ sercmd cfg.get tcp async
  0
Andrei Pelinescu-Onciul 16 yıl önce
ebeveyn
işleme
22db42e4ef
7 değiştirilmiş dosya ile 207 ekleme ve 105 silme
  1. 13 13
      cfg.y
  2. 1 1
      core_cmd.c
  3. 25 21
      main.c
  4. 43 43
      tcp_main.c
  5. 113 21
      tcp_options.c
  6. 11 5
      tcp_options.h
  7. 1 1
      tcp_read.c

+ 13 - 13
cfg.y

@@ -865,7 +865,7 @@ assign_stm:
 	| TCP_SOURCE_IPV6 EQUAL error { yyerror("IPv6 address expected"); }
 	| TCP_OPT_FD_CACHE EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.fd_cache=$3;
+			tcp_default_cfg.fd_cache=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -873,7 +873,7 @@ assign_stm:
 	| TCP_OPT_FD_CACHE EQUAL error { yyerror("boolean value expected"); }
 	| TCP_OPT_BUF_WRITE EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.tcp_buf_write=$3;
+			tcp_default_cfg.tcp_buf_write=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -881,7 +881,7 @@ assign_stm:
 	| TCP_OPT_BUF_WRITE EQUAL error { yyerror("boolean value expected"); }
 	| TCP_OPT_CONN_WQ_MAX EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.tcpconn_wq_max=$3;
+			tcp_default_cfg.tcpconn_wq_max=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -889,7 +889,7 @@ assign_stm:
 	| TCP_OPT_CONN_WQ_MAX error { yyerror("boolean value expected"); }
 	| TCP_OPT_WQ_MAX EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.tcp_wq_max=$3;
+			tcp_default_cfg.tcp_wq_max=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -897,7 +897,7 @@ assign_stm:
 	| TCP_OPT_WQ_MAX error { yyerror("boolean value expected"); }
 	| TCP_OPT_DEFER_ACCEPT EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.defer_accept=$3;
+			tcp_default_cfg.defer_accept=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -905,7 +905,7 @@ assign_stm:
 	| TCP_OPT_DEFER_ACCEPT EQUAL error { yyerror("boolean value expected"); }
 	| TCP_OPT_DELAYED_ACK EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.delayed_ack=$3;
+			tcp_default_cfg.delayed_ack=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -913,7 +913,7 @@ assign_stm:
 	| TCP_OPT_DELAYED_ACK EQUAL error { yyerror("boolean value expected"); }
 	| TCP_OPT_SYNCNT EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.syncnt=$3;
+			tcp_default_cfg.syncnt=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -921,7 +921,7 @@ assign_stm:
 	| TCP_OPT_SYNCNT EQUAL error { yyerror("number expected"); }
 	| TCP_OPT_LINGER2 EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.linger2=$3;
+			tcp_default_cfg.linger2=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -929,7 +929,7 @@ assign_stm:
 	| TCP_OPT_LINGER2 EQUAL error { yyerror("number expected"); }
 	| TCP_OPT_KEEPALIVE EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.keepalive=$3;
+			tcp_default_cfg.keepalive=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -937,7 +937,7 @@ assign_stm:
 	| TCP_OPT_KEEPALIVE EQUAL error { yyerror("boolean value expected");}
 	| TCP_OPT_KEEPIDLE EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.keepidle=$3;
+			tcp_default_cfg.keepidle=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -945,7 +945,7 @@ assign_stm:
 	| TCP_OPT_KEEPIDLE EQUAL error { yyerror("number expected"); }
 	| TCP_OPT_KEEPINTVL EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.keepintvl=$3;
+			tcp_default_cfg.keepintvl=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -953,7 +953,7 @@ assign_stm:
 	| TCP_OPT_KEEPINTVL EQUAL error { yyerror("number expected"); }
 	| TCP_OPT_KEEPCNT EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.keepcnt=$3;
+			tcp_default_cfg.keepcnt=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif
@@ -961,7 +961,7 @@ assign_stm:
 	| TCP_OPT_KEEPCNT EQUAL error { yyerror("number expected"); }
 	| TCP_OPT_CRLF_PING EQUAL NUMBER {
 		#ifdef USE_TCP
-			tcp_options.crlf_ping=$3;
+			tcp_default_cfg.crlf_ping=$3;
 		#else
 			warn("tcp support not compiled in");
 		#endif

+ 1 - 1
core_cmd.c

@@ -560,7 +560,7 @@ static void core_tcp_options(rpc_t* rpc, void* c)
 {
 #ifdef USE_TCP
 	void *handle;
-	struct tcp_cfg_options t;
+	struct cfg_group_tcp t;
 
 	if (!tcp_disable){
 		tcp_options_get(&t);

+ 25 - 21
main.c

@@ -1612,6 +1612,10 @@ int main(int argc, char** argv)
 		}
 	}
 
+	if (endianness_sanity_check() != 0){
+		fprintf(stderr, "BUG: endianness sanity tests failed\n");
+		goto error;
+	}
 	if (init_routes()<0) goto error;
 	if (init_nonsip_hooks()<0) goto error;
 
@@ -1916,6 +1920,27 @@ try_again:
 		goto error;
 	if (init_atomic_ops()==-1)
 		goto error;
+	if (init_basex() != 0){
+		LOG(L_CRIT, "could not initialize base* framework\n");
+		goto error;
+	}
+	if (cfg_init() < 0) {
+		LOG(L_CRIT, "could not initialize configuration framework\n");
+		goto error;
+	}
+	/* declare the core cfg before the module configs */
+	if (cfg_declare("core", core_cfg_def, &default_core_cfg, cfg_sizeof(core),
+			&core_cfg)
+	) {
+		LOG(L_CRIT, "could not declare the core configuration\n");
+		goto error;
+	}
+#ifdef USE_TCP
+	if (tcp_register_cfg()){
+		LOG(L_CRIT, "could not register the tcp configuration\n");
+		goto error;
+	}
+#endif /* USE_TCP */
 	/*init timer, before parsing the cfg!*/
 	if (init_timer()<0){
 		LOG(L_CRIT, "could not initialize timer, exiting...\n");
@@ -1991,27 +2016,6 @@ try_again:
 			set_rt_prio(rt_prio, rt_policy);
 
 	
-	if (cfg_init() < 0) {
-		LOG(L_CRIT, "could not initialize configuration framework\n");
-		goto error;
-	}
-	/* declare the core cfg before the module configs */
-	if (cfg_declare("core", core_cfg_def, &default_core_cfg, cfg_sizeof(core),
-			&core_cfg)
-	) {
-		LOG(L_CRIT, "could not declare the core configuration\n");
-		goto error;
-	}
-
-	if (endianness_sanity_check() != 0){
-		LOG(L_CRIT, "BUG: endianness sanity tests failed\n");
-		goto error;
-	}
-	if (init_basex() != 0){
-		LOG(L_CRIT, "could not initialize base* framework\n");
-		goto error;
-	}
-	
 	if (init_modules() != 0) {
 		fprintf(stderr, "ERROR: error while initializing modules\n");
 		goto error;

+ 43 - 43
tcp_main.c

@@ -315,7 +315,7 @@ static inline int init_sock_keepalive(int s)
 	int optval;
 	
 #ifdef HAVE_SO_KEEPALIVE
-	if (tcp_options.keepalive){
+	if (cfg_get(tcp, tcp_cfg, keepalive)){
 		optval=1;
 		if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval,
 						sizeof(optval))<0){
@@ -326,8 +326,7 @@ static inline int init_sock_keepalive(int s)
 	}
 #endif
 #ifdef HAVE_TCP_KEEPINTVL
-	if (tcp_options.keepintvl){
-		optval=tcp_options.keepintvl;
+	if ((optval=cfg_get(tcp, tcp_cfg, keepintvl))){
 		if (setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, &optval,
 						sizeof(optval))<0){
 			LOG(L_WARN, "WARNING: init_sock_keepalive: failed to set"
@@ -336,8 +335,7 @@ static inline int init_sock_keepalive(int s)
 	}
 #endif
 #ifdef HAVE_TCP_KEEPIDLE
-	if (tcp_options.keepidle){
-		optval=tcp_options.keepidle;
+	if ((optval=cfg_get(tcp, tcp_cfg, keepidle))){
 		if (setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, &optval,
 						sizeof(optval))<0){
 			LOG(L_WARN, "WARNING: init_sock_keepalive: failed to set"
@@ -346,8 +344,7 @@ static inline int init_sock_keepalive(int s)
 	}
 #endif
 #ifdef HAVE_TCP_KEEPCNT
-	if (tcp_options.keepcnt){
-		optval=tcp_options.keepcnt;
+	if ((optval=cfg_get(tcp, tcp_cfg, keepcnt))){
 		if (setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, &optval,
 						sizeof(optval))<0){
 			LOG(L_WARN, "WARNING: init_sock_keepalive: failed to set"
@@ -394,8 +391,7 @@ static int init_sock_opt(int s)
 	}
 #endif /* !TCP_DONT_REUSEADDR */
 #ifdef HAVE_TCP_SYNCNT
-	if (tcp_options.syncnt){
-		optval=tcp_options.syncnt;
+	if ((optval=cfg_get(tcp, tcp_cfg, syncnt))){
 		if (setsockopt(s, IPPROTO_TCP, TCP_SYNCNT, &optval,
 						sizeof(optval))<0){
 			LOG(L_WARN, "WARNING: init_sock_opt: failed to set"
@@ -404,8 +400,7 @@ static int init_sock_opt(int s)
 	}
 #endif
 #ifdef HAVE_TCP_LINGER2
-	if (tcp_options.linger2){
-		optval=tcp_options.linger2;
+	if ((optval=cfg_get(tcp, tcp_cfg, linger2))){
 		if (setsockopt(s, IPPROTO_TCP, TCP_LINGER2, &optval,
 						sizeof(optval))<0){
 			LOG(L_WARN, "WARNING: init_sock_opt: failed to set"
@@ -414,7 +409,7 @@ static int init_sock_opt(int s)
 	}
 #endif
 #ifdef HAVE_TCP_QUICKACK
-	if (tcp_options.delayed_ack){
+	if (cfg_get(tcp, tcp_cfg, delayed_ack)){
 		optval=0; /* reset quick ack => delayed ack */
 		if (setsockopt(s, IPPROTO_TCP, TCP_QUICKACK, &optval,
 						sizeof(optval))<0){
@@ -634,14 +629,15 @@ inline static int _wbufq_add(struct  tcp_connection* c, char* data,
 	
 	q=&c->wbuf_q;
 	t=get_ticks_raw();
-	if (unlikely(	((q->queued+size)>tcp_options.tcpconn_wq_max) ||
-					((*tcp_total_wq+size)>tcp_options.tcp_wq_max) ||
+	if (unlikely(	((q->queued+size)>cfg_get(tcp, tcp_cfg, tcpconn_wq_max)) ||
+					((*tcp_total_wq+size)>cfg_get(tcp, tcp_cfg, tcp_wq_max)) ||
 					(q->first &&
 					TICKS_LT(q->wr_timeout, t)) )){
 		LOG(L_ERR, "ERROR: wbufq_add(%d bytes): write queue full or timeout "
 					" (%d, total %d, last write %d s ago)\n",
 					size, q->queued, *tcp_total_wq,
-					TICKS_TO_S(t-q->wr_timeout-tcp_options.tcp_wq_timeout));
+					TICKS_TO_S(t-q->wr_timeout-
+						cfg_get(tcp, tcp_cfg, tcp_wq_timeout)));
 #ifdef USE_DST_BLACKLIST
 		if (q->first && TICKS_LT(q->wr_timeout, t) &&
 				cfg_get(core, core_cfg, use_dst_blacklist)){
@@ -665,7 +661,7 @@ inline static int _wbufq_add(struct  tcp_connection* c, char* data,
 		q->first=wb;
 		q->last_used=0;
 		q->offset=0;
-		q->wr_timeout=get_ticks_raw()+tcp_options.tcp_wq_timeout;
+		q->wr_timeout=get_ticks_raw()+cfg_get(tcp, tcp_cfg, tcp_wq_timeout);
 	}else{
 		wb=q->last;
 	}
@@ -713,12 +709,12 @@ inline static int _wbufq_insert(struct  tcp_connection* c, char* data,
 	if (likely(q->first==0)) /* if empty, use wbufq_add */
 		return _wbufq_add(c, data, size);
 	
-	if (unlikely((*tcp_total_wq+size)>tcp_options.tcp_wq_max)){
+	if (unlikely((*tcp_total_wq+size)>cfg_get(tcp, tcp_cfg, tcp_wq_max))){
 		LOG(L_ERR, "ERROR: wbufq_insert(%d bytes): write queue full"
 					" (%d, total %d, last write %d s ago)\n",
 					size, q->queued, *tcp_total_wq,
 					TICKS_TO_S(get_ticks_raw()-q->wr_timeout-
-										tcp_options.tcp_wq_timeout));
+									cfg_get(tcp, tcp_cfg, tcp_wq_timeout)));
 		goto error;
 	}
 	if (unlikely(q->offset)){
@@ -815,7 +811,7 @@ inline static int wbufq_run(int fd, struct tcp_connection* c, int* empty)
 				atomic_add_int((int*)tcp_total_wq, -n);
 				break;
 			}
-			q->wr_timeout=t+tcp_options.tcp_wq_timeout;
+			q->wr_timeout=t+cfg_get(tcp, tcp_cfg, tcp_wq_timeout);
 		}else{
 			if (n<0){
 				/* EINTR is handled inside _tcpconn_write_nb */
@@ -1031,7 +1027,7 @@ inline static int tcp_do_connect(	union sockaddr_union* server,
 	}
 	*state=S_CONN_OK;
 #ifdef TCP_BUF_WRITE
-	if (likely(tcp_options.tcp_buf_write)){
+	if (likely(cfg_get(tcp, tcp_cfg, tcp_buf_write))){
 again:
 		n=connect(s, &server->s, sockaddru_len(*server));
 		if (unlikely(n==-1)){
@@ -1633,7 +1629,7 @@ int tcp_send(struct dest_info* dst, union sockaddr_union* from,
 	struct fd_cache_entry* fd_cache_e;
 	int use_fd_cache;
 	
-	use_fd_cache=tcp_options.fd_cache;
+	use_fd_cache=cfg_get(tcp, tcp_cfg, fd_cache);
 	fd_cache_e=0;
 #endif /* TCP_FD_CACHE */
 	do_close_fd=1; /* close the fd on exit */
@@ -1682,8 +1678,8 @@ no_id:
 				}
 			}
 #if defined(TCP_CONNECT_WAIT) && defined(TCP_BUF_WRITE)
-			if (likely(tcp_options.tcp_connect_wait && 
-						tcp_options.tcp_buf_write )){
+			if (likely(cfg_get(tcp, tcp_cfg, tcp_connect_wait) && 
+						cfg_get(tcp, tcp_cfg, tcp_buf_write) )){
 				if (unlikely(*tcp_connections_no >= tcp_max_connections)){
 					LOG(L_ERR, "ERROR: tcp_send %s: maximum number of"
 								" connections exceeded (%d/%d)\n",
@@ -1828,7 +1824,8 @@ no_id:
 get_fd:
 #ifdef TCP_BUF_WRITE
 		/* if data is already queued, we don't need the fd any more */
-		if (unlikely(tcp_options.tcp_buf_write && (_wbufq_non_empty(c)
+		if (unlikely(cfg_get(tcp, tcp_cfg, tcp_buf_write) &&
+						(_wbufq_non_empty(c)
 #ifdef TCP_CONNECT_WAIT
 												|| (c->state==S_CONN_PENDING)
 #endif /* TCP_CONNECT_WAIT */
@@ -1911,7 +1908,7 @@ send_it:
 	DBG("tcp_send: sending...\n");
 	lock_get(&c->write_lock);
 #ifdef TCP_BUF_WRITE
-	if (likely(tcp_options.tcp_buf_write)){
+	if (likely(cfg_get(tcp, tcp_cfg, tcp_buf_write))){
 		if (_wbufq_non_empty(c)
 #ifdef TCP_CONNECT_WAIT
 			|| (c->state==S_CONN_PENDING) 
@@ -1946,7 +1943,7 @@ send_it:
 	DBG("tcp_send: buf=\n%.*s\n", (int)len, buf);
 	if (unlikely(n<(int)len)){
 #ifdef TCP_BUF_WRITE
-		if (tcp_options.tcp_buf_write && 
+		if (cfg_get(tcp, tcp_cfg, tcp_buf_write) && 
 				((n>=0) || errno==EAGAIN || errno==EWOULDBLOCK)){
 			enable_write_watch=_wbufq_empty(c);
 			if (n<0) n=0;
@@ -2023,7 +2020,7 @@ error:
 	
 #ifdef TCP_BUF_WRITE
 	lock_release(&c->write_lock);
-	if (likely(tcp_options.tcp_buf_write)){
+	if (likely(cfg_get(tcp, tcp_cfg, tcp_buf_write))){
 		if (unlikely(c->state==S_CONN_CONNECT))
 			c->state=S_CONN_OK;
 	}
@@ -2137,8 +2134,7 @@ int tcp_init(struct socket_info* sock_info)
 	}
 #ifdef HAVE_TCP_DEFER_ACCEPT
 	/* linux only */
-	if (tcp_options.defer_accept){
-		optval=tcp_options.defer_accept;
+	if ((optval=cfg_get(tcp, tcp_cfg, defer_accept))){
 		if (setsockopt(sock_info->socket, IPPROTO_TCP, TCP_DEFER_ACCEPT,
 					(void*)&optval, sizeof(optval)) ==-1){
 			LOG(L_WARN, "WARNING: tcp_init: setsockopt TCP_DEFER_ACCEPT %s\n",
@@ -2148,8 +2144,7 @@ int tcp_init(struct socket_info* sock_info)
 	}
 #endif /* HAVE_TCP_DEFFER_ACCEPT */
 #ifdef HAVE_TCP_SYNCNT
-	if (tcp_options.syncnt){
-		optval=tcp_options.syncnt;
+	if ((optval=cfg_get(tcp, tcp_cfg, syncnt))){
 		if (setsockopt(sock_info->socket, IPPROTO_TCP, TCP_SYNCNT, &optval,
 						sizeof(optval))<0){
 			LOG(L_WARN, "WARNING: tcp_init: failed to set"
@@ -2158,8 +2153,7 @@ int tcp_init(struct socket_info* sock_info)
 	}
 #endif
 #ifdef HAVE_TCP_LINGER2
-	if (tcp_options.linger2){
-		optval=tcp_options.linger2;
+	if ((optval=cfg_get(tcp, tcp_cfg, linger2))){
 		if (setsockopt(sock_info->socket, IPPROTO_TCP, TCP_LINGER2, &optval,
 						sizeof(optval))<0){
 			LOG(L_WARN, "WARNING: tcp_init: failed to set"
@@ -2187,7 +2181,7 @@ int tcp_init(struct socket_info* sock_info)
 	}
 #ifdef HAVE_TCP_ACCEPT_FILTER
 	/* freebsd */
-	if (tcp_options.defer_accept){
+	if (cfg_get(tcp, tcp_cfg, defer_accept)){
 		memset(&afa, 0, sizeof(afa));
 		strcpy(afa.af_name, "dataready");
 		if (setsockopt(sock_info->socket, SOL_SOCKET, SO_ACCEPTFILTER,
@@ -2224,7 +2218,7 @@ inline static void tcpconn_close_main_fd(struct tcp_connection* tcpconn)
 		tls_close(tcpconn, fd);
 #endif
 #ifdef TCP_FD_CACHE
-	if (likely(tcp_options.fd_cache)) shutdown(fd, SHUT_RDWR);
+	if (likely(cfg_get(tcp, tcp_cfg, fd_cache))) shutdown(fd, SHUT_RDWR);
 #endif /* TCP_FD_CACHE */
 close_again:
 	if (unlikely(close(fd)<0)){
@@ -2659,7 +2653,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
 			tcpconn->timeout=t+tcp_con_lifetime;
 			crt_timeout=tcp_con_lifetime;
 #ifdef TCP_BUF_WRITE
-			if (unlikely(tcp_options.tcp_buf_write && 
+			if (unlikely(cfg_get(tcp, tcp_cfg, tcp_buf_write) && 
 							_wbufq_non_empty(tcpconn) )){
 				if (unlikely(TICKS_GE(t, tcpconn->wbuf_q.wr_timeout))){
 					DBG("handle_tcp_child: wr. timeout on CONN_RELEASE for %p "
@@ -3449,6 +3443,7 @@ static ticks_t tcpconn_main_timeout(ticks_t t, struct timer_ln* tl, void* data)
 {
 	struct tcp_connection *c;
 	int fd;
+	int tcp_async;
 	
 	c=(struct tcp_connection*)data; 
 	/* or (struct tcp...*)(tl-offset(c->timer)) */
@@ -3460,17 +3455,17 @@ static ticks_t tcpconn_main_timeout(ticks_t t, struct timer_ln* tl, void* data)
 			c->wbuf_q.wr_timeout, TICKS_TO_S(c->wbuf_q.wr_timeout-t),
 			c->wbuf_q.queued);
 	
-	if (TICKS_LT(t, c->timeout) && 
-			(!tcp_options.tcp_buf_write | _wbufq_empty(c) |
-				TICKS_LT(t, c->wbuf_q.wr_timeout)) ){
-		if (unlikely(tcp_options.tcp_buf_write && _wbufq_non_empty(c)))
+	tcp_async=cfg_get(tcp, tcp_cfg, tcp_buf_write);
+	if (likely(TICKS_LT(t, c->timeout) && ( !tcp_async | _wbufq_empty(c) |
+					TICKS_LT(t, c->wbuf_q.wr_timeout)) )){
+		if (unlikely(tcp_async && _wbufq_non_empty(c)))
 			return (ticks_t)MIN_unsigned(c->timeout-t, c->wbuf_q.wr_timeout-t);
 		else
 			return (ticks_t)(c->timeout - t);
 	}
 #ifdef USE_DST_BLACKLIST
 	/* if time out due to write, add it to the blacklist */
-	if (tcp_options.tcp_buf_write && _wbufq_non_empty(c) &&
+	if (tcp_async && _wbufq_non_empty(c) &&
 			TICKS_GE(t, c->wbuf_q.wr_timeout) &&
 			cfg_get(core, core_cfg, use_dst_blacklist))
 		dst_blacklist_su((c->state==S_CONN_CONNECT)?  BLST_ERR_CONNECT:
@@ -3561,7 +3556,8 @@ static inline void tcpconn_destroy_all()
 				_tcpconn_rm(c);
 				if (fd>0) {
 #ifdef TCP_FD_CACHE
-					if (likely(tcp_options.fd_cache)) shutdown(fd, SHUT_RDWR);
+					if (likely(cfg_get(tcp, tcp_cfg, fd_cache)))
+						shutdown(fd, SHUT_RDWR);
 #endif /* TCP_FD_CACHE */
 					close(fd);
 				}
@@ -3605,7 +3601,7 @@ void tcp_main_loop()
 		goto error;
 	}
 #ifdef TCP_FD_CACHE
-	if (tcp_options.fd_cache) tcp_fd_cache_init();
+	if (cfg_get(tcp, tcp_cfg, fd_cache)) tcp_fd_cache_init();
 #endif /* TCP_FD_CACHE */
 	
 	/* add all the sockets we listen on for connections */
@@ -3791,6 +3787,10 @@ int init_tcp()
 	char* poll_err;
 	
 	tcp_options_check();
+	if (tcp_cfg==0){
+		BUG("tcp_cfg not initialized\n");
+		goto error;
+	}
 	/* init lock */
 	tcpconn_lock=lock_alloc();
 	if (tcpconn_lock==0){

+ 113 - 21
tcp_options.c

@@ -21,62 +21,137 @@
  * History:
  * --------
  *  2007-11-28  created by andrei
+ *  2009-03-05  use cfg framework (andrei)
  */
 
 #include "tcp_options.h"
 #include "dprint.h"
 #include "globals.h"
 #include "timer_ticks.h"
+#include "cfg/cfg.h"
 
 
-struct tcp_cfg_options tcp_options;
 
+/* default/initial values for tcp config options
+   NOTE: all the options are initialized in init_tcp_options()
+   depending on compile time defines */
+struct cfg_group_tcp tcp_default_cfg;
+#if 0
+{
+	1, /* fd_cache, default on */
+	/* tcp async options */
+	0, /* tcp_buf_write / tcp_async, default off */
+	1, /* tcp_connect_wait - depends on tcp_async */
+	32*1024, /* tcpconn_wq_max - max. write queue len per connection (32k) */
+	10*1024*1024, /* tcp_wq_max - max.  overall queued bytes  (10MB)*/
+	S_TO_TICKS(tcp_send_timeout), /* tcp_wq_timeout - timeout for queued 
+									 writes, depends on tcp_send_timeout */
+	/* tcp socket options */
+	0, /* defer_accept - on/off*/
+	1, /* delayed_ack - delay ack on connect (on/off)*/
+	0, /* syncnt - numbers of SYNs retrs. before giving up (0 = OS default) */
+	0, /* linger2 - lifetime of orphaned FIN_WAIT2 sockets (0 = OS default)*/
+	1, /* keepalive - on/off */
+	0, /* keepidle - idle time (s) before tcp starts sending keepalives */
+	0, /* keepintvl - interval between keep alives (0 = OS default) */
+	0, /* keepcnt - maximum no. of keepalives (0 = OS default)*/
+	
+	/* other options */
+	1 /* crlf_ping - respond to double CRLF ping/keepalive (on/off) */
+	
+};
+#endif
+
+
+
+/* cfg_group_tcp description (for the config framework)*/
+static cfg_def_t tcp_cfg_def[] = {
+	/*   name        , type |input type| chg type, min, max, fixup, proc. cbk 
+	      description */
+	{ "fd_cache",     CFG_VAR_INT | CFG_READONLY,    0,   1,     0,         0,
+		"file descriptor cache for tcp_send"},
+	/* tcp async options */
+	{ "async",        CFG_VAR_INT | CFG_READONLY,    0,   1,      0,         0,
+		"async mode for writes and connects"},
+	{ "connect_wait", CFG_VAR_INT | CFG_READONLY,    0,   1,      0,         0,
+		"parallel simultaneous connects to the same dst. (0) or one connect"},
+	{ "conn_wq_max",  CFG_VAR_INT | CFG_READONLY,    0, 1024*1024, 0,        0,
+		"maximum bytes queued for write per connection (depends on async)"},
+	{ "wq_max",       CFG_VAR_INT | CFG_READONLY,    0,  1<<30,    0,        0,
+		"maximum bytes queued for write allowed globally (depends on async)"},
+	{ "wq_timeout",   CFG_VAR_INT | CFG_READONLY,    1,  1<<30,    0,        0,
+		"timeout for queued writes (in ticks, use send_timeout for seconds)"},
+	/* tcp socket options */
+	{ "defer_accept", CFG_VAR_INT | CFG_READONLY,    0,   3600,   0,         0,
+		"0/1 on linux, seconds on freebsd (see docs)"},
+	{ "delayed_ack",  CFG_VAR_INT | CFG_READONLY,    0,      1,   0,         0,
+		"initial ack will be delayed and sent with the first data segment"},
+	{ "syncnt",       CFG_VAR_INT | CFG_READONLY,    0,      1,   0,         0,
+		"number of syn retransmissions before aborting a connect (0=not set)"},
+	{ "linger2",      CFG_VAR_INT | CFG_READONLY,    0,   3600,   0,         0,
+		"lifetime of orphaned sockets in FIN_WAIT2 state in s (0=not set)"},
+	{ "keepalive",    CFG_VAR_INT | CFG_READONLY,    0,      1,   0,         0,
+		"enables/disables keepalives for tcp"},
+	{ "keepidle",     CFG_VAR_INT | CFG_READONLY,    0, 24*3600,  0,         0,
+		"time before sending a keepalive if the connection is idle (linux)"},
+	{ "keepintvl",    CFG_VAR_INT | CFG_READONLY,    0, 24*3600,  0,         0,
+		"time interval between keepalive probes on failure (linux)"},
+	{ "keepcnt",     CFG_VAR_INT | CFG_READONLY,    0,    1<<10,  0,         0,
+		"number of failed keepalives before dropping the connection (linux)"},
+	/* other options */
+	{ "crlf_ping",   CFG_VAR_INT | CFG_READONLY,    0,        1,  0,         0,
+		"enable responding to CRLF SIP-level keepalives "},
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+
+void* tcp_cfg; /* tcp config handle */
 
 /* set defaults */
 void init_tcp_options()
 {
 #ifdef TCP_BUF_WRITE
-	tcp_options.tcp_buf_write=0;
-	tcp_options.tcpconn_wq_max=32*1024; /* 32 k */
-	tcp_options.tcp_wq_max=10*1024*1024; /* 10 MB */
-	tcp_options.tcp_wq_timeout=S_TO_TICKS(tcp_send_timeout);
+	tcp_default_cfg.tcp_buf_write=0;
+	tcp_default_cfg.tcpconn_wq_max=32*1024; /* 32 k */
+	tcp_default_cfg.tcp_wq_max=10*1024*1024; /* 10 MB */
+	tcp_default_cfg.tcp_wq_timeout=S_TO_TICKS(tcp_send_timeout);
 #ifdef TCP_CONNECT_WAIT
-	tcp_options.tcp_connect_wait=1;
+	tcp_default_cfg.tcp_connect_wait=1;
 #endif /* TCP_CONNECT_WAIT */
 #endif /* TCP_BUF_WRITE */
 #ifdef TCP_FD_CACHE
-	tcp_options.fd_cache=1;
+	tcp_default_cfg.fd_cache=1;
 #endif
 #ifdef HAVE_SO_KEEPALIVE
-	tcp_options.keepalive=1;
+	tcp_default_cfg.keepalive=1;
 #endif
 /*
 #if defined HAVE_TCP_DEFER_ACCEPT || defined HAVE_TCP_ACCEPT_FILTER
-	tcp_options.defer_accept=1;
+	tcp_default_cfg.defer_accept=1;
 #endif
 */
 #ifdef HAVE_TCP_QUICKACK
-	tcp_options.delayed_ack=1;
+	tcp_default_cfg.delayed_ack=1;
 #endif
-	tcp_options.crlf_ping=1;
+	tcp_default_cfg.crlf_ping=1;
 }
 
 
 
 #define W_OPT_NC(option) \
-	if (tcp_options.option){\
+	if (tcp_default_cfg.option){\
 		WARN("tcp_options: tcp_" #option \
 				" cannot be enabled (recompile needed)\n"); \
-		tcp_options.option=0; \
+		tcp_default_cfg.option=0; \
 	}
 
 
 
 #define W_OPT_NS(option) \
-	if (tcp_options.option){\
+	if (tcp_default_cfg.option){\
 		WARN("tcp_options: tcp_" #option \
 				" cannot be enabled (no OS support)\n"); \
-		tcp_options.option=0; \
+		tcp_default_cfg.option=0; \
 	}
 
 
@@ -97,10 +172,10 @@ void tcp_options_check()
 	W_OPT_NC(tcp_connect_wait);
 #endif /* TCP_CONNECT_WAIT */
 	
-	if (tcp_options.tcp_connect_wait && !tcp_options.tcp_buf_write){
+	if (tcp_default_cfg.tcp_connect_wait && !tcp_default_cfg.tcp_buf_write){
 		WARN("tcp_options: tcp_connect_wait depends on tcp_buf_write, "
 				" disabling...\n");
-		tcp_options.tcp_connect_wait=0;
+		tcp_default_cfg.tcp_connect_wait=0;
 	}
 	
 #if ! defined HAVE_TCP_DEFER_ACCEPT && ! defined HAVE_TCP_ACCEPT_FILTER
@@ -121,8 +196,9 @@ void tcp_options_check()
 #ifndef HAVE_TCP_KEEPCNT
 	W_OPT_NS(keepcnt);
 #endif
-	if (tcp_options.keepintvl || tcp_options.keepidle || tcp_options.keepcnt){
-		tcp_options.keepalive=1; /* force on */
+	if (tcp_default_cfg.keepintvl || tcp_default_cfg.keepidle || 
+			tcp_default_cfg.keepcnt){
+		tcp_default_cfg.keepalive=1; /* force on */
 	}
 #ifndef HAVE_SO_KEEPALIVE
 	W_OPT_NS(keepalive);
@@ -134,7 +210,23 @@ void tcp_options_check()
 
 
 
-void tcp_options_get(struct tcp_cfg_options* t)
+void tcp_options_get(struct cfg_group_tcp* t)
 {
-	*t=tcp_options;
+	*t=tcp_default_cfg;
+}
+
+
+
+/** register tcp config into the configuration framework.
+ *  @return 0 on succes, -1 on error*/
+int tcp_register_cfg()
+{
+	if (cfg_declare("tcp", tcp_cfg_def, &tcp_default_cfg, cfg_sizeof(tcp),
+					&tcp_cfg))
+		return -1;
+	if (tcp_cfg==0){
+		BUG("null tcp cfg");
+		return -1;
+	}
+	return 0;
 }

+ 11 - 5
tcp_options.h

@@ -109,15 +109,15 @@
 
 #endif /* USE_TCP */
 
-struct tcp_cfg_options{
+struct cfg_group_tcp{
 	/* ser tcp options */
 	int fd_cache; /* on /off */
-	/* tcp buf. write options */
+	/* tcp async options */
 	int tcp_buf_write; /* on / off */
 	int tcp_connect_wait; /* on / off, depends on tcp_buf_write */
 	unsigned int tcpconn_wq_max; /* maximum queue len per connection */
 	unsigned int tcp_wq_max; /* maximum overall queued bytes */
-	unsigned int tcp_wq_timeout;      /* timeout for queue writes */
+	unsigned int tcp_wq_timeout;      /* timeout for queued writes */
 
 	/* tcp socket options */
 	int defer_accept; /* on / off */
@@ -128,14 +128,20 @@ struct tcp_cfg_options{
 	int keepidle;   /* idle time (s) before tcp starts sending keepalives */
 	int keepintvl;  /* interval between keep alives */
 	int keepcnt;    /* maximum no. of keepalives before giving up */
+	
+	/* other options */
 	int crlf_ping;  /* on/off - reply to double CRLF keepalives */
 };
 
+extern struct cfg_group_tcp tcp_default_cfg;
+
+/* tcp config handle*/
+extern void* tcp_cfg;
 
-extern struct tcp_cfg_options tcp_options;
 
 void init_tcp_options();
 void tcp_options_check();
-void tcp_options_get(struct tcp_cfg_options* t);
+int tcp_register_cfg();
+void tcp_options_get(struct cfg_group_tcp* t);
 
 #endif /* tcp_options_h */

+ 1 - 1
tcp_read.c

@@ -351,7 +351,7 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
 					case '\n':
 						break;
 					case '\r':
-						if (tcp_options.crlf_ping) {
+						if (cfg_get(tcp, tcp_cfg, crlf_ping)) {
 							r->state=H_SKIP_EMPTY_CR_FOUND;
 							r->start=p;
 						}