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.
This commit is contained in:
Oliver Schmidt 2011-05-21 21:03:04 +02:00
parent 8c00be1a56
commit d4f49fa204

View File

@ -55,6 +55,13 @@ AUTOSTART_PROCESSES(&telnetd_process);
#define TELNETD_CONF_NUMLINES 25 #define TELNETD_CONF_NUMLINES 25
#endif #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 { struct telnetd_state {
char buf[TELNETD_CONF_LINELEN + 1]; char buf[TELNETD_CONF_LINELEN + 1];
char bufptr; char bufptr;
@ -93,6 +100,8 @@ struct telnetd_buf {
static struct telnetd_buf buf; static struct telnetd_buf buf;
static uint8_t connected;
#define MIN(a, b) ((a) < (b)? (a): (b)) #define MIN(a, b) ((a) < (b)? (a): (b))
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
@ -192,6 +201,8 @@ PROCESS_THREAD(telnetd_process, ev, data)
telnetd_gui_init(); telnetd_gui_init();
#endif /* TELNETD_CONF_GUI */ #endif /* TELNETD_CONF_GUI */
petsciiconv_toascii(telnetd_reject_text, strlen(telnetd_reject_text));
tcp_listen(UIP_HTONS(23)); tcp_listen(UIP_HTONS(23));
while(1) { while(1) {
@ -341,37 +352,52 @@ void
telnetd_appcall(void *ts) telnetd_appcall(void *ts)
{ {
if(uip_connected()) { if(uip_connected()) {
tcp_unlisten(UIP_HTONS(23)); if(!connected) {
tcp_markconn(uip_conn, &s); buf_init(&buf);
buf_init(&buf); s.bufptr = 0;
s.bufptr = 0; s.state = STATE_NORMAL;
s.state = STATE_NORMAL; connected = 1;
shell_start(); 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) { if(!ts) {
s.state = STATE_NORMAL; if(s.state == STATE_CLOSE) {
uip_close(); s.state = STATE_NORMAL;
return; uip_close();
} return;
if(uip_closed() || }
uip_aborted() || if(uip_closed() ||
uip_timedout()) { uip_aborted() ||
shell_stop(); uip_timedout()) {
tcp_listen(UIP_HTONS(23)); shell_stop();
} connected = 0;
if(uip_acked()) { }
acked(); if(uip_acked()) {
} acked();
if(uip_newdata()) { }
newdata(); if(uip_newdata()) {
} newdata();
if(uip_rexmit() || }
uip_newdata() || if(uip_rexmit() ||
uip_acked() || uip_newdata() ||
uip_connected() || uip_acked() ||
uip_poll()) { uip_connected() ||
senddata(); uip_poll()) {
senddata();
}
} else {
if(uip_poll()) {
tcp_markconn(uip_conn, ++(char *)ts);
if(ts == (char *)10) {
uip_close();
}
}
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/