err_t echo_poll(void *arg, struct tcp_pcb *tpcb) { err_t ret_err; struct echo_state *es; es = 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_write(int fd, short revents, void *conn) { struct conn * c = (struct conn *) conn; evbuffer_write(c->buf, fd); printf("fd %d: wrote echo\n", fd); echo_close(conn); }
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 = 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; }