From 581675818b32d660bed6933102632e9f63292fde Mon Sep 17 00:00:00 2001 From: Norman Princen Date: Tue, 12 May 2020 09:57:38 -0700 Subject: [PATCH 1/8] Minimize sendUDP and readUDP Socket Timeout Delays sendUDP and readUDP were using longer than necessary socket timeouts that may add to process time delay and stuttering. They were also using different values between Window and Linux/Mac. The timeouts are now standardized for all versions. --- C/src/xplaneConnect.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/C/src/xplaneConnect.c b/C/src/xplaneConnect.c index d48ac02..11cc6a8 100755 --- a/C/src/xplaneConnect.c +++ b/C/src/xplaneConnect.c @@ -117,13 +117,16 @@ XPCSocket aopenUDP(const char *xpIP, unsigned short xpPort, unsigned short port) exit(EXIT_FAILURE); } - // Set timeout to 100ms + // Set socket timeout period for sendUDP to 1 millisecond + // Without this, playback may become choppy due to process blocking #ifdef _WIN32 - DWORD timeout = 100; + // Minimum socket timeout in Windows is 1 millisecond (0 makes it blocking) + DWORD timeout = 1; #else + // Set socket timeout to 1 millisecond = 1,000 microseconds to make it the same as Windows (0 makes it blocking) struct timeval timeout; timeout.tv_sec = 0; - timeout.tv_usec = 250000; + timeout.tv_usec = 1000; #endif if (setsockopt(sock.sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0) { @@ -188,13 +191,13 @@ int sendUDP(XPCSocket sock, char buffer[], int len) /// \returns If an error occurs, a negative number. Otherwise, the number of bytes read. int readUDP(XPCSocket sock, char buffer[], int len) { -#ifdef _WIN32 - // Windows readUDP needs the select command- minimum timeout is 1ms. - // Without this playback becomes choppy + // For readUDP, use the select command - minimum timeout of 0 makes it polling. + // Without this, playback may become choppy due to process blocking // Definitions FD_SET stReadFDS; FD_SET stExceptFDS; + struct timeval tv; // Setup for Select FD_ZERO(&stReadFDS); @@ -202,9 +205,10 @@ int readUDP(XPCSocket sock, char buffer[], int len) FD_ZERO(&stExceptFDS); FD_SET(sock.sock, &stExceptFDS); - struct timeval tv; + // Set timeout period for select to 0.05 sec = 50 milliseconds = 50,000 microseconds (0 makes it polling) + // TO DO - This could be set to 0 if a message handling system were implemented, like in the plugin. tv.tv_sec = 0; - tv.tv_usec = 100000; + tv.tv_usec = 50000; // Select Command int status = select(-1, &stReadFDS, (FD_SET*)0, &stExceptFDS, &tv); @@ -218,11 +222,9 @@ int readUDP(XPCSocket sock, char buffer[], int len) // No data return 0; } + + // If no error: Read Data status = recv(sock.sock, buffer, len, 0); -#else - // For apple or linux-just read - will timeout in 0.5 ms - int status = (int)recv(sock.sock, buffer, len, 0); -#endif if (status < 0) { printError("readUDP", "Error reading socket"); From d2486dd73b95f0130c095734794a1fa7ce707874 Mon Sep 17 00:00:00 2001 From: Norman Princen Date: Tue, 12 May 2020 10:25:01 -0700 Subject: [PATCH 2/8] Minimize SendTo and Read Socket Timeout Delays SendTo and Read were using longer than necessary socket timeouts that may add to process time delay and stuttering. They were also using different values between Window and Linux/Mac. The timeouts are now standardized for all versions and coded in the same manner as the xplaneConnect.c functions. --- xpcPlugin/UDPSocket.cpp | 54 ++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/xpcPlugin/UDPSocket.cpp b/xpcPlugin/UDPSocket.cpp index 6eaf3e1..440a6a6 100644 --- a/xpcPlugin/UDPSocket.cpp +++ b/xpcPlugin/UDPSocket.cpp @@ -56,22 +56,25 @@ namespace XPC return; } - // Set Timout - int usTimeOut = 500; - + // Set timeout period for SendTo to 1 millisecond + // Without this, playback may become choppy due to process blocking #ifdef _WIN32 - DWORD msTimeOutWin = 1; // Minimum socket timeout in Windows is 1ms - if(setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&msTimeOutWin, sizeof(msTimeOutWin)) != 0) + // Minimum socket timeout in Windows is 1 millisecond (0 makes it blocking) + DWORD timeout = 1; +#else + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 1000; +#endif + if (setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0) { +#ifdef _WIN32 int err = WSAGetLastError(); Log::FormatLine(LOG_ERROR, tag, "ERROR: Failed to set timeout. (Error code %i)", err); - } #else - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = usTimeOut; - setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); + Log::WriteLine(LOG_ERROR, tag, "ERROR: Failed to set timeout."); #endif + } } UDPSocket::~UDPSocket() @@ -87,11 +90,9 @@ namespace XPC int UDPSocket::Read(unsigned char* dst, int maxLen, sockaddr* recvAddr) const { socklen_t recvaddrlen = sizeof(*recvAddr); - int status = 0; -#ifdef _WIN32 - // Windows readUDP needs the select command- minimum timeout is 1ms. - // Without this playback becomes choppy + // For Read, use the select command - minimum timeout of 0 makes it polling. + // Without this, playback may become choppy due to process blocking // Definitions FD_SET stReadFDS; @@ -103,27 +104,40 @@ namespace XPC FD_SET(sock, &stReadFDS); FD_ZERO(&stExceptFDS); FD_SET(sock, &stExceptFDS); + + // Set timeout period for select to 0 to poll the socket tv.tv_sec = 0; - tv.tv_usec = 250; + tv.tv_usec = 0; // Select Command - int result = select(-1, &stReadFDS, (FD_SET *)0, &stExceptFDS, &tv); - if (result == SOCKET_ERROR) + int status = select(-1, &stReadFDS, (FD_SET *)0, &stExceptFDS, &tv); + if (status < 0) { +#ifdef _WIN32 int err = WSAGetLastError(); Log::FormatLine(LOG_ERROR, tag, "ERROR: Select failed. (Error code %i)", err); +#else + Log::WriteLine(LOG_ERROR, tag, "ERROR: Select failed."); +#endif + return -1; } - if (result <= 0) // No Data or error + if (result == 0) { + // No data return -1; } // If no error: Read Data status = recvfrom(sock, (char*)dst, maxLen, 0, recvAddr, &recvaddrlen); + if (status < 0) + { +#ifdef _WIN32 + int err = WSAGetLastError(); + Log::FormatLine(LOG_ERROR, tag, "ERROR: Receive failed. (Error code %i)", err); #else - // For apple or linux-just read - will timeout in 0.5 ms - status = (int)recvfrom(sock, dst, 5000, 0, recvAddr, &recvaddrlen); + Log::WriteLine(LOG_ERROR, tag, "ERROR: Receive failed."); #endif + } return status; } From 138c738ba07f89782971aa4f44713129305a6879 Mon Sep 17 00:00:00 2001 From: Norman Princen Date: Tue, 12 May 2020 12:23:07 -0700 Subject: [PATCH 3/8] Minimize SendTo and Read Socket Timeout Delays SendTo and Read were using longer than necessary socket timeouts that may add to process time delay and stuttering. They were also using different values between Window and Linux/Mac. The timeouts are now standardized for all versions and coded in the same manner as the xplaneConnect.c functions. --- xpcPlugin/UDPSocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpcPlugin/UDPSocket.cpp b/xpcPlugin/UDPSocket.cpp index 440a6a6..110bcea 100644 --- a/xpcPlugin/UDPSocket.cpp +++ b/xpcPlugin/UDPSocket.cpp @@ -121,7 +121,7 @@ namespace XPC #endif return -1; } - if (result == 0) + if (status == 0) { // No data return -1; From 121b3c92f87dcfcd191cd7b6d41864b72a4baa32 Mon Sep 17 00:00:00 2001 From: Norman Princen Date: Tue, 12 May 2020 13:15:38 -0700 Subject: [PATCH 4/8] Include sys/select.h for Linux and Mac --- xpcPlugin/UDPSocket.h | 1 + 1 file changed, 1 insertion(+) diff --git a/xpcPlugin/UDPSocket.h b/xpcPlugin/UDPSocket.h index a1ee920..398d8ea 100644 --- a/xpcPlugin/UDPSocket.h +++ b/xpcPlugin/UDPSocket.h @@ -14,6 +14,7 @@ #include #include #include +#include #endif From e2a6820d341b7e9e74bb8c1e4994716da5b435f6 Mon Sep 17 00:00:00 2001 From: Norman Princen Date: Tue, 12 May 2020 13:18:47 -0700 Subject: [PATCH 5/8] Minimize SendTo and Read Socket Timeout Delays SendTo and Read were using longer than necessary socket timeouts that may add to process time delay and stuttering. They were also using different values between Window and Linux/Mac. The timeouts are now standardized for all versions and coded in the same manner as the xplaneConnect.c functions. --- xpcPlugin/UDPSocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpcPlugin/UDPSocket.cpp b/xpcPlugin/UDPSocket.cpp index 110bcea..9defeb0 100644 --- a/xpcPlugin/UDPSocket.cpp +++ b/xpcPlugin/UDPSocket.cpp @@ -110,7 +110,7 @@ namespace XPC tv.tv_usec = 0; // Select Command - int status = select(-1, &stReadFDS, (FD_SET *)0, &stExceptFDS, &tv); + int status = select(-1, &stReadFDS, (FD_SET*)0, &stExceptFDS, &tv); if (status < 0) { #ifdef _WIN32 From bb16ab9d94d2afcc6dd6231482340ebea77ba8fe Mon Sep 17 00:00:00 2001 From: Norman Princen Date: Tue, 12 May 2020 13:25:10 -0700 Subject: [PATCH 6/8] Added includes for Linux and Mac socket select functions --- xpcPlugin/UDPSocket.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xpcPlugin/UDPSocket.h b/xpcPlugin/UDPSocket.h index 398d8ea..ea86930 100644 --- a/xpcPlugin/UDPSocket.h +++ b/xpcPlugin/UDPSocket.h @@ -13,8 +13,9 @@ #include #include #include +#include +#include #include -#include #endif From 4241599ad772268831ef652de753b2a5c2711207 Mon Sep 17 00:00:00 2001 From: Norman Princen Date: Tue, 12 May 2020 18:58:29 -0700 Subject: [PATCH 7/8] Minimize sendUDP and readUDP Socket Timeout Delays sendUDP and readUDP were using longer than necessary socket timeouts that may add to process time delay and stuttering. They were also using different values between Window and Linux/Mac. The timeouts are now standardized for all versions. --- C/src/xplaneConnect.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/C/src/xplaneConnect.c b/C/src/xplaneConnect.c index 11cc6a8..208ed7f 100755 --- a/C/src/xplaneConnect.c +++ b/C/src/xplaneConnect.c @@ -195,9 +195,9 @@ int readUDP(XPCSocket sock, char buffer[], int len) // Without this, playback may become choppy due to process blocking // Definitions - FD_SET stReadFDS; - FD_SET stExceptFDS; - struct timeval tv; + fd_set stReadFDS; + fd_set stExceptFDS; + struct timeval timeout; // Setup for Select FD_ZERO(&stReadFDS); @@ -207,11 +207,11 @@ int readUDP(XPCSocket sock, char buffer[], int len) // Set timeout period for select to 0.05 sec = 50 milliseconds = 50,000 microseconds (0 makes it polling) // TO DO - This could be set to 0 if a message handling system were implemented, like in the plugin. - tv.tv_sec = 0; - tv.tv_usec = 50000; + timeout.tv_sec = 0; + timeout.tv_usec = 50000; // Select Command - int status = select(-1, &stReadFDS, (FD_SET*)0, &stExceptFDS, &tv); + int status = select(sock.sock+1, &stReadFDS, NULL, &stExceptFDS, &timeout); if (status < 0) { printError("readUDP", "Select command error"); From 1f78a23351faebc85fe7f82ddcd92a329852792a Mon Sep 17 00:00:00 2001 From: Norman Princen Date: Tue, 12 May 2020 19:06:28 -0700 Subject: [PATCH 8/8] Minimize SendTo and Read Socket Timeout Delays SendTo and Read were using longer than necessary socket timeouts that may add to process time delay and stuttering. They were also using different values between Window and Linux/Mac. The timeouts are now standardized for all versions and coded in the same manner as the xplaneConnect.c functions. --- xpcPlugin/UDPSocket.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/xpcPlugin/UDPSocket.cpp b/xpcPlugin/UDPSocket.cpp index 9defeb0..5925ebe 100644 --- a/xpcPlugin/UDPSocket.cpp +++ b/xpcPlugin/UDPSocket.cpp @@ -95,9 +95,9 @@ namespace XPC // Without this, playback may become choppy due to process blocking // Definitions - FD_SET stReadFDS; - FD_SET stExceptFDS; - timeval tv; + fd_set stReadFDS; + fd_set stExceptFDS; + struct timeval timeout; // Setup for Select FD_ZERO(&stReadFDS); @@ -106,11 +106,11 @@ namespace XPC FD_SET(sock, &stExceptFDS); // Set timeout period for select to 0 to poll the socket - tv.tv_sec = 0; - tv.tv_usec = 0; + timeout.tv_sec = 0; + timeout.tv_usec = 0; // Select Command - int status = select(-1, &stReadFDS, (FD_SET*)0, &stExceptFDS, &tv); + int status = select(sock+1, &stReadFDS, NULL, &stExceptFDS, &timeout); if (status < 0) { #ifdef _WIN32