jcs
/subtext
/amendments
/173
telnet: Pre-allocate nodes, bump max to 10
This way we aren't constantly trying to find space for these big
        chunks of memory for every new connection.
    jcs made amendment 173 over 3 years ago
--- telnet.c	Thu Jun 23 10:05:22 2022
+++ telnet.c	Thu Jun 23 14:21:30 2022
@@ -109,7 +109,7 @@ struct telnet_node {
 	rdsEntry tcp_rds[2];
 };
 
-#define MAX_TELNET_NODES	5
+#define MAX_TELNET_NODES	10
 static struct telnet_node *telnet_nodes[MAX_TELNET_NODES] = { NULL };
 static struct telnet_node *telnet_listener_node = NULL;
 static TCPiopb telnet_exit_pb;
@@ -135,7 +135,7 @@ static const char * vt100_terms[] = {
 };
 
 void telnet_setup(struct session *session);
-void telnet_create_listener_node(short node_idx);
+void telnet_listen_on_node(struct telnet_node *node);
 void telnet_output_iac(struct session *session, const char *iacs,
   size_t len);
 bool telnet_ip_is_banned(ip_addr ip);
@@ -150,6 +150,8 @@ struct node_funcs telnet_node_funcs = {
 void
 telnet_init(void)
 {
+	short n;
+	
 	if (!db->config.telnet_port)
 		return;
 
@@ -157,6 +159,15 @@ telnet_init(void)
 
 	if (_TCPInit() != noErr)
 		panic("Failed initializing MacTCP");
+	
+	/* pre-allocate nodes */
+	for (n = 0; n < MAX_TELNET_NODES; n++) {
+		telnet_nodes[n] = xmalloczero(sizeof(struct telnet_node));
+		telnet_nodes[n]->id = n;
+		
+		if (n == 0)
+			telnet_listen_on_node(telnet_nodes[n]);
+	}
 }
 
 void
@@ -181,18 +192,19 @@ telnet_atexit(void)
 }
 
 void
-telnet_create_listener_node(short node_idx)
+telnet_listen_on_node(struct telnet_node *node)
 {
 	char ip_s[20];
-	struct telnet_node *node;
-	short error;
+	short error, id;
 	ip_addr ip;
 	tcp_port port;
 	long mask;
 
-	node = xmalloczero(sizeof(struct telnet_node));
-	node->id = node_idx;
-	snprintf(node->name, sizeof(node->name), "ttyt%d", node_idx);
+	id = node->id;
+	memset(node, 0, sizeof(struct telnet_node));
+	node->id = id;
+	
+	snprintf(node->name, sizeof(node->name), "ttyt%d", id);
 
 	error = _TCPCreate(&node->listen_pb, &node->stream,
 	  (Ptr)&node->tcp_buf, sizeof(node->tcp_buf), nil, nil, nil, false);
@@ -218,7 +230,6 @@ telnet_create_listener_node(short node_idx)
 		  node->id, db->config.telnet_port, error);
 		  
 	node->state = TELNET_PB_STATE_LISTENING;
-	telnet_nodes[node->id] = node;
 	telnet_listener_node = node;
 }
 
@@ -234,14 +245,11 @@ telnet_idle(void)
 	for (n = 0; n < MAX_TELNET_NODES; n++) {
 		node = telnet_nodes[n];
 		
-		if (!node) {
-			if (telnet_listener_node != NULL)
-				continue;
-			telnet_create_listener_node(n);
-			continue;
-		}
-		
 		switch (node->state) {
+		case TELNET_PB_STATE_UNUSED:
+			if (telnet_listener_node == NULL)
+				telnet_listen_on_node(node);
+			break;
 		case TELNET_PB_STATE_LISTENING:
 			error = _TCPStatus(&node->send_pb, node->stream,
 			  &telnet_status_pb, nil, nil, false);
@@ -283,8 +291,7 @@ telnet_idle(void)
 					_TCPRelease(&node->listen_pb, node->stream, nil,
 					  nil, false);
 					  
-					telnet_nodes[n] = NULL;
-					free(node);
+					node->state = TELNET_PB_STATE_UNUSED;
 					goto next_node;
 				}
 				
@@ -316,16 +323,15 @@ telnet_idle(void)
 				else {
 					_TCPRelease(&node->listen_pb, node->stream, nil, nil,
 					  false);
-					telnet_nodes[n] = telnet_listener_node = NULL;
-					free(node);
+					node->state = TELNET_PB_STATE_UNUSED;
+					telnet_listener_node = NULL;
 				}
 				goto next_node;
 			}
 			break;
 		case TELNET_PB_STATE_CONNECTED:
 			if (!node->session) {
-				free(node);
-				telnet_nodes[n] = NULL;
+				node->state = TELNET_PB_STATE_UNUSED;
 				break;
 			}
 				
@@ -803,8 +809,7 @@ telnet_close(struct session *session)
 	}
 
 	session->cookie = NULL;
-	telnet_nodes[node->id] = NULL;
-	free(node);
+	node->state = TELNET_PB_STATE_UNUSED;
 }
 
 bool
@@ -815,10 +820,10 @@ telnet_ip_is_banned(ip_addr ip)
 	bool ret = false;
 	
 	for (j = 0; j < MAX_BANNED_IPS; j++) {
-		if (banned_ips[j].ip &&
+		if (banned_ips[j].ip && Time > banned_ips[j].time &&
 		  (Time - banned_ips[j].time > IP_BAN_SECONDS)) {
 			long2ip(banned_ips[j].ip, ip_s);
-			logger_printf(logger, "[%s] Unbanning IP after %d seconds",
+			logger_printf(logger, "[%s] Unbanning IP after %ld seconds",
 			  ip_s, Time - banned_ips[j].time);
 			banned_ips[j].ip = 0;
 			continue;