aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2016-01-18 11:36:44 -0500
committerFranklin Wei <git@fwei.tk>2016-01-18 11:36:44 -0500
commita8cdc61833ab16dcb0d0d8364710d55759cc0293 (patch)
tree0fc29d8bd03f5bd9cc6ad61e4b887f5fb939c413
parent17ca1e8e354572f68f0e369431fcfcf3249b93ae (diff)
downloadnetcosm-a8cdc61833ab16dcb0d0d8364710d55759cc0293.zip
netcosm-a8cdc61833ab16dcb0d0d8364710d55759cc0293.tar.gz
netcosm-a8cdc61833ab16dcb0d0d8364710d55759cc0293.tar.bz2
netcosm-a8cdc61833ab16dcb0d0d8364710d55759cc0293.tar.xz
support telnet NAWS (RFC 1073)
-rw-r--r--src/telnet.c76
-rw-r--r--src/telnet.h5
2 files changed, 64 insertions, 17 deletions
diff --git a/src/telnet.c b/src/telnet.c
index 12c9533..0558dfd 100644
--- a/src/telnet.c
+++ b/src/telnet.c
@@ -21,13 +21,26 @@
#include "client.h"
#include "telnet.h"
-int telnet_handle_command(const unsigned char *buf)
+static uint16_t term_width, term_height;
+
+uint16_t telnet_get_width(void)
+{
+ return term_width;
+}
+
+uint16_t telnet_get_height(void)
+{
+ return term_height;
+}
+
+int telnet_handle_command(const unsigned char *buf, size_t buflen)
{
- bool cmd = false;
+ bool found_cmd = false;
+ bool in_sb = false;
- while(*buf)
+ for(unsigned i = 0; i < buflen; ++i)
{
- unsigned char c = *buf;
+ unsigned char c = buf[i];
const struct telnet_cmd {
int val;
@@ -50,24 +63,49 @@ int telnet_handle_command(const unsigned char *buf)
{ IP, "IP" },
};
- for(unsigned int i = 0; i < ARRAYLEN(commands); ++i)
+ for(unsigned int cmd_idx = 0; cmd_idx < ARRAYLEN(commands); ++cmd_idx)
{
- if(c == commands[i].val)
+ if(c == commands[cmd_idx].val)
{
- debugf("%s ", commands[i].name);
- cmd = true;
- if(c == IP)
+ debugf("%s ", commands[cmd_idx].name);
+ found_cmd = true;
+ switch(c)
+ {
+ case IP:
return TELNET_EXIT;
- goto found;
+ case SB:
+ in_sb = true;
+ break;
+ case NAWS:
+ if(in_sb)
+ {
+ /* read height/width */
+ uint8_t bytes[4];
+ int j = 0;
+ while(j < 4 && i < buflen)
+ {
+ bytes[j++] = buf[++i];
+ sig_debugf("read byte %d %d\n", buf[i], j);
+ if(bytes[j - 1] == 255) /* 255 is doubled */
+ {
+ ++i;
+ }
+ }
+ term_width = ntohs(*((uint16_t*)bytes));
+ term_height = ntohs(*((uint16_t*)(bytes+2)));
+ sig_debugf("term size: %dx%d\n", term_width, term_height);
+ }
+ break;
+ }
+ goto got_cmd;
}
}
debugf("???: %d ", c);
- found:
-
- ++buf;
+ got_cmd:
+ ;
}
- if(cmd)
+ if(found_cmd)
debugf("\n");
return TELNET_OK;
@@ -96,13 +134,19 @@ void telnet_init(void)
const unsigned char init_seq[] = {
IAC, WONT, SGA,
IAC, DONT, SGA,
- IAC, WONT, NAWS,
- IAC, DONT, NAWS,
+
+ IAC, DO, NAWS,
+
IAC, WONT, STATUS,
IAC, DONT, STATUS,
+
IAC, DO, ECHO,
IAC, WONT, ECHO,
+
IAC, DONT, LINEMODE,
};
+ term_width = 80;
+ term_height = 24;
+
out_raw(init_seq, ARRAYLEN(init_seq));
}
diff --git a/src/telnet.h b/src/telnet.h
index f54643f..854828e 100644
--- a/src/telnet.h
+++ b/src/telnet.h
@@ -46,7 +46,10 @@ void telnet_init(void);
#define TELNET_EXIT 1
/* returns either TELNET_OK or TELNET_EXIT */
-int telnet_handle_command(const unsigned char*);
+int telnet_handle_command(const unsigned char*, size_t);
+
+uint16_t telnet_get_width(void);
+uint16_t telnet_get_height(void);
void telnet_echo_on(void);
void telnet_echo_off(void);