This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TCP SERVER example (not the ECHO SERVER) connection reset

Hi All,

My application needs to 10 tcp server connections. All the examples that I have found are about tcp server use "echo" but in my application I need to send messages at any time, not only when it receive something from the client. So, I' ve based my code on the "tcp_echoserver" source code and it works for a while and then all the connection reset (wireshark sniffer). In the most of time, when the connection reset, it can't be reconnect and the pcb->state show an invalid value. Some times the pc get stuck in a "for" loop at pbuf_cat function. (And doesn't matter is I use 1, 4 or 10 connections, the result is the same).

void pbuf_cat(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;

LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)",
((h != NULL) && (t != NULL)), return;);

/* proceed to last pbuf of chain */
for (p = h; p->next != NULL; p = p->next) {
/* add total length of second chain to all totals of first chain */
p->tot_len += t->tot_len;
}

...

I'm trying to run my code over the enet_lwip example, with the TM4C129 launchpad, and the problem persist.

I belive that the problem maybe the adaptation from the tcp_echoserver I've made, so i really apreciate if someone can take a look and see what is wrong, indicate another way to do the server or another souce code to buid a tcp server.

I'm problably using the wrong the global tcp_pcb pointer, but I really have tryied in may ways and the connection never became stable.

---------------------

The entire code is attached. Below are some parts of my code that I have doubts:

I use this code below to send messages,at any time, from the application:

if( tcp_server_pcb[vSession]->state == ESTABLISHED )
{
    indice = getPcbIndex( tcp_server_pcb[vSession]->local_port );

    switch( indice )
    {
        case 0:
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
	case 6:
	case 7:
	case 8:
	case 9:
	if(( tcp_server_pcb[vSession]->state == ESTABLISHED )&&( len ))
	{
	    if( tcp_write( tcp_server_pcb[vSession], buf , len, 0 ) == ERR_OK )
	    {
	         tcp_output( tcp_server_pcb[vSession] );
	    }
	    len = 0;
	}
	break;
    }
}


  and the changes that I've made:

