AmendHub

Download:

jcs

/

subtext

/

amendments

/

211

*: Properly handle running out of sessions

Limit sessions to the number of uthreads we can handle, and then
reserve 1 session for the console.
 
In telnet, allocate one extra node so we can print a message to the
client that we have no free nodes, and then disconnect. Add a view
for this to make it editable.
 
In console, handle getting a null session back from session_create.

jcs made amendment 211 about 1 year ago
--- console.c Fri Jun 24 09:47:08 2022 +++ console.c Sat Jul 16 23:05:59 2022 @@ -68,6 +68,15 @@ console_init(void) short width, height; console = xmalloczero(sizeof(struct console)); + + console->session = session_create("console", "console", + &console_node_funcs); + if (console->session == NULL) { + free(console); + warn("No free nodes for a console"); + return NULL; + } + memset(console->chars, ' ', sizeof(console->chars)); console->ncolumns = DEFAULT_TERMINAL_COLUMNS; console->nlines = DEFAULT_TERMINAL_LINES; @@ -101,8 +110,6 @@ console_init(void) console->focusable = focusable; add_focusable(focusable); - console->session = session_create("console", "console", - &console_node_funcs); console->session->cookie = (void *)console; console->session->vt100 = 1; console->session->cp437 = 1; --- db.h Wed Jul 13 17:44:37 2022 +++ db.h Sat Jul 16 23:12:38 2022 @@ -41,6 +41,7 @@ #define DB_TEXT_ISSUE_ID 3 #define DB_TEXT_SIGNUP_ID 4 #define DB_TEXT_PAGE_SYSOP_ID 5 +#define DB_TEXT_NO_FREE_NODES_ID 6 #define DB_USERNAME_LENGTH 16 --- main.c Fri Jul 15 22:33:17 2022 +++ main.c Sat Jul 16 23:35:49 2022 @@ -328,6 +328,9 @@ handle_menu(long menu_id) case VIEWS_SUBMENU_PAGE_SYSOP_ID: view_editor_show(DB_TEXT_PAGE_SYSOP_ID, "Edit: Page Sysop view"); break; + case VIEWS_SUBMENU_NO_FREE_NODES_ID: + view_editor_show(DB_TEXT_NO_FREE_NODES_ID, "Edit: No Free Nodes view"); + break; } ret = 1; break; --- session.c Sat Jul 16 14:32:15 2022 +++ session.c Sat Jul 16 22:59:31 2022 @@ -74,8 +74,15 @@ session_create(char *node, char *via, struct node_func struct session *session; size_t n; - if (nsessions >= MAX_SESSIONS) - return NULL; + /* reserve 1 session for the console */ + if (nsessions >= MAX_SESSIONS - 1) { + if (strcmp(node, "console") != 0) + return NULL; + + /* but only 1 */ + if (nsessions == MAX_SESSIONS) + return NULL; + } nsessions++; --- session.h Sat Jul 16 14:32:32 2022 +++ session.h Sat Jul 16 21:42:56 2022 @@ -102,7 +102,7 @@ struct session { struct uthread *uthread; }; -#define MAX_SESSIONS 20 +#define MAX_SESSIONS NUM_UTHREADS extern struct session *sessions[MAX_SESSIONS]; extern short nsessions; --- subtext.h Tue Jun 21 15:42:02 2022 +++ subtext.h Sat Jul 16 23:35:31 2022 @@ -44,6 +44,7 @@ #define VIEWS_SUBMENU_SHORT_MENU_ID 3 #define VIEWS_SUBMENU_SIGNUP_ID 4 #define VIEWS_SUBMENU_PAGE_SYSOP_ID 5 +#define VIEWS_SUBMENU_NO_FREE_NODES_ID 6 #define STR_LAST_DB 128 --- telnet.c Thu Jul 14 09:41:45 2022 +++ telnet.c Sun Jul 17 00:00:16 2022 @@ -111,7 +111,9 @@ struct telnet_node { wdsEntry tcp_wds[2]; }; -#define MAX_TELNET_NODES 10 +/* add one to be able to print busy messages */ +#define MAX_TELNET_NODES (MAX_SESSIONS + 1) + static struct telnet_node *telnet_nodes[MAX_TELNET_NODES] = { NULL }; static struct telnet_node *telnet_listener_node = NULL; static TCPiopb telnet_exit_pb; @@ -147,6 +149,7 @@ 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); +void telnet_print_busy(struct telnet_node *node); struct node_funcs telnet_node_funcs = { telnet_setup, @@ -324,6 +327,15 @@ telnet_idle(void) node->session = session_create(node->name, node->from_trusted_proxy ? "web" : "telnet", &telnet_node_funcs); + if (node->session == NULL) { + logger_printf(logger, "[%s] No free nodes, " + "disconnecting", node->name); + telnet_print_busy(node); + _TCPRelease(&node->listen_pb, node->stream, nil, + nil, false); + node->state = TELNET_PB_STATE_UNUSED; + goto next_node; + } node->session->cookie = (void *)node; node->session->tspeed = 19200; node->session->is_telnet = true; @@ -901,4 +913,44 @@ telnet_ip_is_banned(ip_addr ip) } return ret; +} + +void +telnet_print_busy(struct telnet_node *node) +{ + size_t len, n, olen; + unsigned long now; + short error; + char *data = NULL; + + if ((len = bile_read_alloc(db->bile, DB_TEXT_TYPE, + DB_TEXT_NO_FREE_NODES_ID, &data)) == 0) { + len = snprintf((char *)&node->obuf, sizeof(node->obuf), + "No free nodes, please call back later.\r\n"); + } else { + for (n = 0, olen = 0; n < len && olen < sizeof(node->obuf) - 1; + n++) { + node->obuf[olen++] = data[n]; + if (data[n] == '\r' && data[n + 1] != '\n') + node->obuf[olen++] = '\n'; + } + free(data); + } + + node->tcp_wds[0].ptr = (Ptr)&node->obuf; + node->tcp_wds[0].length = len; + node->tcp_wds[1].ptr = 0; + node->tcp_wds[1].length = 0; + + now = Ticks; + error = _TCPSend(&node->send_pb, node->stream, node->tcp_wds, nil, nil, + true); + if (error) + return; + + for (;;) { + /* spin for 500ms to let the send finish */ + if (Ticks - now > 30 || node->send_pb.ioResult <= 0) + return; + } } --- uthread.c Sun Jul 10 21:35:22 2022 +++ uthread.c Sat Jul 16 21:42:21 2022 @@ -25,7 +25,6 @@ #define STACK_SIZE (1024 * 5) #define CANARY 0xdeadf00d -#define NUM_UTHREADS 5 jmp_buf uthread_coord_env; static struct uthread uthreads[NUM_UTHREADS] = { 0 }; --- uthread.h Mon Dec 6 15:47:50 2021 +++ uthread.h Sat Jul 16 21:42:35 2022 @@ -19,6 +19,8 @@ #ifndef __UTHREAD_H__ #define __UTHREAD_H__ +#define NUM_UTHREADS 5 + enum { UTHREAD_STATE_DEAD, UTHREAD_STATE_SETUP,