3
votes

I have developed a tcp server in my one embedded device using lwip+freeRTOS. Now this is the flow how I communicate with other device ( Other device has Linux system and let's name it LinuxDevice) using my device ( let's name it lwipDevice)

  1. Send UDP packet from lwipDevice to LinuxDevice to initiate that I am ready to share my information.

  2. Now LinuxDevice recognises this message successfully and sends one TCP packet (which contain command) to lwipDevice for telling to send its information.

  3. But at lwipDevice side this message is not received. So it will not send any response to LinuxDevice. And steps 1-3 repeat again and again.

Now this is code of lwipDevice for TCP server:

long server_sock=-1;
#define FAIL 1
#define PASS 0
int CreateTcpServerSocket(long *pSock, int port)
{
    struct sockaddr_in   sin;
    int addrlen = sizeof(sin);
    int   e;
    struct linger linger;
    linger.l_linger=0;
    int i = 1;

    *pSock = socket(AF_INET, SOCK_STREAM, 0);

    if (*pSock == -1)
    {
        printf("*** createTcpSercerSocket:open sock error,port %d\n",port);
        return FAIL;
    }

    memset((char *)&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_len = sizeof(sin);
    sin.sin_addr.s_addr = htonl(INADDR_ANY);   /* wildcard IP address */
    sin.sin_port = htons(port);


    e = bind(*pSock, (struct sockaddr*)&sin, addrlen);
    if (e != 0)
    {
        printf("error %d binding tcp listen on port\n");
        closesocket(*pSock);
        *pSock = -1;
        return FAIL;
    }

    lwip_ioctl(*pSock, FIONBIO, &i); //Set Non blocking mode

    e = listen(*pSock, 2);

    if (e != 0)
    {
        pprintf("error :listen on TCP server\n");
        closesocket(*pSock);
        *pSock = -1;
        return FAIL;
    }

    return PASS;
}
void vTCPTask(void *parm)
{
    struct sockaddr client; /* for BSDish accept() call */
    int clientsize;
    long sock;

    if(CreateTcpServerSocket(&server_sock, 8000) == FAIL) //Here server created successfully
    {
        printf("Fail to create server!!!!!\n");
        server_sock=-1;
    }

    while(1)
    {
        // some code for other stuff

        sock= accept(server_sock, &client, &clientsize); //This line always fails and reurn -1

        if(sock != -1)
        {
            printf("accepted socket:\n\n");
            //...now receive data from client....
            // send some data to client
        }

        // some code for other stuff

        //sleep for 15 seconds
    }

}
int main()
{

    //...initilization of lwip stack
    //....some more code
    //...................

    xTaskCreate(vTCPTask, (signed char const *) "tcptask",
    356, NULL, 3, (xTaskHandle *)&xNotifierServiceTaskHandle);


    /* Start the scheduler */
    vTaskStartScheduler();

    return 1
}

I have checked lwip_accept function and it will return from this condition:

  if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0))
  {
    LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
    sock_set_errno(sock, EWOULDBLOCK);
    return -1;
  }

EDIT:

I know that netconn_is_nonblocking(sock->conn) condition will always true because have set socket in non blocking mode. But why sock->rcvevent always zero even LinuxDevice already send packet to it?

EDIT:

For testing purpose have commented all other stuff code in task ( see //some code for other stuff ) then socket is successfully accepted and i try to receive the packet but now problem is it's now stuck in lwip_recvfrom function (Note: LinuxDevice continue send packets). So have further debug more and found that it stuck in function sys_arch_mbox_fetch ( function call flow:: lwip_recvfrom\netconn_recv\netconn_recv_data\sys_arch_mbox_fetch).

Does anyone have an idea what is wrong with it?

3
There's a comment about a 15 second sleep in there. That's quite a lot. Are you sure that wasn't the culprit that causes odd behavior ? What about the other stuff you commented out ? Narrow it down. And make sure none of that other stuff actually hangs/blocks for a long time.nos
@nos You are right sleep for 15 seconds is too long. every thing is working when i commented code as explained in question (except sleep for 15 seconds). And issue looks like related to delay in switching task.Jayesh Bhoi

3 Answers

1
votes

You have configured the socket as non-blocking, so the accept() call will never block. If there is no incoming connection pending it will return the EWOULDBLOCK error code, which is what you see.

1
votes

Finally I figured out what is cause of issue.

In lwipopt.h file there is macro like

/* Non-static memory, used with DMA pool */
#ifdef __CODE_RED
#define MEM_SIZE                        (6 * 1024) 
#else
#define MEM_SIZE                        (24 * 1024)
#endif

I have defined _CODE_RED. So MEM_SIZE will (6 * 1024). Now when i change that memory size to (16 * 1024) then everything working fine.

Now all the time connection accepted and after that i am able to send/recv tcp packets successfully.

0
votes

Where do you set rcvevent? Your code doesn't reveal it. I suppose it's the result of recv (or read). Reading from a non-blocking that has no available data (haven't yet received data) returns EAGAIN, which evaluates true in your rcvevent <= 0 condition. You have to manually check these specific error codes.

But why sock->rcvevent always zero even LinuxDevice already send packet to it?

Have you tried sending data with telnet or netcat to be sure the error is in your server and not in your client? Maybe your client is not sending to the correct destination, or something else.