//------------------------------------------------------------------------------------------------------------------------
//
//
//
// Parametros:
// Retorno:
//------------------------------------------------------------------------------------------------------------------------
static err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
{
err_t ret_err;
struct tcp_struct *es;
uint8_t pcbIndex;

  LWIP_UNUSED_ARG(arg);
  LWIP_UNUSED_ARG(err);

  /* set priority for the newly accepted tcp connection newpcb */
  tcp_setprio(newpcb, TCP_PRIO_MIN);

  /* allocate structure es to maintain tcp connection informations */
  es = (struct tcp_struct *)mem_malloc(sizeof(struct tcp_struct));
  if (es != NULL)
  {
    es->state = ES_ACCEPTED;
    es->pcb = newpcb;
    es->p = NULL;

    /* pass newly allocated es structure as argument to newpcb */
    tcp_arg(newpcb, es);

    /* initialize lwip tcp_recv callback function for newpcb  */
    tcp_recv(newpcb, tcp_recv_callback);

    /* initialize lwip tcp_err callback function for newpcb  */
    tcp_err(newpcb, tcp_error_callback);

    /* initialize lwip tcp_poll callback function for newpcb */
    tcp_poll(newpcb, tcp_poll_callback, 1);

    tcp_sent(newpcb, tcp_sent_callback);

    ret_err = ERR_OK;
  }
  else
  {
    /*  close tcp connection */
	  tcp_connection_close(newpcb, es);
    /* return memory error */
    ret_err = ERR_MEM;
  }



 // ADAPTED  ( I guess that the "newpcb" should already be pointing to one of the "tcp_server_pcb" but "tcp_server_pcb->state" never changes ???)
pcbIndex = getPcbIndex( newpcb->local_port ); if( pcbIndex != 0xFF ) tcp_server_pcb[pcbIndex] = newpcb; else tcp_connection_close(newpcb, es);
return ret_err; } //------------------------------------------------------------------------------------------------------------------------ // // // // Parametros: // Retorno: //------------------------------------------------------------------------------------------------------------------------ static err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { struct tcp_struct *es; err_t ret_err; char *pc = NULL; struct pbuf *ptr; u16_t plen; LWIP_ASSERT("arg != NULL",arg != NULL); es = (struct tcp_struct *)arg; /* if we receive an empty tcp frame from client => close connection */ if (p == NULL) { /* remote host closed connection */ es->state = ES_CLOSING; if(es->p == NULL) { /* we're done sending, close connection */ tcp_connection_close(tpcb, es); } else { /* we're not done yet */ /* acknowledge received packet */ tcp_sent(tpcb, tcp_sent_callback); /* send remaining data*/ tcp_send(tpcb, es); } ret_err = ERR_OK; } /* else : a non empty frame was received from client but for some reason err != ERR_OK */ else if(err != ERR_OK) { /* free received pbuf*/ 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; /* initialize LwIP tcp_sent callback function */ tcp_sent(tpcb, tcp_sent_callback); //--------------------------------------------------------------------------- // app get the msg if(es->p != NULL ) { es->p = p; pc = (char *)p->payload; if( es->p->len > 0 ) { app_getTcpPayloadMsg( tpcb->local_port, (uint8_t *)pc, p->len ); } } //-------------------------------------------- // adaptation from tcp_echo_server ptr = es->p; plen = ptr->len; es->p = ptr->next; if(es->p != NULL) pbuf_ref(es->p); pbuf_free(ptr); /* Update tcp window size to be advertized : should be called when received data (with the amount plen) has been processed by the application layer */ tcp_recved(tpcb, plen); ret_err = ERR_OK; } else if (es->state == ES_RECEIVED) { /* more data received from client and previous data has been already sent*/ if(es->p == NULL) { //--------------------------------------------------------------------------- // app get the msg es->p = p; pc = (char *)p->payload; if( es->p->len > 0 ) { app_getTcpPayloadMsg( tpcb->local_port, (uint8_t *)pc, p->len ); } //-------------------------------------------- // adaptation from tcp_echo_server ptr = es->p; plen = ptr->len; es->p = ptr->next; if(es->p != NULL) pbuf_ref(es->p); pbuf_free(ptr); /* Update tcp window size to be advertized : should be called when received data (with the amount plen) has been processed by the application layer */ tcp_recved(tpcb, plen); } 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; } /* data received when connection already closed */ else { /* Acknowledge data reception */ tcp_recved(tpcb, p->tot_len); /* free pbuf and do nothing */ es->p = NULL; pbuf_free(p); ret_err = ERR_OK; } return ret_err; }



and the orignal tcp_echoserver:
http://www1.coocox.org/repo/d0b2d0af-9aca-4f53-aac1-a03176e84769/src/TCP_Server/tcp_server.c.htm


enet_lwip tcpServer.rar

Thanks in advance.

  • Hello Amilton,

    Have you pulled in the LwIP patch from the Forum for memory leak. Also some posts mention increasing the Stack Size. You may want to weigh both the options.

    Regards
    Amit
  •     

    Hi Amit,

            I agree that it may be a problem of memory leak, once it works fine for a while, and saw some posts about that, and for the most, they mention somehow a mistake on using the lwip stack, what makes me belive that I can be doing something wrong in with the tcp_pcb, but I don't know what.
    I have increased the stack and the heap memory size to 16384 (in properties>build>arm link>basic options as well at enet_lwip_ccc.cmd __STACK_TOP), just to discard this possibility but the problem remains.

            After send some packets, the FaultISR at pbuf_cat occured again, as you can see in the image attached.

  • Hello Amilton,

    You may want to search out the patch file first.. This way we can be sure that memory leak from the original code is not affecting your application.

    Regards
    Amit