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
{
Socket::Socket() :
_sockfd(-1)
Socket::Socket(int fd) :
_sockfd(fd)
{
}

View File

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

View File

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

View File

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

View File

@ -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)
{

View File

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

View File

@ -145,6 +145,59 @@ namespace ix
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 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<Socket>(fd);
WebSocketHttpHeaders headers;
return WebSocketInitResult(true, 200, "", headers);
}
WebSocketTransport::ReadyStateValues WebSocketTransport::getReadyState() const
{
return _readyState;

View File

@ -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<bool, WebSocketHttpHeaders> parseHttpHeaders();
};
}