From ed1f9db86e0fa13043fd87c4b56447b20e2fa265 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 18 Sep 2011 22:10:14 +0200 Subject: [PATCH] switch to the netconn-based echo example --- kernel/echo.c | 381 ++++++++------------------------------------------ kernel/init.c | 2 +- 2 files changed, 62 insertions(+), 321 deletions(-) diff --git a/kernel/echo.c b/kernel/echo.c index 6be5e8bf..241f926f 100644 --- a/kernel/echo.c +++ b/kernel/echo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -24,340 +24,81 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * - * This file is part of and a contribution to the lwIP TCP/IP stack. - * - * Credits go to Adam Dunkels (and the current maintainers) of this software. - * - * Christiaan Simons rewrote this file to get a more stable echo example. - */ - -/** - * @file - * TCP echo server example using raw API. - * - * Echos all bytes sent by connecting client, - * and passively closes when client is done. + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels * */ #include -#include -#if defined(CONFIG_LWIP) -#include -#include -#include +#ifdef CONFIG_LWIP -static struct tcp_pcb *echo_pcb; +//#include "tcpecho.h" -enum echo_states +#include + +#if LWIP_NETCONN + +#include +#include + +/*-----------------------------------------------------------------------------------*/ +static void +tcpecho_thread(void *arg) { - ES_NONE = 0, - ES_ACCEPTED, - ES_RECEIVED, - ES_CLOSING -}; + struct netconn *conn, *newconn; + err_t err; + LWIP_UNUSED_ARG(arg); -struct echo_state -{ - u8_t state; - u8_t retries; - struct tcp_pcb *pcb; - /* pbuf (chain) to recycle */ - struct pbuf *p; -}; + /* Create a new connection identifier. */ + conn = netconn_new(NETCONN_TCP); -err_t echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err); -err_t echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); -void echo_error(void *arg, err_t err); -err_t echo_poll(void *arg, struct tcp_pcb *tpcb); -err_t echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len); -void echo_send(struct tcp_pcb *tpcb, struct echo_state *es); -void echo_close(struct tcp_pcb *tpcb, struct echo_state *es); + /* Bind connection to well known port number 7. */ + netconn_bind(conn, NULL, 7); + /* Tell connection to go into listening mode. */ + netconn_listen(conn); + + while (1) { + + /* Grab new connection. */ + err = netconn_accept(conn, &newconn); + /*printf("accepted new connection %p\n", newconn);*/ + /* Process the new connection. */ + if (err == ERR_OK) { + struct netbuf *buf; + void *data; + u16_t len; + + while ((err = netconn_recv(newconn, &buf)) == ERR_OK) { + /*printf("Recved\n");*/ + do { + netbuf_data(buf, &data, &len); + err = netconn_write(newconn, data, len, NETCONN_COPY); +#if 0 + if (err != ERR_OK) { + printf("tcpecho: netconn_write: error \"%s\"\n", lwip_strerr(err)); + } +#endif + } while (netbuf_next(buf) >= 0); + netbuf_delete(buf); + } + /*printf("Got EOF, looping\n");*/ + /* Close connection and discard connection identifier. */ + netconn_close(newconn); + netconn_delete(newconn); + } + } +} +/*-----------------------------------------------------------------------------------*/ void echo_init(void) { - echo_pcb = tcp_new(); - if (echo_pcb != NULL) - { - err_t err; - - err = tcp_bind(echo_pcb, IP_ADDR_ANY, 7); - if (err == ERR_OK) - { - echo_pcb = tcp_listen(echo_pcb); - tcp_accept(echo_pcb, echo_accept); - } - else - { - /* abort? output diagnostic? */ - kputs("echo: tcp_bind failed!\n"); - } - } - else - { - /* abort? output diagnostic? */ - kputs("echo: tcp_new failed!\n"); - } + sys_thread_new("tcpecho_thread", tcpecho_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); } +/*-----------------------------------------------------------------------------------*/ - -err_t -echo_accept(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - err_t ret_err; - struct echo_state *es; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(err); - - /* commonly observed practive to call tcp_setprio(), why? */ - tcp_setprio(newpcb, TCP_PRIO_MIN); - - es = (struct echo_state *)mem_malloc(sizeof(struct echo_state)); - if (es != NULL) - { - es->state = ES_ACCEPTED; - es->pcb = newpcb; - es->retries = 0; - es->p = NULL; - /* pass newly allocated es to our callbacks */ - tcp_arg(newpcb, es); - tcp_recv(newpcb, echo_recv); - tcp_err(newpcb, echo_error); - tcp_poll(newpcb, echo_poll, 0); - ret_err = ERR_OK; - } - else - { - ret_err = ERR_MEM; - } - return ret_err; -} - -err_t -echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) -{ - struct echo_state *es; - err_t ret_err; - - LWIP_ASSERT("arg != NULL",arg != NULL); - es = (struct echo_state *)arg; - if (p == NULL) - { - /* remote host closed connection */ - es->state = ES_CLOSING; - if(es->p == NULL) - { - /* we're done sending, close it */ - echo_close(tpcb, es); - } - else - { - /* we're not done yet */ - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - } - ret_err = ERR_OK; - } - else if(err != ERR_OK) - { - /* cleanup, for unkown reason */ - if (p != NULL) - { - es->p = NULL; - pbuf_free(p); - } - ret_err = err; - } - else if(es->state == ES_ACCEPTED) - { - /* first data chunk in p->payload */ - es->state = ES_RECEIVED; - /* store reference to incoming pbuf (chain) */ - es->p = p; - /* install send completion notifier */ - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - ret_err = ERR_OK; - } - else if (es->state == ES_RECEIVED) - { - /* read some more data */ - if(es->p == NULL) - { - es->p = p; - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - } - else - { - struct pbuf *ptr; - - /* chain pbufs to the end of what we recv'ed previously */ - ptr = es->p; - pbuf_chain(ptr,p); - } - ret_err = ERR_OK; - } - else if(es->state == ES_CLOSING) - { - /* odd case, remote side closing twice, trash data */ - tcp_recved(tpcb, p->tot_len); - es->p = NULL; - pbuf_free(p); - ret_err = ERR_OK; - } - else - { - /* unkown es->state, trash data */ - tcp_recved(tpcb, p->tot_len); - es->p = NULL; - pbuf_free(p); - ret_err = ERR_OK; - } - return ret_err; -} - -void -echo_error(void *arg, err_t err) -{ - struct echo_state *es; - - LWIP_UNUSED_ARG(err); - - es = (struct echo_state *)arg; - if (es != NULL) - { - mem_free(es); - } -} - -err_t -echo_poll(void *arg, struct tcp_pcb *tpcb) -{ - err_t ret_err; - struct echo_state *es; - - es = (struct echo_state *)arg; - if (es != NULL) - { - if (es->p != NULL) - { - /* there is a remaining pbuf (chain) */ - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - } - else - { - /* no remaining pbuf (chain) */ - if(es->state == ES_CLOSING) - { - echo_close(tpcb, es); - } - } - ret_err = ERR_OK; - } - else - { - /* nothing to be done */ - tcp_abort(tpcb); - ret_err = ERR_ABRT; - } - return ret_err; -} - -err_t -echo_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - struct echo_state *es; - - LWIP_UNUSED_ARG(len); - - es = (struct echo_state *)arg; - es->retries = 0; - - if(es->p != NULL) - { - /* still got pbufs to send */ - tcp_sent(tpcb, echo_sent); - echo_send(tpcb, es); - } - else - { - /* no more pbufs to send */ - if(es->state == ES_CLOSING) - { - echo_close(tpcb, es); - } - } - return ERR_OK; -} - -void -echo_send(struct tcp_pcb *tpcb, struct echo_state *es) -{ - struct pbuf *ptr; - err_t wr_err = ERR_OK; - - while ((wr_err == ERR_OK) && - (es->p != NULL) && - (es->p->len <= tcp_sndbuf(tpcb))) - { - ptr = es->p; - - /* enqueue data for transmission */ - wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1); - if (wr_err == ERR_OK) - { - u16_t plen; - u8_t freed; - - plen = ptr->len; - /* continue with next pbuf in chain (if any) */ - es->p = ptr->next; - if(es->p != NULL) - { - /* new reference! */ - pbuf_ref(es->p); - } - /* chop first pbuf from chain */ - do - { - /* try hard to free pbuf */ - freed = pbuf_free(ptr); - } - while(freed == 0); - /* we can read more data now */ - tcp_recved(tpcb, plen); - } - else if(wr_err == ERR_MEM) - { - /* we are low on memory, try later / harder, defer to poll */ - es->p = ptr; - } - else - { - /* other problem ?? */ - } - } -} - -void -echo_close(struct tcp_pcb *tpcb, struct echo_state *es) -{ - tcp_arg(tpcb, NULL); - tcp_sent(tpcb, NULL); - tcp_recv(tpcb, NULL); - tcp_err(tpcb, NULL); - tcp_poll(tpcb, NULL, 0); - - if (es != NULL) - { - mem_free(es); - } - tcp_close(tpcb); -} +#endif /* LWIP_NETCONN */ #endif diff --git a/kernel/init.c b/kernel/init.c index ac76dde6..eaf3b2b8 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -229,7 +229,7 @@ int initd(void* arg) #endif // start echo and/or netio server - //echo_init(); + echo_init(); //netio_init(); #endif