summaryrefslogtreecommitdiffstats
path: root/net/Socket.cpp
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2019-03-30 14:06:16 +0000
committerMichael Meeks <michael.meeks@collabora.com>2019-03-30 16:51:06 +0000
commit81a27e26aab2fed410310c3cda46090b8a2c8a50 (patch)
tree0a169f24afec0bc5bebbbd1e5c0921c64912641b /net/Socket.cpp
parentCrop socket buffer removal to socket buffer size & warn. (diff)
downloadonline-81a27e26aab2fed410310c3cda46090b8a2c8a50.tar.gz
online-81a27e26aab2fed410310c3cda46090b8a2c8a50.zip
Switch local prisoner sockets to abstract UDS
Unix Domain Sockets are inaddressable remotely, and more efficient, as well as allowing future SCM_CREDENTIALS / SCM_RIGHTS. Change-Id: Ia2472260f75feb43e9022cdfa0fe005ccd489454
Diffstat (limited to 'net/Socket.cpp')
-rw-r--r--net/Socket.cpp136
1 files changed, 108 insertions, 28 deletions
diff --git a/net/Socket.cpp b/net/Socket.cpp
index 8d2cd3533c..a1762352e5 100644
--- a/net/Socket.cpp
+++ b/net/Socket.cpp
@@ -37,10 +37,20 @@ int SocketPoll::DefaultPollTimeoutMs = 5000;
std::atomic<bool> SocketPoll::InhibitThreadChecks(false);
std::atomic<bool> Socket::InhibitThreadChecks(false);
+#define SOCKET_ABSTRACT_UNIX_NAME "0loolwsd-"
+
int Socket::createSocket(Socket::Type type)
{
#if !MOBILEAPP
- int domain = type == Type::IPv4 ? AF_INET : AF_INET6;
+ int domain;
+ switch (type)
+ {
+ case Type::IPv4: domain = AF_INET; break;
+ case Type::IPv6: domain = AF_INET6; break;
+ case Type::All: domain = AF_INET6; break;
+ case Type::Unix: domain = AF_UNIX; break;
+ default: assert (false); break;
+ }
return socket(domain, SOCK_STREAM | SOCK_NONBLOCK, 0);
#else
return fakeSocketSocket();
@@ -190,14 +200,9 @@ void SocketPoll::wakeupWorld()
}
void SocketPoll::insertNewWebSocketSync(
-#if !MOBILEAPP
- const Poco::URI &uri,
-#else
- int peerSocket,
-#endif
- const std::shared_ptr<SocketHandlerInterface>& websocketHandler)
+ const Poco::URI &uri,
+ const std::shared_ptr<SocketHandlerInterface>& websocketHandler)
{
-#if !MOBILEAPP
LOG_INF("Connecting to " << uri.getHost() << " : " << uri.getPort() << " : " << uri.getPath());
// FIXME: put this in a ClientSocket class ?
@@ -247,24 +252,7 @@ void SocketPoll::insertNewWebSocketSync(
if (socket)
{
LOG_DBG("Connected to client websocket " << uri.getHost() << " #" << socket->getFD());
-
- // cf. WebSocketHandler::upgradeToWebSocket (?)
- // send Sec-WebSocket-Key: <hmm> ... Sec-WebSocket-Protocol: chat, Sec-WebSocket-Version: 13
-
- std::ostringstream oss;
- oss << "GET " << uri.getPathAndQuery() << " HTTP/1.1\r\n"
- "Connection:Upgrade\r\n"
- "User-Foo: Adminbits\r\n"
- "Sec-WebSocket-Key:fxTaWTEMVhq1PkWsMoLxGw==\r\n"
- "Upgrade:websocket\r\n"
- "Accept-Language:en\r\n"
- "Cache-Control:no-cache\r\n"
- "Pragma:no-cache\r\n"
- "Sec-WebSocket-Version:13\r\n"
- "User-Agent: " << WOPI_AGENT_STRING << "\r\n"
- "\r\n";
- socket->send(oss.str());
- websocketHandler->onConnect(socket);
+ clientRequestWebsocketUpgrade(socket, websocketHandler, uri.getPathAndQuery());
insertNewSocket(socket);
}
else
@@ -282,7 +270,71 @@ void SocketPoll::insertNewWebSocketSync(
}
else
LOG_ERR("Failed to lookup client websocket host '" << uri.getHost() << "' skipping");
-#else
+}
+
+// should this be a static method in the WebsocketHandler(?)
+void SocketPoll::clientRequestWebsocketUpgrade(const std::shared_ptr<StreamSocket>& socket,
+ const std::shared_ptr<SocketHandlerInterface>& websocketHandler,
+ const std::string &pathAndQuery)
+{
+ // cf. WebSocketHandler::upgradeToWebSocket (?)
+ // send Sec-WebSocket-Key: <hmm> ... Sec-WebSocket-Protocol: chat, Sec-WebSocket-Version: 13
+
+ LOG_TRC("Requesting upgrade of websocket at path " << pathAndQuery << " #" << socket->getFD());
+
+ std::ostringstream oss;
+ oss << "GET " << pathAndQuery << " HTTP/1.1\r\n"
+ "Connection:Upgrade\r\n"
+ "User-Foo: Adminbits\r\n"
+ "Sec-WebSocket-Key:fxTaWTEMVhq1PkWsMoLxGw==\r\n"
+ "Upgrade:websocket\r\n"
+ "Accept-Language:en\r\n"
+ "Cache-Control:no-cache\r\n"
+ "Pragma:no-cache\r\n"
+ "Sec-WebSocket-Version:13\r\n"
+ "User-Agent: " << WOPI_AGENT_STRING << "\r\n"
+ "\r\n";
+ socket->send(oss.str());
+ websocketHandler->onConnect(socket);
+}
+
+void SocketPoll::insertNewUnixSocket(
+ const std::string &location,
+ const std::string &pathAndQuery,
+ const std::shared_ptr<SocketHandlerInterface>& websocketHandler)
+{
+ int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
+
+ struct sockaddr_un addrunix;
+ std::memset(&addrunix, 0, sizeof(addrunix));
+ addrunix.sun_family = AF_UNIX;
+ addrunix.sun_path[0] = '\0'; // abstract name
+ memcpy(&addrunix.sun_path[1], location.c_str(), location.length());
+
+ int res = connect(fd, (const struct sockaddr *)&addrunix, sizeof(addrunix));
+ if (fd < 0 || (res < 0 && errno != EINPROGRESS))
+ {
+ LOG_ERR("Failed to connect to unix socket at " << location);
+ ::close(fd);
+ }
+ else
+ {
+ std::shared_ptr<StreamSocket> socket;
+ socket = StreamSocket::create<StreamSocket>(fd, true, websocketHandler);
+ if (socket)
+ {
+ LOG_DBG("Connected to local UDS " << location << " #" << socket->getFD());
+ clientRequestWebsocketUpgrade(socket, websocketHandler, pathAndQuery);
+ insertNewSocket(socket);
+ }
+ }
+}
+
+#if MOBILEAPP
+void SocketPoll::insertNewFakeSocket(
+ int peerSocket,
+ const std::shared_ptr<SocketHandlerInterface>& websocketHandler)
+{
LOG_INF("Connecting to " << peerSocket);
int fd = fakeSocketSocket();
int res = fakeSocketConnect(fd, peerSocket);
@@ -307,8 +359,8 @@ void SocketPoll::insertNewWebSocketSync(
fakeSocketClose(fd);
}
}
-#endif
}
+#endif
void ServerSocket::dumpState(std::ostream& os)
{
@@ -390,6 +442,7 @@ bool ServerSocket::bind(Type type, int port)
int rc;
+ assert (_type != Socket::Type::Unix);
if (_type == Socket::Type::IPv4)
{
struct sockaddr_in addrv4;
@@ -430,6 +483,33 @@ bool ServerSocket::bind(Type type, int port)
#endif
}
+/// Returns true on success only.
+std::string LocalServerSocket::bind()
+{
+#if !MOBILEAPP
+ int rc;
+ struct sockaddr_un addrunix;
+ do
+ {
+ std::memset(&addrunix, 0, sizeof(addrunix));
+ addrunix.sun_family = AF_UNIX;
+ std::memcpy(addrunix.sun_path, SOCKET_ABSTRACT_UNIX_NAME, sizeof(SOCKET_ABSTRACT_UNIX_NAME));
+ addrunix.sun_path[0] = '\0'; // abstract name
+
+ std::string rand = Util::rng::getFilename(8);
+ memcpy(addrunix.sun_path + sizeof(SOCKET_ABSTRACT_UNIX_NAME) - 1, rand.c_str(), 8);
+
+ rc = ::bind(getFD(), (const sockaddr *)&addrunix, sizeof(struct sockaddr_un));
+ LOG_TRC("Bind to location " << std::string(&addrunix.sun_path[1]) <<
+ " result - " << rc << "errno: " << ((rc >= 0) ? "no error" : ::strerror(errno)));
+ } while (rc < 0 && errno == EADDRINUSE);
+
+ if (rc >= 0)
+ return std::string(&addrunix.sun_path[1]);
+#endif
+ return "";
+}
+
#if !MOBILEAPP
bool StreamSocket::parseHeader(const char *clientName,