From ea07afcc0b9c5f65292e9b9094ee4ee8db194c28 Mon Sep 17 00:00:00 2001 From: Benjamin Sergeant Date: Sat, 29 Dec 2018 21:53:33 -0800 Subject: [PATCH] can create a socket from a fd --- ixwebsocket/IXSocket.cpp | 4 +- ixwebsocket/IXSocket.h | 2 +- ixwebsocket/IXSocketAppleSSL.cpp | 2 +- ixwebsocket/IXSocketAppleSSL.h | 2 +- ixwebsocket/IXSocketOpenSSL.cpp | 2 +- ixwebsocket/IXSocketOpenSSL.h | 2 +- ixwebsocket/IXWebSocketTransport.cpp | 109 +++++++++++++++++---------- ixwebsocket/IXWebSocketTransport.h | 7 ++ 8 files changed, 82 insertions(+), 48 deletions(-) diff --git a/ixwebsocket/IXSocket.cpp b/ixwebsocket/IXSocket.cpp index 3a2330b6..1a2a2a8d 100644 --- a/ixwebsocket/IXSocket.cpp +++ b/ixwebsocket/IXSocket.cpp @@ -37,8 +37,8 @@ namespace ix { - Socket::Socket() : - _sockfd(-1) + Socket::Socket(int fd) : + _sockfd(fd) { } diff --git a/ixwebsocket/IXSocket.h b/ixwebsocket/IXSocket.h index ea16160d..96cfc040 100644 --- a/ixwebsocket/IXSocket.h +++ b/ixwebsocket/IXSocket.h @@ -22,7 +22,7 @@ namespace ix public: using OnPollCallback = std::function; - Socket(); + Socket(int fd = -1); virtual ~Socket(); void configure(); diff --git a/ixwebsocket/IXSocketAppleSSL.cpp b/ixwebsocket/IXSocketAppleSSL.cpp index bd60533d..9aec505e 100644 --- a/ixwebsocket/IXSocketAppleSSL.cpp +++ b/ixwebsocket/IXSocketAppleSSL.cpp @@ -143,7 +143,7 @@ std::string getSSLErrorDescription(OSStatus status) namespace ix { - SocketAppleSSL::SocketAppleSSL() : + SocketAppleSSL::SocketAppleSSL(int fd) : Socket(fd), _sslContext(nullptr) { ; diff --git a/ixwebsocket/IXSocketAppleSSL.h b/ixwebsocket/IXSocketAppleSSL.h index bcf8b23f..e9796e72 100644 --- a/ixwebsocket/IXSocketAppleSSL.h +++ b/ixwebsocket/IXSocketAppleSSL.h @@ -19,7 +19,7 @@ namespace ix class SocketAppleSSL : public Socket { public: - SocketAppleSSL(); + SocketAppleSSL(int fd = -1); ~SocketAppleSSL(); virtual bool connect(const std::string& host, diff --git a/ixwebsocket/IXSocketOpenSSL.cpp b/ixwebsocket/IXSocketOpenSSL.cpp index b6c34617..7f8f181c 100644 --- a/ixwebsocket/IXSocketOpenSSL.cpp +++ b/ixwebsocket/IXSocketOpenSSL.cpp @@ -74,7 +74,7 @@ SSL *openssl_create_connection(SSL_CTX *ctx, int socket) namespace ix { - SocketOpenSSL::SocketOpenSSL() : + SocketOpenSSL::SocketOpenSSL(int fd) : Socket(fd), _ssl_connection(nullptr), _ssl_context(nullptr) { diff --git a/ixwebsocket/IXSocketOpenSSL.h b/ixwebsocket/IXSocketOpenSSL.h index 7e360a02..ca4dd88d 100644 --- a/ixwebsocket/IXSocketOpenSSL.h +++ b/ixwebsocket/IXSocketOpenSSL.h @@ -22,7 +22,7 @@ namespace ix class SocketOpenSSL : public Socket { public: - SocketOpenSSL(); + SocketOpenSSL(int fd = -1); ~SocketOpenSSL(); virtual bool connect(const std::string& host, diff --git a/ixwebsocket/IXWebSocketTransport.cpp b/ixwebsocket/IXWebSocketTransport.cpp index bc345cd1..cc45c132 100644 --- a/ixwebsocket/IXWebSocketTransport.cpp +++ b/ixwebsocket/IXWebSocketTransport.cpp @@ -145,6 +145,59 @@ namespace ix std::cout << "-------------------------------" << std::endl; } + std::pair WebSocketTransport::parseHttpHeaders() + { + WebSocketHttpHeaders headers; + + char line[256]; + int i; + + while (true) + { + int colon = 0; + + for (i = 0; + i < 2 || (i < 255 && line[i-2] != '\r' && line[i-1] != '\n'); + ++i) + { + if (!readByte(line+i)) + { + return std::make_pair(false, headers); + } + + if (line[i] == ':' && colon == 0) + { + colon = i; + } + } + if (line[0] == '\r' && line[1] == '\n') + { + break; + } + + // line is a single header entry. split by ':', and add it to our + // header map. ignore lines with no colon. + if (colon > 0) + { + line[i] = '\0'; + std::string lineStr(line); + // colon is ':', colon+1 is ' ', colon+2 is the start of the value. + // i is end of string (\0), i-colon is length of string minus key; + // subtract 1 for '\0', 1 for '\n', 1 for '\r', + // 1 for the ' ' after the ':', and total is -4 + std::string name(lineStr.substr(0, colon)); + std::string value(lineStr.substr(colon + 2, i - colon - 4)); + + // Make the name lower case. + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + + headers[name] = value; + } + } + + return std::make_pair(true, headers); + } + std::string WebSocketTransport::genRandomString(const int len) { std::string alphanum = @@ -247,6 +300,7 @@ namespace ix return WebSocketInitResult(false, 0, std::string("Failed sending GET request to ") + _url); } + // Read first line char line[256]; int i; for (i = 0; i < 2 || (i < 255 && line[i-2] != '\r' && line[i-1] != '\n'); ++i) @@ -285,49 +339,13 @@ namespace ix return WebSocketInitResult(false, status, ss.str()); } - WebSocketHttpHeaders headers; + auto result = parseHttpHeaders(); + auto headersValid = result.first; + auto headers = result.second; - while (true) + if (!headersValid) { - int colon = 0; - - for (i = 0; - i < 2 || (i < 255 && line[i-2] != '\r' && line[i-1] != '\n'); - ++i) - { - if (!readByte(line+i)) - { - return WebSocketInitResult(false, status, std::string("Failed reading response header from ") + _url); - } - - if (line[i] == ':' && colon == 0) - { - colon = i; - } - } - if (line[0] == '\r' && line[1] == '\n') - { - break; - } - - // line is a single header entry. split by ':', and add it to our - // header map. ignore lines with no colon. - if (colon > 0) - { - line[i] = '\0'; - std::string lineStr(line); - // colon is ':', colon+1 is ' ', colon+2 is the start of the value. - // i is end of string (\0), i-colon is length of string minus key; - // subtract 1 for '\0', 1 for '\n', 1 for '\r', - // 1 for the ' ' after the ':', and total is -4 - std::string name(lineStr.substr(0, colon)); - std::string value(lineStr.substr(colon + 2, i - colon - 4)); - - // Make the name lower case. - std::transform(name.begin(), name.end(), name.begin(), ::tolower); - - headers[name] = value; - } + return WebSocketInitResult(false, status, "Error parsing HTTP headers"); } char output[29] = {}; @@ -362,6 +380,15 @@ namespace ix return WebSocketInitResult(true, status, "", headers); } + WebSocketInitResult WebSocketTransport::initFromSocket(int fd) + { + _socket.reset(); + _socket = std::make_shared(fd); + + WebSocketHttpHeaders headers; + return WebSocketInitResult(true, 200, "", headers); + } + WebSocketTransport::ReadyStateValues WebSocketTransport::getReadyState() const { return _readyState; diff --git a/ixwebsocket/IXWebSocketTransport.h b/ixwebsocket/IXWebSocketTransport.h index a3fe9640..dee8add8 100644 --- a/ixwebsocket/IXWebSocketTransport.h +++ b/ixwebsocket/IXWebSocketTransport.h @@ -74,10 +74,14 @@ namespace ix WebSocketTransport(); ~WebSocketTransport(); + // Client void configure(const std::string& url, const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); WebSocketInitResult init(); + // Server + WebSocketInitResult initFromSocket(int fd); + void poll(); WebSocketSendInfo sendBinary(const std::string& message); WebSocketSendInfo sendPing(const std::string& message); @@ -164,5 +168,8 @@ namespace ix // Non blocking versions of read/write, used during http upgrade bool readByte(void* buffer); bool writeBytes(const std::string& str); + + // Parse HTTP headers + std::pair parseHttpHeaders(); }; }