can create a socket from a fd

This commit is contained in:
Benjamin Sergeant 2018-12-29 21:53:33 -08:00
parent 43cd6d34ca
commit ea07afcc0b
8 changed files with 82 additions and 48 deletions

View File

@ -37,8 +37,8 @@
namespace ix namespace ix
{ {
Socket::Socket() : Socket::Socket(int fd) :
_sockfd(-1) _sockfd(fd)
{ {
} }

View File

@ -22,7 +22,7 @@ namespace ix
public: public:
using OnPollCallback = std::function<void()>; using OnPollCallback = std::function<void()>;
Socket(); Socket(int fd = -1);
virtual ~Socket(); virtual ~Socket();
void configure(); void configure();

View File

@ -143,7 +143,7 @@ std::string getSSLErrorDescription(OSStatus status)
namespace ix namespace ix
{ {
SocketAppleSSL::SocketAppleSSL() : SocketAppleSSL::SocketAppleSSL(int fd) : Socket(fd),
_sslContext(nullptr) _sslContext(nullptr)
{ {
; ;

View File

@ -19,7 +19,7 @@ namespace ix
class SocketAppleSSL : public Socket class SocketAppleSSL : public Socket
{ {
public: public:
SocketAppleSSL(); SocketAppleSSL(int fd = -1);
~SocketAppleSSL(); ~SocketAppleSSL();
virtual bool connect(const std::string& host, virtual bool connect(const std::string& host,

View File

@ -74,7 +74,7 @@ SSL *openssl_create_connection(SSL_CTX *ctx, int socket)
namespace ix namespace ix
{ {
SocketOpenSSL::SocketOpenSSL() : SocketOpenSSL::SocketOpenSSL(int fd) : Socket(fd),
_ssl_connection(nullptr), _ssl_connection(nullptr),
_ssl_context(nullptr) _ssl_context(nullptr)
{ {

View File

@ -22,7 +22,7 @@ namespace ix
class SocketOpenSSL : public Socket class SocketOpenSSL : public Socket
{ {
public: public:
SocketOpenSSL(); SocketOpenSSL(int fd = -1);
~SocketOpenSSL(); ~SocketOpenSSL();
virtual bool connect(const std::string& host, virtual bool connect(const std::string& host,

View File

@ -145,6 +145,59 @@ namespace ix
std::cout << "-------------------------------" << std::endl; std::cout << "-------------------------------" << std::endl;
} }
std::pair<bool, WebSocketHttpHeaders> 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 WebSocketTransport::genRandomString(const int len)
{ {
std::string alphanum = std::string alphanum =
@ -247,6 +300,7 @@ namespace ix
return WebSocketInitResult(false, 0, std::string("Failed sending GET request to ") + _url); return WebSocketInitResult(false, 0, std::string("Failed sending GET request to ") + _url);
} }
// Read first line
char line[256]; char line[256];
int i; int i;
for (i = 0; i < 2 || (i < 255 && line[i-2] != '\r' && line[i-1] != '\n'); ++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()); 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; return WebSocketInitResult(false, status, "Error parsing HTTP headers");
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;
}
} }
char output[29] = {}; char output[29] = {};
@ -362,6 +380,15 @@ namespace ix
return WebSocketInitResult(true, status, "", headers); return WebSocketInitResult(true, status, "", headers);
} }
WebSocketInitResult WebSocketTransport::initFromSocket(int fd)
{
_socket.reset();
_socket = std::make_shared<Socket>(fd);
WebSocketHttpHeaders headers;
return WebSocketInitResult(true, 200, "", headers);
}
WebSocketTransport::ReadyStateValues WebSocketTransport::getReadyState() const WebSocketTransport::ReadyStateValues WebSocketTransport::getReadyState() const
{ {
return _readyState; return _readyState;

View File

@ -74,10 +74,14 @@ namespace ix
WebSocketTransport(); WebSocketTransport();
~WebSocketTransport(); ~WebSocketTransport();
// Client
void configure(const std::string& url, void configure(const std::string& url,
const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
WebSocketInitResult init(); WebSocketInitResult init();
// Server
WebSocketInitResult initFromSocket(int fd);
void poll(); void poll();
WebSocketSendInfo sendBinary(const std::string& message); WebSocketSendInfo sendBinary(const std::string& message);
WebSocketSendInfo sendPing(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 // Non blocking versions of read/write, used during http upgrade
bool readByte(void* buffer); bool readByte(void* buffer);
bool writeBytes(const std::string& str); bool writeBytes(const std::string& str);
// Parse HTTP headers
std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders();
}; };
} }