PrivateNetworkServices example with DHCP+TCP server - simulating a client reboot scenario

C G 46 Reputation points
2020-07-24T17:23:22.473+00:00

I am using the PrivateNetworkServices sample code as found on GitHub: https://github.com/Azure/azure-sphere-samples/tree/master/Samples/PrivateNetworkServices

I have a client device connected and it receives a local IP address from the DHCP server. I can then send data using the TCP port.

Now, I wanted to simulate a failure scenario where the client device reboots.

The result from the reboot is that client device connects and receives its IP address again.

The client then connects to the TCP server again, but this time when it tries to send data the Azure Sphere logs an error message:

INFO: TCP server: Closing incoming client connection: only one client supported at a time.

and then closes the client's TCP connection.

How do I resolve this?

Azure Sphere
Azure Sphere
An Azure internet of things security solution including hardware, operating system, and cloud components.
167 questions
{count} votes

1 answer

Sort by: Most helpful
  1. C G 46 Reputation points
    2020-07-24T18:04:09.33+00:00

    Well, I thought to hack away and see what happens. Maybe there is a better way of doing it as I am still learning...

    After 1 runtime exception when I thought a "free (serverState->clientFd);" might do the trick, I came to with this code, which works but I am ending up with "localFd" that increments after each client reboot (that can actually be a good thing as gives you a failure indicator or reboot counter).

    EDIT: Sorted (I think). Adding in a close(serverState->clientFd); solves the socket increment problem (localFd).

    static void HandleListenEvent(EventData *eventData)
    {
        EchoServer_ServerState *serverState =
            EventDataToServerState(eventData, offsetof(EchoServer_ServerState, listenEvent));
        int localFd = -1;
    
        do {
            // Create a new accepted socket to connect to the client.
            // The newly-accepted sockets should be opened in non-blocking mode, and use
            // EPOLLIN and EPOLLOUT to transfer data.
            struct sockaddr in_addr;
            socklen_t sockLen = sizeof(in_addr);
    
            // If there is already a client, then we close that first 
            // - this works as only one client IP address is handled via DHCP.
            if (serverState->clientFd >= 0) {
                UnregisterEventHandlerFromEpoll(serverState->epollFd, serverState->clientFd);
                serverState->epollInEnabled = false;
    close(serverState->clientFd);
                serverState->clientFd = -1;
                Log_Debug(
                    "INFO: TCP server: Closing old client connection as only one client supported "
                    "at a time. A new connection will be issued.\n");
            }
    
            localFd = accept4(serverState->listenFd, &in_addr, &sockLen, SOCK_NONBLOCK | SOCK_CLOEXEC);
    
            if (localFd == -1) {
                ReportError("accept");
                break;
            }
    
            Log_Debug("INFO: TCP server: Accepted client connection (fd %d).\n", localFd);
    
            // Socket opened successfully, so transfer ownership to EchoServer_ServerState object.
            serverState->clientFd = localFd;
            localFd = -1;
    
            LaunchRead(serverState);
        } while (0);
    
        close(localFd);
    }
    
    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.