You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
5.2 KiB

#include <string.h>
#include <stdio.h>
#include "dwt.h"
#include "server.h"
#include "libtelnet.h"
#include "socket.h"
#include "w5500.h"
#include "tick.h"
#include "config.h"
#include "cmd.h"
struct server {
telnet_t *telnet;
zcHandle console;
SOCKET tcp;
int port;
volatile uint8_t *rx_buffer;
uint16_t rx_buffer_size;
volatile uint16_t rx_head, rx_tail;
};
static volatile uint8_t __server0_rx_buffer[TARGET_SERVER_RXBUF_SZ] __attribute__((section(".txbuf.server,\"aw\",%nobits@")));
static struct server server0;
static void rx_buffer_put(struct server *srv, uint8_t data)
{
srv->rx_buffer[srv->rx_tail % srv->rx_buffer_size] = data;
srv->rx_tail++;
}
static int rx_buffer_empty(struct server *srv)
{
return srv->rx_head == srv->rx_tail;
}
static uint8_t rx_buffer_get(struct server *srv)
{
uint8_t data = srv->rx_buffer[srv->rx_head % srv->rx_buffer_size];
srv->rx_head++;
return data;
}
static void __delay_us(void *param, unsigned int us)
{
dwt_wait_us(us);
}
static void __send_char(void *param, int _ch)
{
char ch = _ch;
struct server *srv = param;
if (srv->telnet)
telnet_send(srv->telnet, &ch, 1);
}
static int __get_char(void *param, char *ch)
{
struct server *srv = param;
if (!rx_buffer_empty(srv)) {
*ch = rx_buffer_get(srv);
return 1;
}
return 0;
}
static void tcp_output(struct server *srv, const void *buf, int len)
{
int n;
if (getSn_SR(srv->tcp) != SOCK_ESTABLISHED) { /* drop packets */
return;
}
n = send(srv->tcp, buf, len, 0);
if (n != len) {
printf("drop packet: %d -> %d\r\n", len, n);
}
//delay(5);
//fwrite(buf, 1, len, stdout);
}
static void event_handler(telnet_t *telnet, telnet_event_t *ev, void *user_data)
{
int i;
struct server *srv = user_data;
switch (ev->type) {
case TELNET_EV_DATA:
for (i = 0; i < ev->data.size; ++i) {
rx_buffer_put(srv, ev->data.buffer[i]);
}
break;
case TELNET_EV_SEND:
tcp_output(srv, ev->data.buffer, ev->data.size);
break;
case TELNET_EV_IAC:
if (ev->iac.cmd == TELNET_SUSP || ev->iac.cmd == TELNET_ABORT) {
rx_buffer_put(srv, 26); /* put CTRL-Z */
}
break;
case TELNET_EV_DO:
if (ev->neg.telopt == TELNET_TELOPT_ECHO) {
if (srv->console)
consoleSetEchoMode(srv->console, 1);
}
break;
case TELNET_EV_DONT:
if (ev->neg.telopt == TELNET_TELOPT_ECHO) {
if (srv->console)
consoleSetEchoMode(srv->console, 0);
}
break;
case TELNET_EV_WILL:
if (ev->neg.telopt == TELNET_TELOPT_ECHO) {
if (srv->console)
consoleSetEchoMode(srv->console, 0);
}
break;
case TELNET_EV_WONT:
if (ev->neg.telopt == TELNET_TELOPT_ECHO) {
if (srv->console)
consoleSetEchoMode(srv->console, 1);
}
break;
case TELNET_EV_SUBNEGOTIATION:
printf("opt: %d (%d)\r\n", ev->sub.telopt, ev->sub.size);
break;
default:
break;
}
}
int telnet_proto_init(SOCKET socket, int port)
{
ConsoleCfg cfg;
static const telnet_telopt_t my_telopts[] = {
{ TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO }, /* I will, you don't */
{ TELNET_TELOPT_BINARY, TELNET_WILL, TELNET_DO }, /* I will, you do */
{ TELNET_TELOPT_SGA, TELNET_WILL, TELNET_DO }, /* I will, you do */
{ TELNET_TELOPT_LINEMODE, TELNET_WONT, TELNET_DONT }, /* I will, you do */
{ TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DO },
{ -1, 0, 0 }
};
memset(&server0, 0, sizeof server0);
server0.rx_buffer = __server0_rx_buffer;
server0.rx_buffer_size = TARGET_SERVER_RXBUF_SZ;
memset(&cfg, 0, sizeof cfg);
cfg.delayUs = __delay_us;
cfg.getc = __get_char;
cfg.putc = __send_char;
cfg.param = &server0;
cfg.prompt = "A10> ";
server0.console = consoleNew(&cfg);
if (server0.console)
consoleSetEchoMode(server0.console, 0);
server0.telnet = telnet_init(my_telopts, event_handler, TELNET_FLAG_TRANSMIT_BINARY | TELNET_FLAG_RECEIVE_BINARY, &server0);
if (server0.telnet == NULL) {
return -1;
}
server0.tcp = socket;
server0.port = port;
return 0;
}
static int tcp_input(struct server *srv, int tcp)
{
uint8 buf[64];
int len = getSn_RX_RSR(tcp);
if (len <= 0)
return 0;
if (len > sizeof buf)
len = sizeof buf;
len = recv(tcp, buf, len);
if (srv->telnet)
telnet_recv(srv->telnet, (const char *)buf, len);
return len;
}
static void process_tcp(struct server *srv)
{
int s = srv->tcp;
int state = getSn_SR(s);
switch (state) {
case SOCK_CLOSED:
if(socket(s, (Sn_MR_ND | Sn_MR_TCP),srv->port, 0x00) == 0) {
printf("%d : Fail to create socket.\r\n", s);
}
break;
case SOCK_INIT: /* if a socket is initiated */
listen(s);
printf("%x :LISTEN socket %d\r\n",getSn_SR(s), s);
break;
case SOCK_ESTABLISHED:
tcp_input(srv, s);
break;
case SOCK_CLOSE_WAIT: /* If the client request to close */
disconnect(s);
printf("%d : CLOSE_WAIT\r\n", s);
break;
default:
break;
}
}
zcHandle telnet_get_console()
{
return server0.console;
}
void telnet_proto_loop()
{
if (server0.telnet) {
process_tcp(&server0);
}
if (server0.console)
consoleProcess(server0.console);
}