#include #include #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); }