From d4f49fa2042e5b57287643619082d2dad794854e Mon Sep 17 00:00:00 2001 From: Oliver Schmidt Date: Sat, 21 May 2011 21:03:04 +0200 Subject: [PATCH] Added explicit rejection of multiple connections. Although a simple solution the recently introduced approach to just not listen to incoming connetions if there's already one has the downside that one doesn't know if a connection fails because the server is down or becuase there's a connection. Therefore now connections are always accepted but after sending a message to the user and waiting a few seconds they are closed. The appstate is used used in a somewhat unusual way here: The one and only "active" connection has an appstate of 0. For all other connections the appstate is initially set to 1. Then it is increased on every uIP poll until it reaches 10, which triggers the connection close. This somewhat hacky approach allows to keep track of the rejected sessions without any additional state variables and/or timers. --- apps/telnetd/telnetd.c | 84 +++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/apps/telnetd/telnetd.c b/apps/telnetd/telnetd.c index 012e8766a..2d388f5f9 100644 --- a/apps/telnetd/telnetd.c +++ b/apps/telnetd/telnetd.c @@ -55,6 +55,13 @@ AUTOSTART_PROCESSES(&telnetd_process); #define TELNETD_CONF_NUMLINES 25 #endif +#ifdef TELNETD_CONF_REJECT +extern char telnetd_reject_text[]; +#else +static char telnetd_reject_text[] = + "Too many connections, please try again later."; +#endif + struct telnetd_state { char buf[TELNETD_CONF_LINELEN + 1]; char bufptr; @@ -93,6 +100,8 @@ struct telnetd_buf { static struct telnetd_buf buf; +static uint8_t connected; + #define MIN(a, b) ((a) < (b)? (a): (b)) /*---------------------------------------------------------------------------*/ static void @@ -192,6 +201,8 @@ PROCESS_THREAD(telnetd_process, ev, data) telnetd_gui_init(); #endif /* TELNETD_CONF_GUI */ + petsciiconv_toascii(telnetd_reject_text, strlen(telnetd_reject_text)); + tcp_listen(UIP_HTONS(23)); while(1) { @@ -341,37 +352,52 @@ void telnetd_appcall(void *ts) { if(uip_connected()) { - tcp_unlisten(UIP_HTONS(23)); - tcp_markconn(uip_conn, &s); - buf_init(&buf); - s.bufptr = 0; - s.state = STATE_NORMAL; - shell_start(); + if(!connected) { + buf_init(&buf); + s.bufptr = 0; + s.state = STATE_NORMAL; + connected = 1; + shell_start(); + ts = (char *)0; + } else { + uip_send(telnetd_reject_text, strlen(telnetd_reject_text)); + ts = (char *)1; + } + tcp_markconn(uip_conn, ts); } - if(s.state == STATE_CLOSE) { - s.state = STATE_NORMAL; - uip_close(); - return; - } - if(uip_closed() || - uip_aborted() || - uip_timedout()) { - shell_stop(); - tcp_listen(UIP_HTONS(23)); - } - if(uip_acked()) { - acked(); - } - if(uip_newdata()) { - newdata(); - } - if(uip_rexmit() || - uip_newdata() || - uip_acked() || - uip_connected() || - uip_poll()) { - senddata(); + if(!ts) { + if(s.state == STATE_CLOSE) { + s.state = STATE_NORMAL; + uip_close(); + return; + } + if(uip_closed() || + uip_aborted() || + uip_timedout()) { + shell_stop(); + connected = 0; + } + if(uip_acked()) { + acked(); + } + if(uip_newdata()) { + newdata(); + } + if(uip_rexmit() || + uip_newdata() || + uip_acked() || + uip_connected() || + uip_poll()) { + senddata(); + } + } else { + if(uip_poll()) { + tcp_markconn(uip_conn, ++(char *)ts); + if(ts == (char *)10) { + uip_close(); + } + } } } /*---------------------------------------------------------------------------*/