/*
* NetCosm - a MUD server
* Copyright (C) 2016 Franklin Wei
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#define TELCMDS /* see */
#define TELOPTS
#include "globals.h"
#include "client.h"
#include "telnet.h"
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;
}
enum telnet_status telnet_parse_data(const unsigned char *buf, size_t buflen)
{
bool iac = false;
bool found_cmd = false;
bool in_sb = false;
bool line_done = false;
for(unsigned i = 0; i < buflen; ++i)
{
unsigned char c = buf[i];
if(c == IAC)
iac = true;
else if(c == '\n' || c == '\r')
line_done = true;
if(iac)
{
if(TELCMD_OK(c))
{
found_cmd = true;
switch(c)
{
case IP:
return TELNET_EXIT;
case SB:
in_sb = true;
break;
case TELOPT_NAWS:
if(in_sb)
{
/* read height/width */
uint8_t bytes[4];
int j = 0;
while(j < 4 && i < buflen)
{
bytes[j++] = buf[++i];
//debugf("%d ", buf[j - 1]);
if(bytes[j - 1] == 255) /* 255 is doubled to distinguish from IAC */
{
++i;
}
}
if(i >= buflen && j != 4)
error("client SB NAWS command to short");
term_width = ntohs(*((uint16_t*)bytes));
term_height = ntohs(*((uint16_t*)(bytes+2)));
}
break;
}
continue;
}
}
}
return found_cmd ? TELNET_FOUNDCMD :
(line_done ? TELNET_LINEOVER : TELNET_DATA);
}
void telnet_echo_off(void)
{
const unsigned char seq[] = {
IAC, WILL, TELOPT_ECHO,
IAC, DONT, TELOPT_ECHO,
};
out_raw(seq, ARRAYLEN(seq));
}
void telnet_echo_on(void)
{
const unsigned char seq[] = {
IAC, WONT, TELOPT_ECHO,
IAC, DO, TELOPT_ECHO,
};
out_raw(seq, ARRAYLEN(seq));
}
void telnet_init(void)
{
const unsigned char init_seq[] = {
IAC, WONT, TELOPT_SGA,
IAC, DONT, TELOPT_SGA,
IAC, DO, TELOPT_NAWS,
IAC, WONT, TELOPT_STATUS,
IAC, DONT, TELOPT_STATUS,
IAC, DO, TELOPT_ECHO,
IAC, DONT, TELOPT_LINEMODE,
};
term_width = 80;
term_height = 24;
out_raw(init_seq, ARRAYLEN(init_seq));
}
void telnet_clear_screen(void)
{
/* ESC ] 2 J */
unsigned char clear_seq[] = { '\033',
']',
'2',
'J' };
out_raw(clear_seq, ARRAYLEN(clear_seq));
}