3

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?

Jayesh Bhoi
  • 24,694
  • 15
  • 58
  • 73
  • 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 Aug 08 '14 at 09:10
  • @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 Aug 08 '14 at 09:30

3 Answers3

1

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.

stathisv
  • 489
  • 2
  • 7
  • If i remove non-blocking state then it will in always blocking state and not giving chance to other task for initiate communication. Also if i first start communication then also in blocking state even other device send TCP packet. – Jayesh Bhoi Jul 28 '14 at 04:54
  • It is OK to use non-blocking state. What you see is not really an error, it just means that the lwIP stack does not receive the connection request from the 'LinuxDevice'. Have you run any other tests to make sure that lwIP talks OK with your Ethernet driver and receives/sends data? – stathisv Jul 28 '14 at 09:45
  • Yes.i have tested `ping` command.Have successfully able to `ping` my lwipdevice from linux device. – Jayesh Bhoi Jul 28 '14 at 09:50
1

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.

Jayesh Bhoi
  • 24,694
  • 15
  • 58
  • 73
0

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.

jweyrich
  • 31,198
  • 5
  • 66
  • 97
  • Thanks for reply. `rcevent` is set in `event_callback`. You can check in `socket.c` file if you have source of lwip. Also have tested using hercules utility to connect with server but it also fails. – Jayesh Bhoi Aug 07 '14 at 12:30