[Live-devel] Bug in GroupsockHelper makeSocketBlocking()

Jeff Shanab jshanab at jfs-tech.com
Fri Aug 18 13:44:04 PDT 2017


I have tested for over 100 hours with instrumentation to confirm the code
is being used.
This happens during rtsp-over-http and appears to be where the device is
not expecting Receiver Reports back on the GET connection.

RTPInterface calls the following function in GroupsockHelper.cpp with 500
milliseconds  whenever it sends rtcp Receiver Reports and the buffer has
gotten full. Wireshark confirms "TCP zero window"

Boolean makeSocketBlocking(int sock, unsigned
writeTimeoutInMilliseconds) {  Boolean result;#if defined(__WIN32__)
|| defined(_WIN32)  unsigned long arg = 0;  result = ioctlsocket(sock,
FIONBIO, &arg) == 0;#elif defined(VXWORKS)  int arg = 0;  result =
ioctl(sock, FIONBIO, (int)&arg) == 0;#else  int curFlags = fcntl(sock,
F_GETFL, 0);  result = fcntl(sock, F_SETFL, curFlags&(~O_NONBLOCK)) >=
0;#endif  if (writeTimeoutInMilliseconds > 0) {#ifdef SO_SNDTIMEO
struct timeval tv;    tv.tv_sec = writeTimeoutInMilliseconds/1000;
tv.tv_usec = (writeTimeoutInMilliseconds%1000)*1000;
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof
tv);#endif  }  return result;}

The setsockopt in windows for SO_SNDTIMEO expects DWORD, an unsigned long.

However, timeval is 2 signed longs and the 500ms leaves the first long 0.

When Windows sees the 0 it waits FOREVER.


Test code :

Boolean makeSocketBlocking(UsageEnvironment& env, int sock, unsigned
writeTimeoutInMilliseconds) {
    Boolean result;
#if defined(__WIN32__) || defined(_WIN32)
    unsigned long arg = 0;
    result = ioctlsocket(sock, FIONBIO, &arg) == 0;
#elif defined(VXWORKS)
    int arg = 0;
    result = ioctl(sock, FIONBIO, (int)&arg) == 0;
#else
    int curFlags = fcntl(sock, F_GETFL, 0);
    result = fcntl(sock, F_SETFL, curFlags&(~O_NONBLOCK)) >= 0;
#endif

    int success = 0;
    if (writeTimeoutInMilliseconds > 0) {
#ifdef SO_SNDTIMEO
#if defined(__WIN32__) || defined(_WIN32)
        DWORD msto = (DWORD)writeTimeoutInMilliseconds;
        success = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char
*)&msto, sizeof(msto) );
#else
        struct timeval tv;
        tv.tv_sec = writeTimeoutInMilliseconds/1000;
        tv.tv_usec = (writeTimeoutInMilliseconds%1000)*1000;
        success = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char
*)&tv, sizeof tv);
#endif
        if (success < 0)
            socketErr(env, "Failed to set SO_SNDTIMEO ");
#endif
    }

    return result;
}

(UsageEnvironment arg added to signature only to allow socketErr call.)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20170818/e9ed3f20/attachment-0001.html>


More information about the live-devel mailing list