pupnp / pupnp

libupnp: Build UPnP-compliant control points, devices, and bridges on several operating systems.
https://pupnp.github.io/pupnp
BSD 3-Clause "New" or "Revised" License
349 stars 114 forks source link

The mini server socket lost packets。 miniserver.c #434

Open ezhoulike opened 6 months ago

ezhoulike commented 6 months ago

When receiving web messages on certain platforms, the TCP_NODELAY algorithm is not disabled, resulting in packet loss

static void web_server_accept(SOCKET lsock, fd_set *set) {

ifdef INTERNAL_WEB_SERVER

SOCKET asock;
socklen_t clientLen;
struct sockaddr_storage clientAddr;
char errorBuffer[ERROR_BUFFER_LEN];

if (lsock != INVALID_SOCKET && FD_ISSET(lsock, set)) {
    printf("web_server_accept server fd = %d\n", lsock);
    clientLen = sizeof(clientAddr);
    asock = accept(
        lsock, (struct sockaddr *)&clientAddr, &clientLen);
    if (asock == INVALID_SOCKET) {
        strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
        UpnpPrintf(UPNP_INFO,
            MSERV,
            __FILE__,
            __LINE__,
            "miniserver: Error in accept(): %s\n",
            errorBuffer);
    } else {
        schedule_request_job(
            asock, (struct sockaddr *)&clientAddr);
    }
}

endif / INTERNAL_WEB_SERVER /

}

ihgkhjk

ezhoulike commented 6 months ago

need set TCP_NODELAY

setsockopt(asock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on))

ingo-h commented 6 months ago

Hi Angel, you wrote:

When receiving web messages on certain platforms, the TCP_NODELAY algorithm is not disabled, resulting in packet loss

that means TCP_NODELAY is enabled.

I'm pretty sure that it is disabled by default and I cannot grep any setsockopt in all sources that enable it. What make you think that it is enabled and why then you try to enable it again with setsockopt?

ezhoulike commented 6 months ago

Dear ingo-h, This is not an inevitable question. During the DLNA screencasting process, the mobile application instantly sent two Soap requests (which were confirmed by grabbing the tcp packet), and the device only called back one operation. The problem occurs on a certain android operating system platform.

ingo-h commented 6 months ago

Hi Angel, I try to understand your problem. The TCP_NODELAY algorithm is disabled by default and not enabled by any 'setsockopt'. What make you think that it is enabled?

ezhoulike commented 6 months ago

Dear ingo-h, My personal understanding is that the Nagle algorithm should be enabled by default. What I mean is to explicitly disable the Nagle algorithm through the interface setsockopt.

ingo-h commented 6 months ago

Ah, now ..., some confusion with "set TCP_NODELAY" means "disable Nagle" and vice versa. You mean "the TCP_NODELAY is disabled".

man 7 tcp says:

TCP_NODELAY If set, disable the Nagle algorithm. This means that segments are always sent as soon as possible, even if there is only a small amount of data. When not set, data is buffered until there is a sufficient amount to send out, thereby avoiding the frequent sending of small packets, which results in poor utilization of the network. This option is overridden by TCP_CORK; however, setting this option forces an explicit flush of pending output, even if TCP_CORK is currently set.

I would be worried about permanently using this option, especially for a library. It would have a negative impact on the user's network.

Do you see any way to reproduce the problem in a test environment?

ezhoulike commented 6 months ago

Dear ingo-h, image

As shown in the figure, the requests sent by the control point in sequence are #Stop, #SetAVTransportURL, #Play, #SetAVTransport, #Play, #Stop.

The above result is that screencasting fails. The reason is that the control point requests Play, but there is no reply from the device. The control point tries again and still fails. This is the problem I encountered.

ezhoulike commented 6 months ago

What I can confirm is that there is no #Play request in the device callback UPNP CONTROL ACTION REQUEST type, and I did not see #Play twice.