You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by em...@apache.org on 2021/09/01 09:05:08 UTC
[thrift] branch master updated: Added support for Unix domain
sockets on Windows
This is an automated email from the ASF dual-hosted git repository.
emmenlau pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/thrift.git
The following commit(s) were added to refs/heads/master by this push:
new 18bf591 Added support for Unix domain sockets on Windows
new 0f5aebb Merge pull request #2327 from BioDataAnalysis/bda_add_domain_sockets_for_windows
18bf591 is described below
commit 18bf59153521a813296142929308fbb0c3f4db65
Author: Mario Emmenlauer <me...@biodataanalysis.de>
AuthorDate: Thu Nov 19 13:54:12 2020 +0100
Added support for Unix domain sockets on Windows
---
lib/cpp/src/thrift/transport/SocketCommon.cpp | 25 ++--------
lib/cpp/src/thrift/transport/SocketCommon.h | 11 +++--
lib/cpp/src/thrift/transport/TServerSocket.cpp | 63 ++++++++++++++------------
lib/cpp/src/thrift/transport/TSocket.cpp | 20 ++++----
lib/cpp/src/thrift/windows/config.h | 15 ++++++
5 files changed, 69 insertions(+), 65 deletions(-)
diff --git a/lib/cpp/src/thrift/transport/SocketCommon.cpp b/lib/cpp/src/thrift/transport/SocketCommon.cpp
index 570f39a..0b064c7 100644
--- a/lib/cpp/src/thrift/transport/SocketCommon.cpp
+++ b/lib/cpp/src/thrift/transport/SocketCommon.cpp
@@ -19,32 +19,17 @@
* @author: David Suárez <da...@gmail.com>
*/
-#ifndef THRIFT_SOCKETCOMMON_H
-#define THRIFT_SOCKETCOMMON_H
-
-#ifndef _WIN32
-
-#include <thrift/thrift-config.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-
-#include <string>
-
+#include <thrift/transport/SocketCommon.h>
#include <thrift/transport/PlatformSocket.h>
#include <thrift/transport/TTransportException.h>
#include <thrift/TOutput.h>
+#include <cstring>
+
namespace apache {
namespace thrift {
namespace transport {
-
socklen_t fillUnixSocketAddr(struct sockaddr_un& address, std::string& path)
{
// abstract namespace socket ?
@@ -79,7 +64,3 @@ socklen_t fillUnixSocketAddr(struct sockaddr_un& address, std::string& path)
}
}
} // apache::thrift::transport
-
-#endif // _WIN32
-
-#endif //THRIFT_SOCKETCOMMON_H
diff --git a/lib/cpp/src/thrift/transport/SocketCommon.h b/lib/cpp/src/thrift/transport/SocketCommon.h
index 78839c4..bd1032f 100644
--- a/lib/cpp/src/thrift/transport/SocketCommon.h
+++ b/lib/cpp/src/thrift/transport/SocketCommon.h
@@ -22,17 +22,20 @@
#ifndef THRIFT_SOCKETCOMMON_H
#define THRIFT_SOCKETCOMMON_H
-#ifndef _WIN32
-
#include <thrift/thrift-config.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
+#ifdef HAVE_AF_UNIX_H
+#include <afunix.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
#include <string>
@@ -46,6 +49,4 @@ socklen_t fillUnixSocketAddr(struct sockaddr_un& address, std::string& path);
}
} // apache::thrift::transport
-#endif // _WIN32
-
#endif //THRIFT_SOCKETCOMMON_H
diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp
index 671cabc..8d6e7ef 100644
--- a/lib/cpp/src/thrift/transport/TServerSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp
@@ -249,26 +249,28 @@ void TServerSocket::setInterruptableChildren(bool enable) {
}
void TServerSocket::_setup_sockopts() {
-
- // Set THRIFT_NO_SOCKET_CACHING to prevent 2MSL delay on accept
- int one = 1;
- if (-1 == setsockopt(serverSocket_,
- SOL_SOCKET,
- THRIFT_NO_SOCKET_CACHING,
- cast_sockopt(&one),
- sizeof(one))) {
-// ignore errors coming out of this setsockopt on Windows. This is because
-// SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't
-// want to force servers to be an admin.
-#ifndef _WIN32
- int errno_copy = THRIFT_GET_SOCKET_ERROR;
- GlobalOutput.perror("TServerSocket::listen() setsockopt() THRIFT_NO_SOCKET_CACHING ",
- errno_copy);
- close();
- throw TTransportException(TTransportException::NOT_OPEN,
- "Could not set THRIFT_NO_SOCKET_CACHING",
- errno_copy);
-#endif
+ if (!isUnixDomainSocket()) {
+ // Set THRIFT_NO_SOCKET_CACHING to prevent 2MSL delay on accept.
+ // This does not work with Domain sockets on most platforms. And
+ // on Windows it completely breaks the socket. Therefore do not
+ // use this on Domain sockets.
+ int one = 1;
+ if (-1 == setsockopt(serverSocket_,
+ SOL_SOCKET,
+ THRIFT_NO_SOCKET_CACHING,
+ cast_sockopt(&one),
+ sizeof(one))) {
+ // NOTE: SO_EXCLUSIVEADDRUSE socket option can only be used by members
+ // of the Administrators security group on Windows XP and earlier. But
+ // we do not target WinXP anymore so no special checks required.
+ int errno_copy = THRIFT_GET_SOCKET_ERROR;
+ GlobalOutput.perror("TServerSocket::listen() setsockopt() THRIFT_NO_SOCKET_CACHING ",
+ errno_copy);
+ close();
+ throw TTransportException(TTransportException::NOT_OPEN,
+ "Could not set THRIFT_NO_SOCKET_CACHING",
+ errno_copy);
+ }
}
// Set TCP buffer sizes
@@ -437,12 +439,9 @@ void TServerSocket::listen() {
_setup_sockopts();
_setup_unixdomain_sockopts();
-/*
- * TODO: seems that windows now support unix sockets,
- * see: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
- */
-#ifndef _WIN32
-
+ // Windows supports Unix domain sockets since it ships the header
+ // HAVE_AF_UNIX_H (see https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/)
+#if (!defined(_WIN32) || defined(HAVE_AF_UNIX_H))
struct sockaddr_un address;
socklen_t structlen = fillUnixSocketAddr(address, path_);
@@ -454,7 +453,7 @@ void TServerSocket::listen() {
// use short circuit evaluation here to only sleep if we need to
} while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0));
#else
- GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on windows", -99);
+ GlobalOutput.perror("TServerSocket::open() Unix Domain socket path not supported on this version of Windows", -99);
throw TTransportException(TTransportException::NOT_OPEN,
" Unix Domain socket path not supported");
#endif
@@ -537,9 +536,14 @@ void TServerSocket::listen() {
if (retries > retryLimit_) {
char errbuf[1024];
if (isUnixDomainSocket()) {
- THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TServerSocket::listen() PATH %s", path_.c_str());
+#ifdef _WIN32
+ THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TServerSocket::listen() Could not bind to domain socket path %s, error %d", path_.c_str(), WSAGetLastError());
+#else
+ // Fixme: This does not currently handle abstract domain sockets:
+ THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TServerSocket::listen() Could not bind to domain socket path %s", path_.c_str());
+#endif
} else {
- THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TServerSocket::listen() BIND %d", port_);
+ THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TServerSocket::listen() Could not bind to port %d", port_);
}
GlobalOutput(errbuf);
close();
@@ -664,6 +668,7 @@ shared_ptr<TTransport> TServerSocket::acceptImpl() {
}
shared_ptr<TSocket> client = createSocket(clientSocket);
+ client->setPath(path_);
if (sendTimeout_ > 0) {
client->setSendTimeout(sendTimeout_);
}
diff --git a/lib/cpp/src/thrift/transport/TSocket.cpp b/lib/cpp/src/thrift/transport/TSocket.cpp
index 1542c08..9991fd6 100644
--- a/lib/cpp/src/thrift/transport/TSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSocket.cpp
@@ -331,23 +331,18 @@ void TSocket::openConnection(struct addrinfo* res) {
// Connect the socket
int ret;
if (isUnixDomainSocket()) {
-
-/*
- * TODO: seems that windows now support unix sockets,
- * see: https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
- */
-#ifndef _WIN32
-
+ // Windows supports Unix domain sockets since it ships the header
+ // HAVE_AF_UNIX_H (see https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/)
+#if (!defined(_WIN32) || defined(HAVE_AF_UNIX_H))
struct sockaddr_un address;
socklen_t structlen = fillUnixSocketAddr(address, path_);
ret = connect(socket_, (struct sockaddr*)&address, structlen);
#else
- GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on windows", -99);
+ GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on this version of Windows", -99);
throw TTransportException(TTransportException::NOT_OPEN,
" Unix Domain socket path not supported");
#endif
-
} else {
ret = connect(socket_, res->ai_addr, static_cast<int>(res->ai_addrlen));
}
@@ -804,6 +799,13 @@ void TSocket::setKeepAlive(bool keepAlive) {
return;
}
+#ifdef _WIN32
+ if (isUnixDomainSocket()) {
+ // Windows Domain sockets do not support SO_KEEPALIVE.
+ return;
+ }
+#endif
+
int value = keepAlive_;
int ret
= setsockopt(socket_, SOL_SOCKET, SO_KEEPALIVE, const_cast_sockopt(&value), sizeof(value));
diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h
index a218d90..ce10c55 100644
--- a/lib/cpp/src/thrift/windows/config.h
+++ b/lib/cpp/src/thrift/windows/config.h
@@ -59,6 +59,7 @@
// windows
#include <Winsock2.h>
#include <ws2tcpip.h>
+
#ifndef __MINGW32__
#ifdef _WIN32_WCE
#pragma comment(lib, "Ws2.lib")
@@ -72,4 +73,18 @@
#endif
#endif // __MINGW32__
+// Replicate the logic of afunix.h on Windows (the header is only present on
+// newer Windows SDKs)
+#ifdef HAVE_AF_UNIX_H
+#include <afunix.h>
+#else
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX 108
+#endif
+typedef struct sockaddr_un {
+ ADDRESS_FAMILY sun_family; // AF_UNIX
+ char sun_path[UNIX_PATH_MAX]; // pathname
+} SOCKADDR_UN, *PSOCKADDR_UN;
+#endif // HAVE_AF_UNIX_H
+
#endif // _THRIFT_WINDOWS_CONFIG_H_