From 5910ae4170e2ebaca9fc05ee87aef167b533d586 Mon Sep 17 00:00:00 2001 From: armink Date: Fri, 18 Aug 2017 11:29:26 +0800 Subject: [NET] Add telnet app to netutils. --- components/net/lwip-2.0.2/apps/telnet.c | 391 -------------------------------- components/net/netutils/README.md | 1 + components/net/netutils/SConscript | 10 + components/net/netutils/telnet.c | 391 ++++++++++++++++++++++++++++++++ 4 files changed, 402 insertions(+), 391 deletions(-) delete mode 100644 components/net/lwip-2.0.2/apps/telnet.c create mode 100644 components/net/netutils/README.md create mode 100644 components/net/netutils/SConscript create mode 100644 components/net/netutils/telnet.c (limited to 'components') diff --git a/components/net/lwip-2.0.2/apps/telnet.c b/components/net/lwip-2.0.2/apps/telnet.c deleted file mode 100644 index d5c127b713..0000000000 --- a/components/net/lwip-2.0.2/apps/telnet.c +++ /dev/null @@ -1,391 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -#define TELNET_PORT 23 -#define TELNET_BACKLOG 5 -#define RX_BUFFER_SIZE 256 -#define TX_BUFFER_SIZE 4096 - -#define ISO_nl 0x0a -#define ISO_cr 0x0d - -#define STATE_NORMAL 0 -#define STATE_IAC 1 -#define STATE_WILL 2 -#define STATE_WONT 3 -#define STATE_DO 4 -#define STATE_DONT 5 -#define STATE_CLOSE 6 - -#define TELNET_IAC 255 -#define TELNET_WILL 251 -#define TELNET_WONT 252 -#define TELNET_DO 253 -#define TELNET_DONT 254 - -struct telnet_session -{ - struct rt_ringbuffer rx_ringbuffer; - struct rt_ringbuffer tx_ringbuffer; - - rt_mutex_t rx_ringbuffer_lock; - rt_mutex_t tx_ringbuffer_lock; - - struct rt_device device; - rt_int32_t server_fd; - rt_int32_t client_fd; - - /* telnet protocol */ - rt_uint8_t state; - rt_uint8_t echo_mode; - -}; - -static struct telnet_session* telnet; - -/* process tx data */ -static void send_to_client(struct telnet_session* telnet) -{ - rt_size_t length; - rt_uint8_t tx_buffer[32]; - - while (1) - { - rt_memset(tx_buffer, 0, sizeof(tx_buffer)); - rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); - /* get buffer from ringbuffer */ - length = rt_ringbuffer_get(&(telnet->tx_ringbuffer), tx_buffer, sizeof(tx_buffer)); - rt_mutex_release(telnet->tx_ringbuffer_lock); - - /* do a tx procedure */ - if (length > 0) - { - send(telnet->client_fd, tx_buffer, length, 0); - } - else break; - } -} - -/* send telnet option to remote */ -static void send_option_to_client(struct telnet_session* telnet, rt_uint8_t option, rt_uint8_t value) -{ - rt_uint8_t optbuf[4]; - - optbuf[0] = TELNET_IAC; - optbuf[1] = option; - optbuf[2] = value; - optbuf[3] = 0; - - rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); - rt_ringbuffer_put(&telnet->tx_ringbuffer, optbuf, 3); - rt_mutex_release(telnet->tx_ringbuffer_lock); - - send_to_client(telnet); -} - -/* process rx data */ -static void process_rx(struct telnet_session* telnet, rt_uint8_t *data, rt_size_t length) -{ - rt_size_t rx_length, index; - - for (index = 0; index < length; index ++) - { - switch(telnet->state) - { - case STATE_IAC: - if (*data == TELNET_IAC) - { - rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); - /* put buffer to ringbuffer */ - rt_ringbuffer_putchar(&(telnet->rx_ringbuffer), *data); - rt_mutex_release(telnet->rx_ringbuffer_lock); - - telnet->state = STATE_NORMAL; - } - else - { - /* set telnet state according to received package */ - switch (*data) - { - case TELNET_WILL: telnet->state = STATE_WILL; break; - case TELNET_WONT: telnet->state = STATE_WONT; break; - case TELNET_DO: telnet->state = STATE_DO; break; - case TELNET_DONT: telnet->state = STATE_DONT; break; - default: telnet->state = STATE_NORMAL; break; - } - } - break; - - /* don't option */ - case STATE_WILL: - case STATE_WONT: - send_option_to_client(telnet, TELNET_DONT, *data); - telnet->state = STATE_NORMAL; - break; - - /* won't option */ - case STATE_DO: - case STATE_DONT: - send_option_to_client(telnet, TELNET_WONT, *data); - telnet->state = STATE_NORMAL; - break; - - case STATE_NORMAL: - if (*data == TELNET_IAC) telnet->state = STATE_IAC; - else if (*data != '\r') /* ignore '\r' */ - { - rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); - /* put buffer to ringbuffer */ - rt_ringbuffer_putchar(&(telnet->rx_ringbuffer), *data); - rt_mutex_release(telnet->rx_ringbuffer_lock); - } - break; - } - - data ++; - } - - rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); - /* get total size */ - rx_length = rt_ringbuffer_data_len(&telnet->rx_ringbuffer); - rt_mutex_release(telnet->rx_ringbuffer_lock); - - /* indicate there are reception data */ - if ((rx_length > 0) && (telnet->device.rx_indicate != RT_NULL)) - telnet->device.rx_indicate(&telnet->device, rx_length); - - return; -} - -/* client close */ -static void client_close(struct telnet_session* telnet) -{ - /* set console */ - rt_console_set_device(RT_CONSOLE_DEVICE_NAME); - /* set finsh device */ - finsh_set_device(RT_CONSOLE_DEVICE_NAME); - - /* close connection */ - closesocket(telnet->client_fd); - - /* restore shell option */ - finsh_set_echo(telnet->echo_mode); - - rt_kprintf("resume console to %s\n", RT_CONSOLE_DEVICE_NAME); -} - -/* RT-Thread Device Driver Interface */ -static rt_err_t telnet_init(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_err_t telnet_open(rt_device_t dev, rt_uint16_t oflag) -{ - return RT_EOK; -} - -static rt_err_t telnet_close(rt_device_t dev) -{ - return RT_EOK; -} - -static rt_size_t telnet_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) -{ - rt_size_t result; - - /* read from rx ring buffer */ - rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); - result = rt_ringbuffer_get(&(telnet->rx_ringbuffer), buffer, size); - rt_mutex_release(telnet->rx_ringbuffer_lock); - - return result; -} - -static rt_size_t telnet_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) -{ - const rt_uint8_t *ptr; - - ptr = (rt_uint8_t*) buffer; - - rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); - while (size) - { - if (*ptr == '\n') - rt_ringbuffer_putchar(&telnet->tx_ringbuffer, '\r'); - - if (rt_ringbuffer_putchar(&telnet->tx_ringbuffer, *ptr) == 0) /* overflow */ - break; - ptr++; - size--; - } - rt_mutex_release(telnet->tx_ringbuffer_lock); - - /* send data to telnet client */ - send_to_client(telnet); - - return (rt_uint32_t) ptr - (rt_uint32_t) buffer; -} - -static rt_err_t telnet_control(rt_device_t dev, rt_uint8_t cmd, void *args) -{ - return RT_EOK; -} - -/* telnet server thread entry */ -static void telnet_thread(void* parameter) -{ -#define RECV_BUF_LEN 64 - - struct sockaddr_in addr; - socklen_t addr_size; - rt_uint8_t recv_buf[RECV_BUF_LEN]; - rt_int32_t recv_len = 0; - - if ((telnet->server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) - { - rt_kprintf("telnet: create socket failed\n"); - return; - } - - addr.sin_family = AF_INET; - addr.sin_port = htons(TELNET_PORT); - addr.sin_addr.s_addr = INADDR_ANY; - rt_memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero)); - if (bind(telnet->server_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) - { - rt_kprintf("telnet: bind socket failed\n"); - return; - } - - if (listen(telnet->server_fd, TELNET_BACKLOG) == -1) - { - rt_kprintf("telnet: listen socket failed\n"); - return; - } - - /* register telnet device */ - telnet->device.type = RT_Device_Class_Char; - telnet->device.init = telnet_init; - telnet->device.open = telnet_open; - telnet->device.close = telnet_close; - telnet->device.read = telnet_read; - telnet->device.write = telnet_write; - telnet->device.control = telnet_control; - - /* no private */ - telnet->device.user_data = RT_NULL; - - /* register telnet device */ - rt_device_register(&telnet->device, "telnet", - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM); - - while (1) - { - rt_kprintf("telnet server waiting for connection\n"); - - /* grab new connection */ - if ((telnet->client_fd = accept(telnet->server_fd, (struct sockaddr * )&addr, &addr_size)) == -1) - { - continue; - } - - rt_kprintf("new telnet client(%s:%d) connection, switch console to telnet...\n", inet_ntoa(addr.sin_addr), addr.sin_port); - - /* process the new connection */ - /* set console */ - rt_console_set_device("telnet"); - /* set finsh device */ - finsh_set_device("telnet"); - - /* set init state */ - telnet->state = STATE_NORMAL; - - telnet->echo_mode = finsh_get_echo(); - /* disable echo mode */ - finsh_set_echo(0); - - while (1) - { - /* try to send all data in tx ringbuffer */ - send_to_client(telnet); - - /* do a rx procedure */ - if ((recv_len = recv(telnet->client_fd, recv_buf, RECV_BUF_LEN, 0)) > 0) - { - process_rx(telnet, recv_buf, recv_len); - } - else - { - /* close connection */ - client_close(telnet); - break; - } - } - } -} - -/* telnet server */ -void telnet_srv(void) -{ - rt_thread_t tid; - - if (telnet == RT_NULL) - { - rt_uint8_t *ptr; - - telnet = rt_malloc(sizeof(struct telnet_session)); - if (telnet == RT_NULL) - { - rt_kprintf("telnet: no memory\n"); - return; - } - /* init ringbuffer */ - ptr = rt_malloc(RX_BUFFER_SIZE); - if (ptr) - { - rt_ringbuffer_init(&telnet->rx_ringbuffer, ptr, RX_BUFFER_SIZE); - } - else - { - rt_kprintf("telnet: no memory\n"); - return; - } - ptr = rt_malloc(TX_BUFFER_SIZE); - if (ptr) - { - rt_ringbuffer_init(&telnet->tx_ringbuffer, ptr, TX_BUFFER_SIZE); - } - else - { - rt_kprintf("telnet: no memory\n"); - return; - } - /* create tx ringbuffer lock */ - telnet->tx_ringbuffer_lock = rt_mutex_create("telnet_tx", RT_IPC_FLAG_FIFO); - /* create rx ringbuffer lock */ - telnet->rx_ringbuffer_lock = rt_mutex_create("telnet_rx", RT_IPC_FLAG_FIFO); - - tid = rt_thread_create("telnet", telnet_thread, RT_NULL, 2048, 25, 5); - if (tid != RT_NULL) - rt_thread_startup(tid); - } - else - { - rt_kprintf("telnet: already running\n"); - } - -} - -#ifdef RT_USING_FINSH -#include -FINSH_FUNCTION_EXPORT(telnet_srv, startup telnet server); -#ifdef FINSH_USING_MSH -MSH_CMD_EXPORT(telnet_srv, startup telnet server) -#endif /* FINSH_USING_MSH */ -#endif /* RT_USING_FINSH */ diff --git a/components/net/netutils/README.md b/components/net/netutils/README.md new file mode 100644 index 0000000000..49545bab32 --- /dev/null +++ b/components/net/netutils/README.md @@ -0,0 +1 @@ +Some net utils which using standard interface such as BSD Sockets. \ No newline at end of file diff --git a/components/net/netutils/SConscript b/components/net/netutils/SConscript new file mode 100644 index 0000000000..853b94a857 --- /dev/null +++ b/components/net/netutils/SConscript @@ -0,0 +1,10 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +CPPPATH = [cwd] + +group = DefineGroup('LwIP', src, depend = ['RT_USING_NETUTILS'], CPPPATH = CPPPATH) + +Return('group') \ No newline at end of file diff --git a/components/net/netutils/telnet.c b/components/net/netutils/telnet.c new file mode 100644 index 0000000000..d5c127b713 --- /dev/null +++ b/components/net/netutils/telnet.c @@ -0,0 +1,391 @@ +#include +#include +#include +#include + +#include +#include + +#define TELNET_PORT 23 +#define TELNET_BACKLOG 5 +#define RX_BUFFER_SIZE 256 +#define TX_BUFFER_SIZE 4096 + +#define ISO_nl 0x0a +#define ISO_cr 0x0d + +#define STATE_NORMAL 0 +#define STATE_IAC 1 +#define STATE_WILL 2 +#define STATE_WONT 3 +#define STATE_DO 4 +#define STATE_DONT 5 +#define STATE_CLOSE 6 + +#define TELNET_IAC 255 +#define TELNET_WILL 251 +#define TELNET_WONT 252 +#define TELNET_DO 253 +#define TELNET_DONT 254 + +struct telnet_session +{ + struct rt_ringbuffer rx_ringbuffer; + struct rt_ringbuffer tx_ringbuffer; + + rt_mutex_t rx_ringbuffer_lock; + rt_mutex_t tx_ringbuffer_lock; + + struct rt_device device; + rt_int32_t server_fd; + rt_int32_t client_fd; + + /* telnet protocol */ + rt_uint8_t state; + rt_uint8_t echo_mode; + +}; + +static struct telnet_session* telnet; + +/* process tx data */ +static void send_to_client(struct telnet_session* telnet) +{ + rt_size_t length; + rt_uint8_t tx_buffer[32]; + + while (1) + { + rt_memset(tx_buffer, 0, sizeof(tx_buffer)); + rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); + /* get buffer from ringbuffer */ + length = rt_ringbuffer_get(&(telnet->tx_ringbuffer), tx_buffer, sizeof(tx_buffer)); + rt_mutex_release(telnet->tx_ringbuffer_lock); + + /* do a tx procedure */ + if (length > 0) + { + send(telnet->client_fd, tx_buffer, length, 0); + } + else break; + } +} + +/* send telnet option to remote */ +static void send_option_to_client(struct telnet_session* telnet, rt_uint8_t option, rt_uint8_t value) +{ + rt_uint8_t optbuf[4]; + + optbuf[0] = TELNET_IAC; + optbuf[1] = option; + optbuf[2] = value; + optbuf[3] = 0; + + rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); + rt_ringbuffer_put(&telnet->tx_ringbuffer, optbuf, 3); + rt_mutex_release(telnet->tx_ringbuffer_lock); + + send_to_client(telnet); +} + +/* process rx data */ +static void process_rx(struct telnet_session* telnet, rt_uint8_t *data, rt_size_t length) +{ + rt_size_t rx_length, index; + + for (index = 0; index < length; index ++) + { + switch(telnet->state) + { + case STATE_IAC: + if (*data == TELNET_IAC) + { + rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); + /* put buffer to ringbuffer */ + rt_ringbuffer_putchar(&(telnet->rx_ringbuffer), *data); + rt_mutex_release(telnet->rx_ringbuffer_lock); + + telnet->state = STATE_NORMAL; + } + else + { + /* set telnet state according to received package */ + switch (*data) + { + case TELNET_WILL: telnet->state = STATE_WILL; break; + case TELNET_WONT: telnet->state = STATE_WONT; break; + case TELNET_DO: telnet->state = STATE_DO; break; + case TELNET_DONT: telnet->state = STATE_DONT; break; + default: telnet->state = STATE_NORMAL; break; + } + } + break; + + /* don't option */ + case STATE_WILL: + case STATE_WONT: + send_option_to_client(telnet, TELNET_DONT, *data); + telnet->state = STATE_NORMAL; + break; + + /* won't option */ + case STATE_DO: + case STATE_DONT: + send_option_to_client(telnet, TELNET_WONT, *data); + telnet->state = STATE_NORMAL; + break; + + case STATE_NORMAL: + if (*data == TELNET_IAC) telnet->state = STATE_IAC; + else if (*data != '\r') /* ignore '\r' */ + { + rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); + /* put buffer to ringbuffer */ + rt_ringbuffer_putchar(&(telnet->rx_ringbuffer), *data); + rt_mutex_release(telnet->rx_ringbuffer_lock); + } + break; + } + + data ++; + } + + rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); + /* get total size */ + rx_length = rt_ringbuffer_data_len(&telnet->rx_ringbuffer); + rt_mutex_release(telnet->rx_ringbuffer_lock); + + /* indicate there are reception data */ + if ((rx_length > 0) && (telnet->device.rx_indicate != RT_NULL)) + telnet->device.rx_indicate(&telnet->device, rx_length); + + return; +} + +/* client close */ +static void client_close(struct telnet_session* telnet) +{ + /* set console */ + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); + /* set finsh device */ + finsh_set_device(RT_CONSOLE_DEVICE_NAME); + + /* close connection */ + closesocket(telnet->client_fd); + + /* restore shell option */ + finsh_set_echo(telnet->echo_mode); + + rt_kprintf("resume console to %s\n", RT_CONSOLE_DEVICE_NAME); +} + +/* RT-Thread Device Driver Interface */ +static rt_err_t telnet_init(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_err_t telnet_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +static rt_err_t telnet_close(rt_device_t dev) +{ + return RT_EOK; +} + +static rt_size_t telnet_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + rt_size_t result; + + /* read from rx ring buffer */ + rt_mutex_take(telnet->rx_ringbuffer_lock, RT_WAITING_FOREVER); + result = rt_ringbuffer_get(&(telnet->rx_ringbuffer), buffer, size); + rt_mutex_release(telnet->rx_ringbuffer_lock); + + return result; +} + +static rt_size_t telnet_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + const rt_uint8_t *ptr; + + ptr = (rt_uint8_t*) buffer; + + rt_mutex_take(telnet->tx_ringbuffer_lock, RT_WAITING_FOREVER); + while (size) + { + if (*ptr == '\n') + rt_ringbuffer_putchar(&telnet->tx_ringbuffer, '\r'); + + if (rt_ringbuffer_putchar(&telnet->tx_ringbuffer, *ptr) == 0) /* overflow */ + break; + ptr++; + size--; + } + rt_mutex_release(telnet->tx_ringbuffer_lock); + + /* send data to telnet client */ + send_to_client(telnet); + + return (rt_uint32_t) ptr - (rt_uint32_t) buffer; +} + +static rt_err_t telnet_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + return RT_EOK; +} + +/* telnet server thread entry */ +static void telnet_thread(void* parameter) +{ +#define RECV_BUF_LEN 64 + + struct sockaddr_in addr; + socklen_t addr_size; + rt_uint8_t recv_buf[RECV_BUF_LEN]; + rt_int32_t recv_len = 0; + + if ((telnet->server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) + { + rt_kprintf("telnet: create socket failed\n"); + return; + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(TELNET_PORT); + addr.sin_addr.s_addr = INADDR_ANY; + rt_memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero)); + if (bind(telnet->server_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) + { + rt_kprintf("telnet: bind socket failed\n"); + return; + } + + if (listen(telnet->server_fd, TELNET_BACKLOG) == -1) + { + rt_kprintf("telnet: listen socket failed\n"); + return; + } + + /* register telnet device */ + telnet->device.type = RT_Device_Class_Char; + telnet->device.init = telnet_init; + telnet->device.open = telnet_open; + telnet->device.close = telnet_close; + telnet->device.read = telnet_read; + telnet->device.write = telnet_write; + telnet->device.control = telnet_control; + + /* no private */ + telnet->device.user_data = RT_NULL; + + /* register telnet device */ + rt_device_register(&telnet->device, "telnet", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM); + + while (1) + { + rt_kprintf("telnet server waiting for connection\n"); + + /* grab new connection */ + if ((telnet->client_fd = accept(telnet->server_fd, (struct sockaddr * )&addr, &addr_size)) == -1) + { + continue; + } + + rt_kprintf("new telnet client(%s:%d) connection, switch console to telnet...\n", inet_ntoa(addr.sin_addr), addr.sin_port); + + /* process the new connection */ + /* set console */ + rt_console_set_device("telnet"); + /* set finsh device */ + finsh_set_device("telnet"); + + /* set init state */ + telnet->state = STATE_NORMAL; + + telnet->echo_mode = finsh_get_echo(); + /* disable echo mode */ + finsh_set_echo(0); + + while (1) + { + /* try to send all data in tx ringbuffer */ + send_to_client(telnet); + + /* do a rx procedure */ + if ((recv_len = recv(telnet->client_fd, recv_buf, RECV_BUF_LEN, 0)) > 0) + { + process_rx(telnet, recv_buf, recv_len); + } + else + { + /* close connection */ + client_close(telnet); + break; + } + } + } +} + +/* telnet server */ +void telnet_srv(void) +{ + rt_thread_t tid; + + if (telnet == RT_NULL) + { + rt_uint8_t *ptr; + + telnet = rt_malloc(sizeof(struct telnet_session)); + if (telnet == RT_NULL) + { + rt_kprintf("telnet: no memory\n"); + return; + } + /* init ringbuffer */ + ptr = rt_malloc(RX_BUFFER_SIZE); + if (ptr) + { + rt_ringbuffer_init(&telnet->rx_ringbuffer, ptr, RX_BUFFER_SIZE); + } + else + { + rt_kprintf("telnet: no memory\n"); + return; + } + ptr = rt_malloc(TX_BUFFER_SIZE); + if (ptr) + { + rt_ringbuffer_init(&telnet->tx_ringbuffer, ptr, TX_BUFFER_SIZE); + } + else + { + rt_kprintf("telnet: no memory\n"); + return; + } + /* create tx ringbuffer lock */ + telnet->tx_ringbuffer_lock = rt_mutex_create("telnet_tx", RT_IPC_FLAG_FIFO); + /* create rx ringbuffer lock */ + telnet->rx_ringbuffer_lock = rt_mutex_create("telnet_rx", RT_IPC_FLAG_FIFO); + + tid = rt_thread_create("telnet", telnet_thread, RT_NULL, 2048, 25, 5); + if (tid != RT_NULL) + rt_thread_startup(tid); + } + else + { + rt_kprintf("telnet: already running\n"); + } + +} + +#ifdef RT_USING_FINSH +#include +FINSH_FUNCTION_EXPORT(telnet_srv, startup telnet server); +#ifdef FINSH_USING_MSH +MSH_CMD_EXPORT(telnet_srv, startup telnet server) +#endif /* FINSH_USING_MSH */ +#endif /* RT_USING_FINSH */ -- cgit v1.3.1 From 871297747a1aea9c0f3868640856aab97377eea5 Mon Sep 17 00:00:00 2001 From: armink Date: Fri, 18 Aug 2017 11:52:12 +0800 Subject: [LWIP] Move net apps to `LwIP/src/apps`. --- components/net/lwip-2.0.2/apps/ping.c | 201 --------------------- components/net/lwip-2.0.2/apps/tftp_server.c | 83 --------- components/net/lwip-2.0.2/src/apps/README.md | 6 + components/net/lwip-2.0.2/src/apps/ping/ping.c | 201 +++++++++++++++++++++ .../net/lwip-2.0.2/src/apps/tftp/tftp_port.c | 87 +++++++++ 5 files changed, 294 insertions(+), 284 deletions(-) delete mode 100644 components/net/lwip-2.0.2/apps/ping.c delete mode 100644 components/net/lwip-2.0.2/apps/tftp_server.c create mode 100644 components/net/lwip-2.0.2/src/apps/README.md create mode 100644 components/net/lwip-2.0.2/src/apps/ping/ping.c create mode 100644 components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c (limited to 'components') diff --git a/components/net/lwip-2.0.2/apps/ping.c b/components/net/lwip-2.0.2/apps/ping.c deleted file mode 100644 index 4b934f0cac..0000000000 --- a/components/net/lwip-2.0.2/apps/ping.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * netutils: ping implementation - */ - -#include "lwip/opt.h" - -#include "lwip/mem.h" -#include "lwip/icmp.h" -#include "lwip/netif.h" -#include "lwip/sys.h" -#include "lwip/sockets.h" -#include "lwip/inet.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip.h" - -/** - * PING_DEBUG: Enable debugging for PING. - */ -#ifndef PING_DEBUG -#define PING_DEBUG LWIP_DBG_ON -#endif - -/** ping receive timeout - in milliseconds */ -#define PING_RCV_TIMEO rt_tick_from_millisecond(2000) -/** ping delay - in milliseconds */ -#define PING_DELAY rt_tick_from_millisecond(1000) - -/** ping identifier - must fit on a u16_t */ -#ifndef PING_ID -#define PING_ID 0xAFAF -#endif - -/** ping additional data size to include in the packet */ -#ifndef PING_DATA_SIZE -#define PING_DATA_SIZE 32 -#endif - -/* ping variables */ -static u16_t ping_seq_num; -struct _ip_addr -{ - rt_uint8_t addr0, addr1, addr2, addr3; -}; - -/** Prepare a echo ICMP request */ -static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) -{ - size_t i; - size_t data_len = len - sizeof(struct icmp_echo_hdr); - - ICMPH_TYPE_SET(iecho, ICMP_ECHO); - ICMPH_CODE_SET(iecho, 0); - iecho->chksum = 0; - iecho->id = PING_ID; - iecho->seqno = htons(++ping_seq_num); - - /* fill the additional data buffer with some data */ - for(i = 0; i < data_len; i++) - { - ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; - } - - iecho->chksum = inet_chksum(iecho, len); -} - -/* Ping using the socket ip */ -static err_t ping_send(int s, ip_addr_t *addr, int size) -{ - int err; - struct icmp_echo_hdr *iecho; - struct sockaddr_in to; - size_t ping_size = sizeof(struct icmp_echo_hdr) + size; - LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff); - - iecho = rt_malloc(ping_size); - if (iecho == RT_NULL) - { - return ERR_MEM; - } - - ping_prepare_echo(iecho, (u16_t)ping_size); - - to.sin_len = sizeof(to); - to.sin_family = AF_INET; - to.sin_addr.s_addr = addr->addr; - - err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to)); - rt_free(iecho); - - return (err == ping_size ? ERR_OK : ERR_VAL); -} - -static int ping_recv(int s, int *ttl) -{ - char buf[64]; - int fromlen = sizeof(struct sockaddr_in), len; - struct sockaddr_in from; - struct ip_hdr *iphdr; - struct icmp_echo_hdr *iecho; - - while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) - { - if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) - { - iphdr = (struct ip_hdr *)buf; - iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4)); - if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) - { - *ttl = iphdr->_ttl; - return len; - } - } - } - - return len; -} - -rt_err_t ping(char* target, rt_uint32_t times, rt_size_t size) -{ - int s, ttl, recv_len; - struct timeval timeout = { PING_RCV_TIMEO / RT_TICK_PER_SECOND, PING_RCV_TIMEO % RT_TICK_PER_SECOND }; - ip_addr_t ping_target; - rt_uint32_t send_times; - rt_tick_t recv_start_tick; - struct _ip_addr - { - rt_uint8_t addr0, addr1, addr2, addr3; - } *addr; - - send_times = 0; - ping_seq_num = 0; - - if(size == 0) - size = PING_DATA_SIZE; - - if (inet_aton(target, &ping_target) == 0) - { - rt_kprintf("ping: unknown host %s\n", target); - return -RT_ERROR; - } - addr = (struct _ip_addr*)&ping_target; - - if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) - { - rt_kprintf("ping: create socket failled\n"); - return -RT_ERROR; - } - - lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)); - - while (1) - { - if (ping_send(s, &ping_target, size) == ERR_OK) - { - recv_start_tick = rt_tick_get(); - if ((recv_len = ping_recv(s, &ttl)) >= 0) - { - rt_kprintf("%d bytes from %d.%d.%d.%d icmp_seq=%d ttl=%d time=%d ticks\n", recv_len, addr->addr0, - addr->addr1, addr->addr2, addr->addr3, send_times, ttl, rt_tick_get() - recv_start_tick); - } - else - { - rt_kprintf("From %d.%d.%d.%d icmp_seq=%d timeout\n", addr->addr0, addr->addr1, addr->addr2, - addr->addr3, send_times); - } - } - else - { - rt_kprintf("Send %d.%d.%d.%d - error\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3); - } - - send_times ++; - if (send_times >= times) break; /* send ping times reached, stop */ - - rt_thread_delay(PING_DELAY); /* take a delay */ - } - - lwip_close(s); - - return RT_EOK; -} -#ifdef RT_USING_FINSH -#include - -FINSH_FUNCTION_EXPORT(ping, ping network host); - -int cmd_ping(int argc, char **argv) -{ - if (argc == 1) - { - rt_kprintf("Please input: ping \n"); - } - else - { - ping(argv[1], 4, 0); - } - - return 0; -} -FINSH_FUNCTION_EXPORT_ALIAS(cmd_ping, __cmd_ping, ping network host); -#endif diff --git a/components/net/lwip-2.0.2/apps/tftp_server.c b/components/net/lwip-2.0.2/apps/tftp_server.c deleted file mode 100644 index f5667ef0ad..0000000000 --- a/components/net/lwip-2.0.2/apps/tftp_server.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * File : tftp_server.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team - * - * 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 2 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, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Change Logs: - * Date Author Notes - * 2017-08-17 armink first version. - */ - - -#include -#include -#include - -static struct tftp_context ctx; - -static void* tftp_open(const char* fname, const char* mode, u8_t write) -{ - int fd = -1; - - if (!rt_strcmp(mode, "octet")) - { - if (write) - { - fd = open(fname, O_WRONLY | O_CREAT, 0); - } - else - { - fd = open(fname, O_RDONLY, 0); - } - } - else - { - rt_kprintf("tftp: No support this mode(%s).", mode); - } - - return (void *) fd; -} - -static int tftp_write(void* handle, struct pbuf* p) -{ - int fd = (int) handle; - - return write(fd, p->payload, p->len); -} - -#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) -#include - -static void tftp_server(uint8_t argc, char **argv) -{ - ctx.open = tftp_open; - ctx.close = (void (*)(void *)) close; - ctx.read = (int (*)(void *, void *, int)) read; - ctx.write = tftp_write; - - if (tftp_init(&ctx) == ERR_OK) - { - rt_kprintf("TFTP server start successfully.\n"); - } - else - { - rt_kprintf("TFTP server start failed.\n"); - } -} -MSH_CMD_EXPORT(tftp_server, start tftp server.); - -#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */ diff --git a/components/net/lwip-2.0.2/src/apps/README.md b/components/net/lwip-2.0.2/src/apps/README.md new file mode 100644 index 0000000000..26670858c5 --- /dev/null +++ b/components/net/lwip-2.0.2/src/apps/README.md @@ -0,0 +1,6 @@ +Some net apps for current version LwIP. + +The RT-Thread develop team ported apps. It's easy to use it on finsh/msh. + +- ping +- tftp diff --git a/components/net/lwip-2.0.2/src/apps/ping/ping.c b/components/net/lwip-2.0.2/src/apps/ping/ping.c new file mode 100644 index 0000000000..4b934f0cac --- /dev/null +++ b/components/net/lwip-2.0.2/src/apps/ping/ping.c @@ -0,0 +1,201 @@ +/* + * netutils: ping implementation + */ + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/icmp.h" +#include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/sockets.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" + +/** + * PING_DEBUG: Enable debugging for PING. + */ +#ifndef PING_DEBUG +#define PING_DEBUG LWIP_DBG_ON +#endif + +/** ping receive timeout - in milliseconds */ +#define PING_RCV_TIMEO rt_tick_from_millisecond(2000) +/** ping delay - in milliseconds */ +#define PING_DELAY rt_tick_from_millisecond(1000) + +/** ping identifier - must fit on a u16_t */ +#ifndef PING_ID +#define PING_ID 0xAFAF +#endif + +/** ping additional data size to include in the packet */ +#ifndef PING_DATA_SIZE +#define PING_DATA_SIZE 32 +#endif + +/* ping variables */ +static u16_t ping_seq_num; +struct _ip_addr +{ + rt_uint8_t addr0, addr1, addr2, addr3; +}; + +/** Prepare a echo ICMP request */ +static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) +{ + size_t i; + size_t data_len = len - sizeof(struct icmp_echo_hdr); + + ICMPH_TYPE_SET(iecho, ICMP_ECHO); + ICMPH_CODE_SET(iecho, 0); + iecho->chksum = 0; + iecho->id = PING_ID; + iecho->seqno = htons(++ping_seq_num); + + /* fill the additional data buffer with some data */ + for(i = 0; i < data_len; i++) + { + ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; + } + + iecho->chksum = inet_chksum(iecho, len); +} + +/* Ping using the socket ip */ +static err_t ping_send(int s, ip_addr_t *addr, int size) +{ + int err; + struct icmp_echo_hdr *iecho; + struct sockaddr_in to; + size_t ping_size = sizeof(struct icmp_echo_hdr) + size; + LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff); + + iecho = rt_malloc(ping_size); + if (iecho == RT_NULL) + { + return ERR_MEM; + } + + ping_prepare_echo(iecho, (u16_t)ping_size); + + to.sin_len = sizeof(to); + to.sin_family = AF_INET; + to.sin_addr.s_addr = addr->addr; + + err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to)); + rt_free(iecho); + + return (err == ping_size ? ERR_OK : ERR_VAL); +} + +static int ping_recv(int s, int *ttl) +{ + char buf[64]; + int fromlen = sizeof(struct sockaddr_in), len; + struct sockaddr_in from; + struct ip_hdr *iphdr; + struct icmp_echo_hdr *iecho; + + while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) + { + if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) + { + iphdr = (struct ip_hdr *)buf; + iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4)); + if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) + { + *ttl = iphdr->_ttl; + return len; + } + } + } + + return len; +} + +rt_err_t ping(char* target, rt_uint32_t times, rt_size_t size) +{ + int s, ttl, recv_len; + struct timeval timeout = { PING_RCV_TIMEO / RT_TICK_PER_SECOND, PING_RCV_TIMEO % RT_TICK_PER_SECOND }; + ip_addr_t ping_target; + rt_uint32_t send_times; + rt_tick_t recv_start_tick; + struct _ip_addr + { + rt_uint8_t addr0, addr1, addr2, addr3; + } *addr; + + send_times = 0; + ping_seq_num = 0; + + if(size == 0) + size = PING_DATA_SIZE; + + if (inet_aton(target, &ping_target) == 0) + { + rt_kprintf("ping: unknown host %s\n", target); + return -RT_ERROR; + } + addr = (struct _ip_addr*)&ping_target; + + if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) + { + rt_kprintf("ping: create socket failled\n"); + return -RT_ERROR; + } + + lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)); + + while (1) + { + if (ping_send(s, &ping_target, size) == ERR_OK) + { + recv_start_tick = rt_tick_get(); + if ((recv_len = ping_recv(s, &ttl)) >= 0) + { + rt_kprintf("%d bytes from %d.%d.%d.%d icmp_seq=%d ttl=%d time=%d ticks\n", recv_len, addr->addr0, + addr->addr1, addr->addr2, addr->addr3, send_times, ttl, rt_tick_get() - recv_start_tick); + } + else + { + rt_kprintf("From %d.%d.%d.%d icmp_seq=%d timeout\n", addr->addr0, addr->addr1, addr->addr2, + addr->addr3, send_times); + } + } + else + { + rt_kprintf("Send %d.%d.%d.%d - error\n", addr->addr0, addr->addr1, addr->addr2, addr->addr3); + } + + send_times ++; + if (send_times >= times) break; /* send ping times reached, stop */ + + rt_thread_delay(PING_DELAY); /* take a delay */ + } + + lwip_close(s); + + return RT_EOK; +} +#ifdef RT_USING_FINSH +#include + +FINSH_FUNCTION_EXPORT(ping, ping network host); + +int cmd_ping(int argc, char **argv) +{ + if (argc == 1) + { + rt_kprintf("Please input: ping \n"); + } + else + { + ping(argv[1], 4, 0); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_ping, __cmd_ping, ping network host); +#endif diff --git a/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c b/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c new file mode 100644 index 0000000000..129cc7da17 --- /dev/null +++ b/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c @@ -0,0 +1,87 @@ +/* + * File : tftp_port.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017-08-17 armink first version. + */ + + +#include +#include +#include + +static struct tftp_context ctx; + +static void* tftp_open(const char* fname, const char* mode, u8_t write) +{ + int fd = -1; + + if (!rt_strcmp(mode, "octet")) + { + if (write) + { + fd = open(fname, O_WRONLY | O_CREAT, 0); + } + else + { + fd = open(fname, O_RDONLY, 0); + } + } + else + { + rt_kprintf("tftp: No support this mode(%s).", mode); + } + + return (void *) fd; +} + +static int tftp_write(void* handle, struct pbuf* p) +{ + int fd = (int) handle; + + return write(fd, p->payload, p->len); +} + +#if defined(RT_USING_FINSH) +#include + +static void tftp_server(uint8_t argc, char **argv) +{ + ctx.open = tftp_open; + ctx.close = (void (*)(void *)) close; + ctx.read = (int (*)(void *, void *, int)) read; + ctx.write = tftp_write; + + if (tftp_init(&ctx) == ERR_OK) + { + rt_kprintf("TFTP server start successfully.\n"); + } + else + { + rt_kprintf("TFTP server start failed.\n"); + } +} +FINSH_FUNCTION_EXPORT(tftp_server, start tftp server.); + +#if defined(FINSH_USING_MSH) +MSH_CMD_EXPORT(tftp_server, start tftp server.); +#endif /* defined(FINSH_USING_MSH) */ + +#endif /* defined(RT_USING_FINSH) */ -- cgit v1.3.1 From a97d70066b9626018801d87c7dba35939c005e94 Mon Sep 17 00:00:00 2001 From: armink Date: Fri, 18 Aug 2017 12:10:28 +0800 Subject: [LWIP] Add LwIP apps SConscript. --- components/net/lwip-2.0.2/src/apps/SConscript | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 components/net/lwip-2.0.2/src/apps/SConscript (limited to 'components') diff --git a/components/net/lwip-2.0.2/src/apps/SConscript b/components/net/lwip-2.0.2/src/apps/SConscript new file mode 100644 index 0000000000..2bc01cc16e --- /dev/null +++ b/components/net/lwip-2.0.2/src/apps/SConscript @@ -0,0 +1,13 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('tftp/*.c') + +if GetDepend(['RT_LWIP_ICMP', 'RT_LWIP_RAW']): + src += Glob('ping/*.c') + +CPPPATH = [cwd] + +group = DefineGroup('LwIP', src, depend = ['RT_USING_NETUTILS', 'RT_USING_LWIP202'], CPPPATH = CPPPATH) + +Return('group') \ No newline at end of file -- cgit v1.3.1