reformat everything with clang-format

This commit is contained in:
Benjamin Sergeant 2019-09-23 10:25:23 -07:00
parent 398c4fbf99
commit cd3c9d879c
92 changed files with 3158 additions and 3348 deletions

View File

@ -10,14 +10,13 @@
namespace ix namespace ix
{ {
CancellationRequest makeCancellationRequestWithTimeout(int secs, CancellationRequest makeCancellationRequestWithTimeout(
std::atomic<bool>& requestInitCancellation) int secs, std::atomic<bool>& requestInitCancellation)
{ {
auto start = std::chrono::system_clock::now(); auto start = std::chrono::system_clock::now();
auto timeout = std::chrono::seconds(secs); auto timeout = std::chrono::seconds(secs);
auto isCancellationRequested = [&requestInitCancellation, start, timeout]() -> bool auto isCancellationRequested = [&requestInitCancellation, start, timeout]() -> bool {
{
// Was an explicit cancellation requested ? // Was an explicit cancellation requested ?
if (requestInitCancellation) return true; if (requestInitCancellation) return true;
@ -30,4 +29,4 @@ namespace ix
return isCancellationRequested; return isCancellationRequested;
} }
} } // namespace ix

View File

@ -10,7 +10,8 @@ namespace ix
{ {
std::atomic<uint64_t> ConnectionState::_globalId(0); std::atomic<uint64_t> ConnectionState::_globalId(0);
ConnectionState::ConnectionState() : _terminated(false) ConnectionState::ConnectionState()
: _terminated(false)
{ {
computeId(); computeId();
} }
@ -39,5 +40,4 @@ namespace ix
{ {
_terminated = true; _terminated = true;
} }
} } // namespace ix

View File

@ -5,22 +5,22 @@
*/ */
#include "IXDNSLookup.h" #include "IXDNSLookup.h"
#include "IXNetSystem.h"
#include <string.h> #include "IXNetSystem.h"
#include <chrono> #include <chrono>
#include <string.h>
#include <thread> #include <thread>
namespace ix namespace ix
{ {
const int64_t DNSLookup::kDefaultWait = 1; // ms const int64_t DNSLookup::kDefaultWait = 1; // ms
DNSLookup::DNSLookup(const std::string& hostname, int port, int64_t wait) : DNSLookup::DNSLookup(const std::string& hostname, int port, int64_t wait)
_hostname(hostname), : _hostname(hostname)
_port(port), , _port(port)
_wait(wait), , _wait(wait)
_res(nullptr), , _res(nullptr)
_done(false) , _done(false)
{ {
; ;
} }
@ -38,8 +38,7 @@ namespace ix
std::string sport = std::to_string(port); std::string sport = std::to_string(port);
struct addrinfo* res; struct addrinfo* res;
int getaddrinfo_result = getaddrinfo(hostname.c_str(), sport.c_str(), int getaddrinfo_result = getaddrinfo(hostname.c_str(), sport.c_str(), &hints, &res);
&hints, &res);
if (getaddrinfo_result) if (getaddrinfo_result)
{ {
errMsg = gai_strerror(getaddrinfo_result); errMsg = gai_strerror(getaddrinfo_result);
@ -56,8 +55,8 @@ namespace ix
: resolveUnCancellable(errMsg, isCancellationRequested); : resolveUnCancellable(errMsg, isCancellationRequested);
} }
struct addrinfo* DNSLookup::resolveUnCancellable(std::string& errMsg, struct addrinfo* DNSLookup::resolveUnCancellable(
const CancellationRequest& isCancellationRequested) std::string& errMsg, const CancellationRequest& isCancellationRequested)
{ {
errMsg = "no error"; errMsg = "no error";
@ -71,8 +70,8 @@ namespace ix
return getAddrInfo(_hostname, _port, errMsg); return getAddrInfo(_hostname, _port, errMsg);
} }
struct addrinfo* DNSLookup::resolveCancellable(std::string& errMsg, struct addrinfo* DNSLookup::resolveCancellable(
const CancellationRequest& isCancellationRequested) std::string& errMsg, const CancellationRequest& isCancellationRequested)
{ {
errMsg = "no error"; errMsg = "no error";
@ -126,7 +125,9 @@ namespace ix
return getRes(); return getRes();
} }
void DNSLookup::run(std::weak_ptr<DNSLookup> self, std::string hostname, int port) // thread runner void DNSLookup::run(std::weak_ptr<DNSLookup> self,
std::string hostname,
int port) // thread runner
{ {
// We don't want to read or write into members variables of an object that could be // We don't want to read or write into members variables of an object that could be
// gone, so we use temporary variables (res) or we pass in by copy everything that // gone, so we use temporary variables (res) or we pass in by copy everything that
@ -167,4 +168,4 @@ namespace ix
std::lock_guard<std::mutex> lock(_resMutex); std::lock_guard<std::mutex> lock(_resMutex);
return _res; return _res;
} }
} } // namespace ix

View File

@ -10,8 +10,7 @@
namespace ix namespace ix
{ {
uint32_t calculateRetryWaitMilliseconds( uint32_t calculateRetryWaitMilliseconds(uint32_t retry_count,
uint32_t retry_count,
uint32_t maxWaitBetweenReconnectionRetries) uint32_t maxWaitBetweenReconnectionRetries)
{ {
uint32_t wait_time = std::pow(2, retry_count) * 100; uint32_t wait_time = std::pow(2, retry_count) * 100;
@ -23,4 +22,4 @@ namespace ix
return wait_time; return wait_time;
} }
} } // namespace ix

View File

@ -10,7 +10,6 @@
namespace ix namespace ix
{ {
uint32_t calculateRetryWaitMilliseconds( uint32_t calculateRetryWaitMilliseconds(uint32_t retry_count,
uint32_t retry_count,
uint32_t maxWaitBetweenReconnectionRetries); uint32_t maxWaitBetweenReconnectionRetries);
} // namespace ix } // namespace ix

View File

@ -5,9 +5,9 @@
*/ */
#include "IXHttp.h" #include "IXHttp.h"
#include "IXCancellationRequest.h" #include "IXCancellationRequest.h"
#include "IXSocket.h" #include "IXSocket.h"
#include <sstream> #include <sstream>
#include <vector> #include <vector>
@ -57,7 +57,8 @@ namespace ix
return std::make_pair(httpVersion, statusCode); return std::make_pair(httpVersion, statusCode);
} }
std::tuple<std::string, std::string, std::string> Http::parseRequestLine(const std::string& line) std::tuple<std::string, std::string, std::string> Http::parseRequestLine(
const std::string& line)
{ {
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
std::string token; std::string token;
@ -161,8 +162,6 @@ namespace ix
return false; return false;
} }
return response->payload.empty() return response->payload.empty() ? true : socket->writeBytes(response->payload, nullptr);
? true
: socket->writeBytes(response->payload, nullptr);
}
} }
} // namespace ix

View File

@ -115,8 +115,7 @@ namespace ix
std::shared_ptr<Socket> socket); std::shared_ptr<Socket> socket);
static bool sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket); static bool sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket);
static std::pair<std::string, int> parseStatusLine( static std::pair<std::string, int> parseStatusLine(const std::string& line);
const std::string& line);
static std::tuple<std::string, std::string, std::string> parseRequestLine( static std::tuple<std::string, std::string, std::string> parseRequestLine(
const std::string& line); const std::string& line);
static std::string trim(const std::string& str); static std::string trim(const std::string& str);

View File

@ -5,17 +5,16 @@
*/ */
#include "IXHttpClient.h" #include "IXHttpClient.h"
#include "IXSocketFactory.h"
#include "IXUrlParser.h" #include "IXUrlParser.h"
#include "IXUserAgent.h" #include "IXUserAgent.h"
#include "IXWebSocketHttpHeaders.h" #include "IXWebSocketHttpHeaders.h"
#include "IXSocketFactory.h"
#include <sstream>
#include <iomanip>
#include <vector>
#include <cstring>
#include <assert.h> #include <assert.h>
#include <cstring>
#include <iomanip>
#include <sstream>
#include <vector>
#include <zlib.h> #include <zlib.h>
namespace ix namespace ix
@ -26,7 +25,9 @@ namespace ix
const std::string HttpClient::kDel = "DEL"; const std::string HttpClient::kDel = "DEL";
const std::string HttpClient::kPut = "PUT"; const std::string HttpClient::kPut = "PUT";
HttpClient::HttpClient(bool async) : _async(async), _stop(false) HttpClient::HttpClient(bool async)
: _async(async)
, _stop(false)
{ {
if (!_async) return; if (!_async) return;
@ -42,8 +43,7 @@ namespace ix
_thread.join(); _thread.join();
} }
HttpRequestArgsPtr HttpClient::createRequest(const std::string& url, HttpRequestArgsPtr HttpClient::createRequest(const std::string& url, const std::string& verb)
const std::string& verb)
{ {
auto request = std::make_shared<HttpRequestArgs>(); auto request = std::make_shared<HttpRequestArgs>();
request->url = url; request->url = url;
@ -106,8 +106,7 @@ namespace ix
} }
} }
HttpResponsePtr HttpClient::request( HttpResponsePtr HttpClient::request(const std::string& url,
const std::string& url,
const std::string& verb, const std::string& verb,
const std::string& body, const std::string& body,
HttpRequestArgsPtr args, HttpRequestArgsPtr args,
@ -131,9 +130,14 @@ namespace ix
{ {
std::stringstream ss; std::stringstream ss;
ss << "Cannot parse url: " << url; ss << "Cannot parse url: " << url;
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::UrlMalformed, return std::make_shared<HttpResponse>(code,
headers, payload, ss.str(), description,
uploadSize, downloadSize); HttpErrorCode::UrlMalformed,
headers,
payload,
ss.str(),
uploadSize,
downloadSize);
} }
bool tls = protocol == "https"; bool tls = protocol == "https";
@ -143,9 +147,14 @@ namespace ix
if (!_socket) if (!_socket)
{ {
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::CannotCreateSocket, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::CannotCreateSocket,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
// Build request string // Build request string
@ -155,7 +164,8 @@ namespace ix
if (args->compress) if (args->compress)
{ {
ss << "Accept-Encoding: gzip" << "\r\n"; ss << "Accept-Encoding: gzip"
<< "\r\n";
} }
// Append extra headers // Append extra headers
@ -167,7 +177,8 @@ namespace ix
// Set a default Accept header if none is present // Set a default Accept header if none is present
if (headers.find("Accept") == headers.end()) if (headers.find("Accept") == headers.end())
{ {
ss << "Accept: */*" << "\r\n"; ss << "Accept: */*"
<< "\r\n";
} }
// Set a default User agent if none is present // Set a default User agent if none is present
@ -183,7 +194,8 @@ namespace ix
// Set default Content-Type if unspecified // Set default Content-Type if unspecified
if (args->extraHeaders.find("Content-Type") == args->extraHeaders.end()) if (args->extraHeaders.find("Content-Type") == args->extraHeaders.end())
{ {
ss << "Content-Type: application/x-www-form-urlencoded" << "\r\n"; ss << "Content-Type: application/x-www-form-urlencoded"
<< "\r\n";
} }
ss << "\r\n"; ss << "\r\n";
ss << body; ss << body;
@ -206,9 +218,14 @@ namespace ix
{ {
std::stringstream ss; std::stringstream ss;
ss << "Cannot connect to url: " << url << " / error : " << errMsg; ss << "Cannot connect to url: " << url << " / error : " << errMsg;
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::CannotConnect, return std::make_shared<HttpResponse>(code,
headers, payload, ss.str(), description,
uploadSize, downloadSize); HttpErrorCode::CannotConnect,
headers,
payload,
ss.str(),
uploadSize,
downloadSize);
} }
// Make a new cancellation object dealing with transfer timeout // Make a new cancellation object dealing with transfer timeout
@ -222,8 +239,7 @@ namespace ix
<< "to " << host << ":" << port << std::endl << "to " << host << ":" << port << std::endl
<< "request size: " << req.size() << " bytes" << std::endl << "request size: " << req.size() << " bytes" << std::endl
<< "=============" << std::endl << "=============" << std::endl
<< req << req << "=============" << std::endl
<< "=============" << std::endl
<< std::endl; << std::endl;
log(ss.str(), args); log(ss.str(), args);
@ -232,9 +248,14 @@ namespace ix
if (!_socket->writeBytes(req, isCancellationRequested)) if (!_socket->writeBytes(req, isCancellationRequested))
{ {
std::string errorMsg("Cannot send request"); std::string errorMsg("Cannot send request");
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::SendError, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::SendError,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
uploadSize = req.size(); uploadSize = req.size();
@ -246,9 +267,14 @@ namespace ix
if (!lineValid) if (!lineValid)
{ {
std::string errorMsg("Cannot retrieve status line"); std::string errorMsg("Cannot retrieve status line");
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::CannotReadStatusLine, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::CannotReadStatusLine,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
if (args->verbose) if (args->verbose)
@ -261,9 +287,14 @@ namespace ix
if (sscanf(line.c_str(), "HTTP/1.1 %d", &code) != 1) if (sscanf(line.c_str(), "HTTP/1.1 %d", &code) != 1)
{ {
std::string errorMsg("Cannot parse response code from status line"); std::string errorMsg("Cannot parse response code from status line");
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::MissingStatus, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::MissingStatus,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
auto result = parseHttpHeaders(_socket, isCancellationRequested); auto result = parseHttpHeaders(_socket, isCancellationRequested);
@ -273,9 +304,14 @@ namespace ix
if (!headersValid) if (!headersValid)
{ {
std::string errorMsg("Cannot parse http headers"); std::string errorMsg("Cannot parse http headers");
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::HeaderParsingError, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::HeaderParsingError,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
// Redirect ? // Redirect ?
@ -284,18 +320,28 @@ namespace ix
if (headers.find("Location") == headers.end()) if (headers.find("Location") == headers.end())
{ {
std::string errorMsg("Missing location header for redirect"); std::string errorMsg("Missing location header for redirect");
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::MissingLocation, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::MissingLocation,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
if (redirects >= args->maxRedirects) if (redirects >= args->maxRedirects)
{ {
std::stringstream ss; std::stringstream ss;
ss << "Too many redirects: " << redirects; ss << "Too many redirects: " << redirects;
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::TooManyRedirects, return std::make_shared<HttpResponse>(code,
headers, payload, ss.str(), description,
uploadSize, downloadSize); HttpErrorCode::TooManyRedirects,
headers,
payload,
ss.str(),
uploadSize,
downloadSize);
} }
// Recurse // Recurse
@ -305,9 +351,14 @@ namespace ix
if (verb == "HEAD") if (verb == "HEAD")
{ {
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::Ok, return std::make_shared<HttpResponse>(code,
headers, payload, std::string(), description,
uploadSize, downloadSize); HttpErrorCode::Ok,
headers,
payload,
std::string(),
uploadSize,
downloadSize);
} }
// Parse response: // Parse response:
@ -320,15 +371,19 @@ namespace ix
payload.reserve(contentLength); payload.reserve(contentLength);
auto chunkResult = _socket->readBytes(contentLength, auto chunkResult = _socket->readBytes(
args->onProgressCallback, contentLength, args->onProgressCallback, isCancellationRequested);
isCancellationRequested);
if (!chunkResult.first) if (!chunkResult.first)
{ {
errorMsg = "Cannot read chunk"; errorMsg = "Cannot read chunk";
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::ChunkReadError, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::ChunkReadError,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
payload += chunkResult.second; payload += chunkResult.second;
} }
@ -344,9 +399,14 @@ namespace ix
if (!lineResult.first) if (!lineResult.first)
{ {
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::ChunkReadError, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::ChunkReadError,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
uint64_t chunkSize; uint64_t chunkSize;
@ -357,23 +417,26 @@ namespace ix
if (args->verbose) if (args->verbose)
{ {
std::stringstream oss; std::stringstream oss;
oss << "Reading " << chunkSize << " bytes" oss << "Reading " << chunkSize << " bytes" << std::endl;
<< std::endl;
log(oss.str(), args); log(oss.str(), args);
} }
payload.reserve(payload.size() + (size_t) chunkSize); payload.reserve(payload.size() + (size_t) chunkSize);
// Read a chunk // Read a chunk
auto chunkResult = _socket->readBytes((size_t) chunkSize, auto chunkResult = _socket->readBytes(
args->onProgressCallback, (size_t) chunkSize, args->onProgressCallback, isCancellationRequested);
isCancellationRequested);
if (!chunkResult.first) if (!chunkResult.first)
{ {
errorMsg = "Cannot read chunk"; errorMsg = "Cannot read chunk";
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::ChunkReadError, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::ChunkReadError,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
payload += chunkResult.second; payload += chunkResult.second;
@ -382,9 +445,14 @@ namespace ix
if (!lineResult.first) if (!lineResult.first)
{ {
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::ChunkReadError, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::ChunkReadError,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
if (chunkSize == 0) break; if (chunkSize == 0) break;
@ -397,9 +465,14 @@ namespace ix
else else
{ {
std::string errorMsg("Cannot read http body"); std::string errorMsg("Cannot read http body");
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::CannotReadBody, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::CannotReadBody,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
downloadSize = payload.size(); downloadSize = payload.size();
@ -411,32 +484,39 @@ namespace ix
if (!gzipInflate(payload, decompressedPayload)) if (!gzipInflate(payload, decompressedPayload))
{ {
std::string errorMsg("Error decompressing payload"); std::string errorMsg("Error decompressing payload");
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::Gzip, return std::make_shared<HttpResponse>(code,
headers, payload, errorMsg, description,
uploadSize, downloadSize); HttpErrorCode::Gzip,
headers,
payload,
errorMsg,
uploadSize,
downloadSize);
} }
payload = decompressedPayload; payload = decompressedPayload;
} }
return std::make_shared<HttpResponse>(code, description, HttpErrorCode::Ok, return std::make_shared<HttpResponse>(code,
headers, payload, std::string(), description,
uploadSize, downloadSize); HttpErrorCode::Ok,
headers,
payload,
std::string(),
uploadSize,
downloadSize);
} }
HttpResponsePtr HttpClient::get(const std::string& url, HttpResponsePtr HttpClient::get(const std::string& url, HttpRequestArgsPtr args)
HttpRequestArgsPtr args)
{ {
return request(url, kGet, std::string(), args); return request(url, kGet, std::string(), args);
} }
HttpResponsePtr HttpClient::head(const std::string& url, HttpResponsePtr HttpClient::head(const std::string& url, HttpRequestArgsPtr args)
HttpRequestArgsPtr args)
{ {
return request(url, kHead, std::string(), args); return request(url, kHead, std::string(), args);
} }
HttpResponsePtr HttpClient::del(const std::string& url, HttpResponsePtr HttpClient::del(const std::string& url, HttpRequestArgsPtr args)
HttpRequestArgsPtr args)
{ {
return request(url, kDel, std::string(), args); return request(url, kDel, std::string(), args);
} }
@ -475,8 +555,7 @@ namespace ix
escaped.fill('0'); escaped.fill('0');
escaped << std::hex; escaped << std::hex;
for (std::string::const_iterator i = value.begin(), n = value.end(); for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i)
i != n; ++i)
{ {
std::string::value_type c = (*i); std::string::value_type c = (*i);
@ -504,9 +583,7 @@ namespace ix
for (auto&& it : httpParameters) for (auto&& it : httpParameters)
{ {
ss << urlEncode(it.first) ss << urlEncode(it.first) << "=" << urlEncode(it.second);
<< "="
<< urlEncode(it.second);
if (i++ < (count - 1)) if (i++ < (count - 1))
{ {
@ -516,9 +593,7 @@ namespace ix
return ss.str(); return ss.str();
} }
bool HttpClient::gzipInflate( bool HttpClient::gzipInflate(const std::string& in, std::string& out)
const std::string& in,
std::string& out)
{ {
z_stream inflateState; z_stream inflateState;
std::memset(&inflateState, 0, sizeof(inflateState)); std::memset(&inflateState, 0, sizeof(inflateState));
@ -555,22 +630,19 @@ namespace ix
return false; return false;
} }
out.append( out.append(reinterpret_cast<char*>(compressBuffer.get()),
reinterpret_cast<char *>(compressBuffer.get()), kBufferSize - inflateState.avail_out);
kBufferSize - inflateState.avail_out
);
} while (inflateState.avail_out == 0); } while (inflateState.avail_out == 0);
inflateEnd(&inflateState); inflateEnd(&inflateState);
return true; return true;
} }
void HttpClient::log(const std::string& msg, void HttpClient::log(const std::string& msg, HttpRequestArgsPtr args)
HttpRequestArgsPtr args)
{ {
if (args->logger) if (args->logger)
{ {
args->logger(msg); args->logger(msg);
} }
} }
} } // namespace ix

View File

@ -5,13 +5,13 @@
*/ */
#include "IXHttpServer.h" #include "IXHttpServer.h"
#include "IXNetSystem.h"
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include "IXSocketFactory.h" #include "IXSocketFactory.h"
#include "IXNetSystem.h" #include <fstream>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <fstream>
#include <vector> #include <vector>
namespace namespace
@ -39,15 +39,13 @@ namespace
auto vec = res.second; auto vec = res.second;
return std::make_pair(res.first, std::string(vec.begin(), vec.end())); return std::make_pair(res.first, std::string(vec.begin(), vec.end()));
} }
} } // namespace
namespace ix namespace ix
{ {
HttpServer::HttpServer(int port, HttpServer::HttpServer(int port, const std::string& host, int backlog, size_t maxConnections)
const std::string& host, : SocketServer(port, host, backlog, maxConnections)
int backlog, , _connectedClientsCount(0)
size_t maxConnections) : SocketServer(port, host, backlog, maxConnections),
_connectedClientsCount(0)
{ {
setDefaultConnectionCallback(); setDefaultConnectionCallback();
} }
@ -71,9 +69,7 @@ namespace ix
_onConnectionCallback = callback; _onConnectionCallback = callback;
} }
void HttpServer::handleConnection( void HttpServer::handleConnection(int fd, std::shared_ptr<ConnectionState> connectionState)
int fd,
std::shared_ptr<ConnectionState> connectionState)
{ {
_connectedClientsCount++; _connectedClientsCount++;
@ -109,8 +105,7 @@ namespace ix
{ {
setOnConnectionCallback( setOnConnectionCallback(
[this](HttpRequestPtr request, [this](HttpRequestPtr request,
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr {
{
std::string uri(request->uri); std::string uri(request->uri);
if (uri.empty() || uri == "/") if (uri.empty() || uri == "/")
{ {
@ -122,23 +117,16 @@ namespace ix
bool found = res.first; bool found = res.first;
if (!found) if (!found)
{ {
return std::make_shared<HttpResponse>(404, "Not Found", return std::make_shared<HttpResponse>(
HttpErrorCode::Ok, 404, "Not Found", HttpErrorCode::Ok, WebSocketHttpHeaders(), std::string());
WebSocketHttpHeaders(),
std::string());
} }
std::string content = res.second; std::string content = res.second;
// Log request // Log request
std::stringstream ss; std::stringstream ss;
ss << request->method ss << request->method << " " << request->headers["User-Agent"] << " "
<< " " << request->uri << " " << content.size();
<< request->headers["User-Agent"]
<< " "
<< request->uri
<< " "
<< content.size();
logInfo(ss.str()); logInfo(ss.str());
WebSocketHttpHeaders headers; WebSocketHttpHeaders headers;
@ -151,11 +139,8 @@ namespace ix
headers[it.first] = it.second; headers[it.first] = it.second;
} }
return std::make_shared<HttpResponse>(200, "OK", return std::make_shared<HttpResponse>(
HttpErrorCode::Ok, 200, "OK", HttpErrorCode::Ok, headers, content);
headers, });
content);
}
);
}
} }
} // namespace ix

View File

@ -77,8 +77,7 @@ namespace ix
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
int ret = select(maxfd + 1, &readfds, &writefds, &errorfds, int ret = select(maxfd + 1, &readfds, &writefds, &errorfds, timeout != -1 ? &tv : NULL);
timeout != -1 ? &tv : NULL);
if (ret < 0) if (ret < 0)
{ {

View File

@ -42,5 +42,4 @@ namespace ix
{ {
return -1; return -1;
} }
} } // namespace ix

View File

@ -26,14 +26,13 @@
#include "IXSelectInterruptEventFd.h" #include "IXSelectInterruptEventFd.h"
#include <sys/eventfd.h>
#include <unistd.h> // for write
#include <string.h> // for strerror
#include <fcntl.h>
#include <errno.h>
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <sstream> #include <sstream>
#include <string.h> // for strerror
#include <sys/eventfd.h>
#include <unistd.h> // for write
namespace ix namespace ix
{ {
@ -113,4 +112,4 @@ namespace ix
{ {
return _eventfd; return _eventfd;
} }
} } // namespace ix

View File

@ -22,4 +22,4 @@ namespace ix
return std::make_shared<SelectInterrupt>(); return std::make_shared<SelectInterrupt>();
#endif #endif
} }
} } // namespace ix

View File

@ -10,12 +10,12 @@
#include "IXSelectInterruptPipe.h" #include "IXSelectInterruptPipe.h"
#include <unistd.h> // for write
#include <string.h> // for strerror
#include <fcntl.h>
#include <errno.h>
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <sstream> #include <sstream>
#include <string.h> // for strerror
#include <unistd.h> // for write
namespace ix namespace ix
{ {
@ -143,4 +143,4 @@ namespace ix
return _fildes[kPipeReadIndex]; return _fildes[kPipeReadIndex];
} }
} } // namespace ix

View File

@ -5,21 +5,20 @@
*/ */
#include "IXSocket.h" #include "IXSocket.h"
#include "IXSocketConnect.h"
#include "IXNetSystem.h" #include "IXNetSystem.h"
#include "IXSelectInterrupt.h" #include "IXSelectInterrupt.h"
#include "IXSelectInterruptFactory.h" #include "IXSelectInterruptFactory.h"
#include "IXSocketConnect.h"
#include <algorithm>
#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <algorithm>
#ifdef min #ifdef min
#undef min #undef min
#endif #endif
@ -32,9 +31,9 @@ namespace ix
const uint64_t Socket::kCloseRequest = 2; const uint64_t Socket::kCloseRequest = 2;
constexpr size_t Socket::kChunkSize; constexpr size_t Socket::kChunkSize;
Socket::Socket(int fd) : Socket::Socket(int fd)
_sockfd(fd), : _sockfd(fd)
_selectInterrupt(createSelectInterrupt()) , _selectInterrupt(createSelectInterrupt())
{ {
; ;
} }
@ -123,8 +122,7 @@ namespace ix
// getsockopt() puts the errno value for connect into optval so 0 // getsockopt() puts the errno value for connect into optval so 0
// means no-error. // means no-error.
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1 || if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1 || optval != 0)
optval != 0)
{ {
pollResult = PollResultType::Error; pollResult = PollResultType::Error;
@ -292,8 +290,7 @@ namespace ix
} }
} }
bool Socket::readByte(void* buffer, bool Socket::readByte(void* buffer, const CancellationRequest& isCancellationRequested)
const CancellationRequest& isCancellationRequested)
{ {
while (true) while (true)
{ {
@ -369,9 +366,7 @@ namespace ix
if (ret > 0) if (ret > 0)
{ {
output.insert(output.end(), output.insert(output.end(), _readBuffer.begin(), _readBuffer.begin() + ret);
_readBuffer.begin(),
_readBuffer.begin() + ret);
} }
else if (ret <= 0 && !Socket::isWaitNeeded()) else if (ret <= 0 && !Socket::isWaitNeeded())
{ {
@ -388,7 +383,6 @@ namespace ix
} }
} }
return std::make_pair(true, std::string(output.begin(), return std::make_pair(true, std::string(output.begin(), output.end()));
output.end()));
}
} }
} // namespace ix

View File

@ -6,11 +6,13 @@
* Adapted from Satori SDK Apple SSL code. * Adapted from Satori SDK Apple SSL code.
*/ */
#include "IXSocketAppleSSL.h" #include "IXSocketAppleSSL.h"
#include "IXSocketConnect.h"
#include "IXSocketConnect.h"
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -18,20 +20,16 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <stdint.h>
#include <errno.h>
#define socketerrno errno #define socketerrno errno
#include <Security/SecureTransport.h> #include <Security/SecureTransport.h>
namespace { namespace
{
OSStatus read_from_socket(SSLConnectionRef connection, void* data, size_t* len) OSStatus read_from_socket(SSLConnectionRef connection, void* data, size_t* len)
{ {
int fd = (int) (long) connection; int fd = (int) (long) connection;
if (fd < 0) if (fd < 0) return errSSLInternal;
return errSSLInternal;
assert(data != nullptr); assert(data != nullptr);
assert(len != nullptr); assert(len != nullptr);
@ -56,18 +54,15 @@ OSStatus read_from_socket(SSLConnectionRef connection, void *data, size_t *len)
else else
{ {
*len = 0; *len = 0;
switch (errno) { switch (errno)
case ENOENT: {
return errSSLClosedGraceful; case ENOENT: return errSSLClosedGraceful;
case EAGAIN: case EAGAIN: return errSSLWouldBlock;
return errSSLWouldBlock;
case ECONNRESET: case ECONNRESET: return errSSLClosedAbort;
return errSSLClosedAbort;
default: default: return errSecIO;
return errSecIO;
} }
} }
} }
@ -75,8 +70,7 @@ OSStatus read_from_socket(SSLConnectionRef connection, void *data, size_t *len)
OSStatus write_to_socket(SSLConnectionRef connection, const void* data, size_t* len) OSStatus write_to_socket(SSLConnectionRef connection, const void* data, size_t* len)
{ {
int fd = (int) (long) connection; int fd = (int) (long) connection;
if (fd < 0) if (fd < 0) return errSSLInternal;
return errSSLInternal;
assert(data != nullptr); assert(data != nullptr);
assert(len != nullptr); assert(len != nullptr);
@ -123,8 +117,8 @@ std::string getSSLErrorDescription(OSStatus status)
{ {
char localBuffer[128]; char localBuffer[128];
Boolean success; Boolean success;
success = CFStringGetCString(message, localBuffer, 128, success =
CFStringGetSystemEncoding()); CFStringGetCString(message, localBuffer, 128, CFStringGetSystemEncoding());
if (success) if (success)
{ {
errMsg = localBuffer; errMsg = localBuffer;
@ -141,9 +135,10 @@ std::string getSSLErrorDescription(OSStatus status)
namespace ix namespace ix
{ {
SocketAppleSSL::SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd) : Socket(fd), SocketAppleSSL::SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd)
_sslContext(nullptr), : Socket(fd)
_tlsOptions(tlsOptions) , _sslContext(nullptr)
, _tlsOptions(tlsOptions)
{ {
; ;
} }
@ -173,10 +168,10 @@ namespace ix
SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12); SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12);
SSLSetPeerDomainName(_sslContext, host.c_str(), host.size()); SSLSetPeerDomainName(_sslContext, host.c_str(), host.size());
do { do
{
status = SSLHandshake(_sslContext); status = SSLHandshake(_sslContext);
} while (errSSLWouldBlock == status || } while (errSSLWouldBlock == status || errSSLServerAuthCompleted == status);
errSSLServerAuthCompleted == status);
} }
if (noErr != status) if (noErr != status)
@ -206,7 +201,8 @@ namespace ix
{ {
ssize_t ret = 0; ssize_t ret = 0;
OSStatus status; OSStatus status;
do { do
{
size_t processed = 0; size_t processed = 0;
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
status = SSLWrite(_sslContext, buf, nbyte, &processed); status = SSLWrite(_sslContext, buf, nbyte, &processed);
@ -215,8 +211,7 @@ namespace ix
nbyte -= processed; nbyte -= processed;
} while (nbyte > 0 && errSSLWouldBlock == status); } while (nbyte > 0 && errSSLWouldBlock == status);
if (ret == 0 && errSSLClosedAbort != status) if (ret == 0 && errSSLClosedAbort != status) ret = -1;
ret = -1;
return ret; return ret;
} }
@ -235,13 +230,11 @@ namespace ix
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
status = SSLRead(_sslContext, buf, nbyte, &processed); status = SSLRead(_sslContext, buf, nbyte, &processed);
if (processed > 0) if (processed > 0) return (ssize_t) processed;
return (ssize_t) processed;
// The connection was reset, inform the caller that this // The connection was reset, inform the caller that this
// Socket should close // Socket should close
if (status == errSSLClosedGraceful || if (status == errSSLClosedGraceful || status == errSSLClosedNoNotify ||
status == errSSLClosedNoNotify ||
status == errSSLClosedAbort) status == errSSLClosedAbort)
{ {
errno = ECONNRESET; errno = ECONNRESET;
@ -257,4 +250,4 @@ namespace ix
return -1; return -1;
} }
} } // namespace ix

View File

@ -5,12 +5,12 @@
*/ */
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include "IXDNSLookup.h" #include "IXDNSLookup.h"
#include "IXNetSystem.h" #include "IXNetSystem.h"
#include "IXSocket.h" #include "IXSocket.h"
#include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
// Android needs extra headers for TCP_NODELAY and IPPROTO_TCP // Android needs extra headers for TCP_NODELAY and IPPROTO_TCP
@ -23,8 +23,8 @@ namespace ix
{ {
// //
// This function can be cancelled every 50 ms // This function can be cancelled every 50 ms
// This is important so that we don't block the main UI thread when shutting down a connection which is // This is important so that we don't block the main UI thread when shutting down a connection
// already trying to reconnect, and can be blocked waiting for ::connect to respond. // which is already trying to reconnect, and can be blocked waiting for ::connect to respond.
// //
int SocketConnect::connectToAddress(const struct addrinfo* address, int SocketConnect::connectToAddress(const struct addrinfo* address,
std::string& errMsg, std::string& errMsg,
@ -32,9 +32,7 @@ namespace ix
{ {
errMsg = "no error"; errMsg = "no error";
int fd = socket(address->ai_family, int fd = socket(address->ai_family, address->ai_socktype, address->ai_protocol);
address->ai_socktype,
address->ai_protocol);
if (fd < 0) if (fd < 0)
{ {
errMsg = "Cannot create a socket"; errMsg = "Cannot create a socket";
@ -74,8 +72,7 @@ namespace ix
else if (pollResult == PollResultType::Error) else if (pollResult == PollResultType::Error)
{ {
Socket::closeSocket(fd); Socket::closeSocket(fd);
errMsg = std::string("Connect error: ") + errMsg = std::string("Connect error: ") + strerror(Socket::getErrno());
strerror(Socket::getErrno());
return -1; return -1;
} }
else if (pollResult == PollResultType::ReadyForWrite) else if (pollResult == PollResultType::ReadyForWrite)
@ -85,8 +82,7 @@ namespace ix
else else
{ {
Socket::closeSocket(fd); Socket::closeSocket(fd);
errMsg = std::string("Connect error: ") + errMsg = std::string("Connect error: ") + strerror(Socket::getErrno());
strerror(Socket::getErrno());
return -1; return -1;
} }
} }
@ -149,8 +145,7 @@ namespace ix
// 3. (apple) prevent SIGPIPE from being emitted when the remote end disconnect // 3. (apple) prevent SIGPIPE from being emitted when the remote end disconnect
#ifdef SO_NOSIGPIPE #ifdef SO_NOSIGPIPE
int value = 1; int value = 1;
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*) &value, sizeof(value));
(void *)&value, sizeof(value));
#endif #endif
} }
} } // namespace ix

View File

@ -7,15 +7,16 @@
#pragma once #pragma once
#include "IXSocketTLSOptions.h"
#include <memory> #include <memory>
#include <string> #include <string>
#include "IXSocketTLSOptions.h"
namespace ix namespace ix
{ {
class Socket; class Socket;
std::shared_ptr<Socket> createSocket(bool tls, std::string& errorMsg, const SocketTLSOptions& tlsOptions); std::shared_ptr<Socket> createSocket(bool tls,
std::string& errorMsg,
const SocketTLSOptions& tlsOptions);
std::shared_ptr<Socket> createSocket(int fd, std::string& errorMsg); std::shared_ptr<Socket> createSocket(int fd, std::string& errorMsg);
} // namespace ix } // namespace ix

View File

@ -9,16 +9,16 @@
*/ */
#include "IXSocketMbedTLS.h" #include "IXSocketMbedTLS.h"
#include "IXSocketConnect.h"
#include "IXNetSystem.h" #include "IXNetSystem.h"
#include "IXSocket.h" #include "IXSocket.h"
#include "IXSocketConnect.h"
#include <string.h> #include <string.h>
namespace ix namespace ix
{ {
SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions& tlsOptions) : SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions& tlsOptions)
_tlsOptions(tlsOptions) : _tlsOptions(tlsOptions)
{ {
; ;
} }
@ -102,8 +102,7 @@ namespace ix
{ {
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
res = mbedtls_ssl_handshake(&_ssl); res = mbedtls_ssl_handshake(&_ssl);
} } while (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE);
while (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE);
if (res != 0) if (res != 0)
{ {
@ -142,13 +141,18 @@ namespace ix
ssize_t res = mbedtls_ssl_write(&_ssl, (unsigned char*) buf, nbyte); ssize_t res = mbedtls_ssl_write(&_ssl, (unsigned char*) buf, nbyte);
if (res > 0) { if (res > 0)
{
nbyte -= res; nbyte -= res;
sent += res; sent += res;
} else if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE) { }
else if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE)
{
errno = EWOULDBLOCK; errno = EWOULDBLOCK;
return -1; return -1;
} else { }
else
{
return -1; return -1;
} }
} }
@ -181,4 +185,4 @@ namespace ix
} }
} }
} } // namespace ix

View File

@ -121,7 +121,9 @@ namespace ix
}); });
SSL_CTX_set_verify_depth(ctx, 4); SSL_CTX_set_verify_depth(ctx, 4);
} else { }
else
{
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr); SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr);
} }

View File

@ -13,12 +13,12 @@
#include "IXSocketSChannel.h" #include "IXSocketSChannel.h"
#ifdef _WIN32 #ifdef _WIN32
# include <basetsd.h>
# include <WinSock2.h>
# include <ws2def.h>
#include <WS2tcpip.h> #include <WS2tcpip.h>
# include <schannel.h> #include <WinSock2.h>
#include <basetsd.h>
#include <io.h> #include <io.h>
#include <schannel.h>
#include <ws2def.h>
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
@ -26,14 +26,15 @@
#define UNICODE #define UNICODE
#endif #endif
#include <windows.h>
#include <winsock2.h>
#include <mstcpip.h> #include <mstcpip.h>
#include <ws2tcpip.h>
#include <rpc.h>
#include <ntdsapi.h> #include <ntdsapi.h>
#include <rpc.h>
#include <stdio.h> #include <stdio.h>
#include <tchar.h> #include <tchar.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#define RECV_DATA_BUF_SIZE 256 #define RECV_DATA_BUF_SIZE 256
@ -50,10 +51,6 @@
// has already been initialized // has already been initialized
#else #else
#error("This file should only be built on Windows") #error("This file should only be built on Windows")
#endif #endif
@ -67,12 +64,9 @@ namespace ix
SocketSChannel::~SocketSChannel() SocketSChannel::~SocketSChannel()
{ {
} }
bool SocketSChannel::connect(const std::string& host, bool SocketSChannel::connect(const std::string& host, int port, std::string& errMsg)
int port,
std::string& errMsg)
{ {
return Socket::connect(host, port, errMsg, nullptr); return Socket::connect(host, port, errMsg, nullptr);
} }
@ -103,4 +97,4 @@ namespace ix
return Socket::recv(buf, nbyte); return Socket::recv(buf, nbyte);
} }
} } // namespace ix

View File

@ -5,14 +5,14 @@
*/ */
#include "IXSocketServer.h" #include "IXSocketServer.h"
#include "IXNetSystem.h"
#include "IXSocket.h" #include "IXSocket.h"
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include "IXNetSystem.h" #include <assert.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <string.h> #include <string.h>
#include <assert.h>
namespace ix namespace ix
{ {
@ -24,17 +24,16 @@ namespace ix
SocketServer::SocketServer(int port, SocketServer::SocketServer(int port,
const std::string& host, const std::string& host,
int backlog, int backlog,
size_t maxConnections) : size_t maxConnections)
_port(port), : _port(port)
_host(host), , _host(host)
_backlog(backlog), , _backlog(backlog)
_maxConnections(maxConnections), , _maxConnections(maxConnections)
_serverFd(-1), , _serverFd(-1)
_stop(false), , _stop(false)
_stopGc(false), , _stopGc(false)
_connectionStateFactory(&ConnectionState::createConnectionState) , _connectionStateFactory(&ConnectionState::createConnectionState)
{ {
} }
SocketServer::~SocketServer() SocketServer::~SocketServer()
@ -62,21 +61,18 @@ namespace ix
if ((_serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((_serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{ {
std::stringstream ss; std::stringstream ss;
ss << "SocketServer::listen() error creating socket): " ss << "SocketServer::listen() error creating socket): " << strerror(Socket::getErrno());
<< strerror(Socket::getErrno());
return std::make_pair(false, ss.str()); return std::make_pair(false, ss.str());
} }
// Make that socket reusable. (allow restarting this server at will) // Make that socket reusable. (allow restarting this server at will)
int enable = 1; int enable = 1;
if (setsockopt(_serverFd, SOL_SOCKET, SO_REUSEADDR, if (setsockopt(_serverFd, SOL_SOCKET, SO_REUSEADDR, (char*) &enable, sizeof(enable)) < 0)
(char*) &enable, sizeof(enable)) < 0)
{ {
std::stringstream ss; std::stringstream ss;
ss << "SocketServer::listen() error calling setsockopt(SO_REUSEADDR) " ss << "SocketServer::listen() error calling setsockopt(SO_REUSEADDR) "
<< "at address " << _host << ":" << _port << "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
<< " : " << strerror(Socket::getErrno());
Socket::closeSocket(_serverFd); Socket::closeSocket(_serverFd);
return std::make_pair(false, ss.str()); return std::make_pair(false, ss.str());
@ -99,8 +95,7 @@ namespace ix
{ {
std::stringstream ss; std::stringstream ss;
ss << "SocketServer::listen() error calling bind " ss << "SocketServer::listen() error calling bind "
<< "at address " << _host << ":" << _port << "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
<< " : " << strerror(Socket::getErrno());
Socket::closeSocket(_serverFd); Socket::closeSocket(_serverFd);
return std::make_pair(false, ss.str()); return std::make_pair(false, ss.str());
@ -113,8 +108,7 @@ namespace ix
{ {
std::stringstream ss; std::stringstream ss;
ss << "SocketServer::listen() error calling listen " ss << "SocketServer::listen() error calling listen "
<< "at address " << _host << ":" << _port << "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
<< " : " << strerror(Socket::getErrno());
Socket::closeSocket(_serverFd); Socket::closeSocket(_serverFd);
return std::make_pair(false, ss.str()); return std::make_pair(false, ss.str());
@ -221,8 +215,7 @@ namespace ix
if (pollResult == PollResultType::Error) if (pollResult == PollResultType::Error)
{ {
std::stringstream ss; std::stringstream ss;
ss << "SocketServer::run() error in select: " ss << "SocketServer::run() error in select: " << strerror(Socket::getErrno());
<< strerror(Socket::getErrno());
logError(ss.str()); logError(ss.str());
continue; continue;
} }
@ -245,8 +238,8 @@ namespace ix
// FIXME: that error should be propagated // FIXME: that error should be propagated
int err = Socket::getErrno(); int err = Socket::getErrno();
std::stringstream ss; std::stringstream ss;
ss << "SocketServer::run() error accepting connection: " ss << "SocketServer::run() error accepting connection: " << err << ", "
<< err << ", " << strerror(err); << strerror(err);
logError(ss.str()); logError(ss.str());
} }
continue; continue;
@ -255,8 +248,7 @@ namespace ix
if (getConnectedClientsCount() >= _maxConnections) if (getConnectedClientsCount() >= _maxConnections)
{ {
std::stringstream ss; std::stringstream ss;
ss << "SocketServer::run() reached max connections = " ss << "SocketServer::run() reached max connections = " << _maxConnections << ". "
<< _maxConnections << ". "
<< "Not accepting connection"; << "Not accepting connection";
logError(ss.str()); logError(ss.str());
@ -277,10 +269,7 @@ namespace ix
std::lock_guard<std::mutex> lock(_connectionsThreadsMutex); std::lock_guard<std::mutex> lock(_connectionsThreadsMutex);
_connectionsThreads.push_back(std::make_pair( _connectionsThreads.push_back(std::make_pair(
connectionState, connectionState,
std::thread(&SocketServer::handleConnection, std::thread(&SocketServer::handleConnection, this, clientFd, connectionState)));
this,
clientFd,
connectionState)));
} }
} }
@ -308,5 +297,4 @@ namespace ix
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
} }
} } // namespace ix

View File

@ -4,13 +4,14 @@
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
*/ */
#include <assert.h>
#include "IXSocketTLSOptions.h" #include "IXSocketTLSOptions.h"
#include <assert.h>
namespace ix namespace ix
{ {
SocketTLSOptions::SocketTLSOptions()
SocketTLSOptions::SocketTLSOptions() { {
#ifndef IXWEBSOCKET_USE_TLS #ifndef IXWEBSOCKET_USE_TLS
assert(false && "To use TLS features the library must be compiled with USE_TLS"); assert(false && "To use TLS features the library must be compiled with USE_TLS");
#endif #endif

View File

@ -5,6 +5,7 @@
*/ */
#include "IXUrlParser.h" #include "IXUrlParser.h"
#include "LUrlParser.h" #include "LUrlParser.h"
namespace ix namespace ix
@ -64,4 +65,4 @@ namespace ix
return true; return true;
} }
} } // namespace ix

View File

@ -5,8 +5,8 @@
*/ */
#include "IXUserAgent.h" #include "IXUserAgent.h"
#include "IXWebSocketVersion.h"
#include "IXWebSocketVersion.h"
#include <sstream> #include <sstream>
#include <zlib.h> #include <zlib.h>
@ -80,4 +80,4 @@ namespace ix
return ss.str(); return ss.str();
} }
} } // namespace ix

View File

@ -48,20 +48,31 @@ namespace ix
/// Lookup table for the UTF8 decode state machine /// Lookup table for the UTF8 decode state machine
static uint8_t const utf8d[] = { static uint8_t const utf8d[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df
0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef 0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff 0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1,
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1,
1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8
}; };
/// Decode the next byte of a UTF8 sequence /// Decode the next byte of a UTF8 sequence
@ -75,9 +86,7 @@ namespace ix
{ {
uint32_t type = utf8d[byte]; uint32_t type = utf8d[byte];
*codep = (*state != utf8_accept) ? *codep = (*state != utf8_accept) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte);
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
*state = utf8d[256 + *state * 16 + type]; *state = utf8d[256 + *state * 16 + type];
return *state; return *state;
@ -88,7 +97,11 @@ namespace ix
{ {
public: public:
/// Construct and initialize the validator /// Construct and initialize the validator
Utf8Validator() : m_state(utf8_accept),m_codepoint(0) {} Utf8Validator()
: m_state(utf8_accept)
, m_codepoint(0)
{
}
/// Advance the state of the validator with the next input byte /// Advance the state of the validator with the next input byte
/** /**
@ -115,11 +128,8 @@ namespace ix
{ {
for (iterator_type it = begin; it != end; ++it) for (iterator_type it = begin; it != end; ++it)
{ {
unsigned int result = decodeNextByte( unsigned int result =
&m_state, decodeNextByte(&m_state, &m_codepoint, static_cast<uint8_t>(*it));
&m_codepoint,
static_cast<uint8_t>(*it)
);
if (result == utf8_reject) if (result == utf8_reject)
{ {
@ -144,6 +154,7 @@ namespace ix
m_state = utf8_accept; m_state = utf8_accept;
m_codepoint = 0; m_codepoint = 0;
} }
private: private:
uint32_t m_state; uint32_t m_state;
uint32_t m_codepoint; uint32_t m_codepoint;

View File

@ -5,13 +5,13 @@
*/ */
#include "IXWebSocket.h" #include "IXWebSocket.h"
#include "IXSetThreadName.h"
#include "IXWebSocketHandshake.h"
#include "IXExponentialBackoff.h"
#include "IXUtf8Validator.h"
#include <cmath> #include "IXExponentialBackoff.h"
#include "IXSetThreadName.h"
#include "IXUtf8Validator.h"
#include "IXWebSocketHandshake.h"
#include <cassert> #include <cassert>
#include <cmath>
namespace ix namespace ix
@ -23,26 +23,26 @@ namespace ix
const bool WebSocket::kDefaultEnablePong(true); const bool WebSocket::kDefaultEnablePong(true);
const uint32_t WebSocket::kDefaultMaxWaitBetweenReconnectionRetries(10 * 1000); // 10s const uint32_t WebSocket::kDefaultMaxWaitBetweenReconnectionRetries(10 * 1000); // 10s
WebSocket::WebSocket() : WebSocket::WebSocket()
_onMessageCallback(OnMessageCallback()), : _onMessageCallback(OnMessageCallback())
_stop(false), , _stop(false)
_automaticReconnection(true), , _automaticReconnection(true)
_maxWaitBetweenReconnectionRetries(kDefaultMaxWaitBetweenReconnectionRetries), , _maxWaitBetweenReconnectionRetries(kDefaultMaxWaitBetweenReconnectionRetries)
_handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs), , _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs)
_enablePong(kDefaultEnablePong), , _enablePong(kDefaultEnablePong)
_pingIntervalSecs(kDefaultPingIntervalSecs), , _pingIntervalSecs(kDefaultPingIntervalSecs)
_pingTimeoutSecs(kDefaultPingTimeoutSecs) , _pingTimeoutSecs(kDefaultPingTimeoutSecs)
{ {
_ws.setOnCloseCallback( _ws.setOnCloseCallback(
[this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) {
{
_onMessageCallback( _onMessageCallback(
std::make_shared<WebSocketMessage>( std::make_shared<WebSocketMessage>(WebSocketMessageType::Close,
WebSocketMessageType::Close, "", wireSize, "",
WebSocketErrorInfo(), WebSocketOpenInfo(), wireSize,
WebSocketErrorInfo(),
WebSocketOpenInfo(),
WebSocketCloseInfo(code, reason, remote))); WebSocketCloseInfo(code, reason, remote)));
} });
);
} }
WebSocket::~WebSocket() WebSocket::~WebSocket()
@ -67,7 +67,8 @@ namespace ix
return _url; return _url;
} }
void WebSocket::setPerMessageDeflateOptions(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions) void WebSocket::setPerMessageDeflateOptions(
const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions)
{ {
std::lock_guard<std::mutex> lock(_configMutex); std::lock_guard<std::mutex> lock(_configMutex);
_perMessageDeflateOptions = perMessageDeflateOptions; _perMessageDeflateOptions = perMessageDeflateOptions;
@ -159,8 +160,7 @@ namespace ix
_thread = std::thread(&WebSocket::run, this); _thread = std::thread(&WebSocket::run, this);
} }
void WebSocket::stop(uint16_t code, void WebSocket::stop(uint16_t code, const std::string& reason)
const std::string& reason)
{ {
close(code, reason); close(code, reason);
@ -192,8 +192,9 @@ namespace ix
} }
_onMessageCallback( _onMessageCallback(
std::make_shared<WebSocketMessage>( std::make_shared<WebSocketMessage>(WebSocketMessageType::Open,
WebSocketMessageType::Open, "", 0, "",
0,
WebSocketErrorInfo(), WebSocketErrorInfo(),
WebSocketOpenInfo(status.uri, status.headers), WebSocketOpenInfo(status.uri, status.headers),
WebSocketCloseInfo())); WebSocketCloseInfo()));
@ -218,8 +219,9 @@ namespace ix
} }
_onMessageCallback( _onMessageCallback(
std::make_shared<WebSocketMessage>( std::make_shared<WebSocketMessage>(WebSocketMessageType::Open,
WebSocketMessageType::Open, "", 0, "",
0,
WebSocketErrorInfo(), WebSocketErrorInfo(),
WebSocketOpenInfo(status.uri, status.headers), WebSocketOpenInfo(status.uri, status.headers),
WebSocketCloseInfo())); WebSocketCloseInfo()));
@ -236,8 +238,7 @@ namespace ix
return getReadyState() == ReadyState::Closing; return getReadyState() == ReadyState::Closing;
} }
void WebSocket::close(uint16_t code, void WebSocket::close(uint16_t code, const std::string& reason)
const std::string& reason)
{ {
_ws.close(code, reason); _ws.close(code, reason);
} }
@ -281,7 +282,8 @@ namespace ix
if (_automaticReconnection) if (_automaticReconnection)
{ {
duration = millis(calculateRetryWaitMilliseconds(retries++, _maxWaitBetweenReconnectionRetries)); duration = millis(calculateRetryWaitMilliseconds(
retries++, _maxWaitBetweenReconnectionRetries));
connectErr.wait_time = duration.count(); connectErr.wait_time = duration.count();
connectErr.retries = retries; connectErr.retries = retries;
@ -290,10 +292,11 @@ namespace ix
connectErr.reason = status.errorStr; connectErr.reason = status.errorStr;
connectErr.http_status = status.http_status; connectErr.http_status = status.http_status;
_onMessageCallback( _onMessageCallback(std::make_shared<WebSocketMessage>(WebSocketMessageType::Error,
std::make_shared<WebSocketMessage>( "",
WebSocketMessageType::Error, "", 0, 0,
connectErr, WebSocketOpenInfo(), connectErr,
WebSocketOpenInfo(),
WebSocketCloseInfo())); WebSocketCloseInfo()));
} }
} }
@ -330,8 +333,7 @@ namespace ix
[this](const std::string& msg, [this](const std::string& msg,
size_t wireSize, size_t wireSize,
bool decompressionError, bool decompressionError,
WebSocketTransport::MessageKind messageKind) WebSocketTransport::MessageKind messageKind) {
{
WebSocketMessageType webSocketMessageType; WebSocketMessageType webSocketMessageType;
switch (messageKind) switch (messageKind)
{ {
@ -339,22 +341,26 @@ namespace ix
case WebSocketTransport::MessageKind::MSG_BINARY: case WebSocketTransport::MessageKind::MSG_BINARY:
{ {
webSocketMessageType = WebSocketMessageType::Message; webSocketMessageType = WebSocketMessageType::Message;
} break; }
break;
case WebSocketTransport::MessageKind::PING: case WebSocketTransport::MessageKind::PING:
{ {
webSocketMessageType = WebSocketMessageType::Ping; webSocketMessageType = WebSocketMessageType::Ping;
} break; }
break;
case WebSocketTransport::MessageKind::PONG: case WebSocketTransport::MessageKind::PONG:
{ {
webSocketMessageType = WebSocketMessageType::Pong; webSocketMessageType = WebSocketMessageType::Pong;
} break; }
break;
case WebSocketTransport::MessageKind::FRAGMENT: case WebSocketTransport::MessageKind::FRAGMENT:
{ {
webSocketMessageType = WebSocketMessageType::Fragment; webSocketMessageType = WebSocketMessageType::Fragment;
} break; }
break;
} }
WebSocketErrorInfo webSocketErrorInfo; WebSocketErrorInfo webSocketErrorInfo;
@ -362,11 +368,13 @@ namespace ix
bool binary = messageKind == WebSocketTransport::MessageKind::MSG_BINARY; bool binary = messageKind == WebSocketTransport::MessageKind::MSG_BINARY;
_onMessageCallback( _onMessageCallback(std::make_shared<WebSocketMessage>(webSocketMessageType,
std::make_shared<WebSocketMessage>( msg,
webSocketMessageType, msg, wireSize, wireSize,
webSocketErrorInfo, WebSocketOpenInfo(), webSocketErrorInfo,
WebSocketCloseInfo(), binary)); WebSocketOpenInfo(),
WebSocketCloseInfo(),
binary));
WebSocket::invokeTrafficTrackerCallback(msg.size(), true); WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
}); });
@ -453,17 +461,20 @@ namespace ix
case SendMessageKind::Text: case SendMessageKind::Text:
{ {
webSocketSendInfo = _ws.sendText(text, onProgressCallback); webSocketSendInfo = _ws.sendText(text, onProgressCallback);
} break; }
break;
case SendMessageKind::Binary: case SendMessageKind::Binary:
{ {
webSocketSendInfo = _ws.sendBinary(text, onProgressCallback); webSocketSendInfo = _ws.sendBinary(text, onProgressCallback);
} break; }
break;
case SendMessageKind::Ping: case SendMessageKind::Ping:
{ {
webSocketSendInfo = _ws.sendPing(text); webSocketSendInfo = _ws.sendPing(text);
} break; }
break;
} }
WebSocket::invokeTrafficTrackerCallback(webSocketSendInfo.wireSize, false); WebSocket::invokeTrafficTrackerCallback(webSocketSendInfo.wireSize, false);
@ -514,4 +525,4 @@ namespace ix
{ {
return _ws.bufferedAmount(); return _ws.bufferedAmount();
} }
} } // namespace ix

View File

@ -22,10 +22,15 @@ namespace ix
const std::string WebSocketCloseConstants::kProtocolErrorMessage("Protocol error"); const std::string WebSocketCloseConstants::kProtocolErrorMessage("Protocol error");
const std::string WebSocketCloseConstants::kNoStatusCodeErrorMessage("No status code"); const std::string WebSocketCloseConstants::kNoStatusCodeErrorMessage("No status code");
const std::string WebSocketCloseConstants::kProtocolErrorReservedBitUsed("Reserved bit used"); const std::string WebSocketCloseConstants::kProtocolErrorReservedBitUsed("Reserved bit used");
const std::string WebSocketCloseConstants::kProtocolErrorPingPayloadOversized("Ping reason control frame with payload length > 125 octets"); const std::string WebSocketCloseConstants::kProtocolErrorPingPayloadOversized(
const std::string WebSocketCloseConstants::kProtocolErrorCodeControlMessageFragmented("Control message fragmented"); "Ping reason control frame with payload length > 125 octets");
const std::string WebSocketCloseConstants::kProtocolErrorCodeDataOpcodeOutOfSequence("Fragmentation: data message out of sequence"); const std::string WebSocketCloseConstants::kProtocolErrorCodeControlMessageFragmented(
const std::string WebSocketCloseConstants::kProtocolErrorCodeContinuationOpCodeOutOfSequence("Fragmentation: continuation opcode out of sequence"); "Control message fragmented");
const std::string WebSocketCloseConstants::kInvalidFramePayloadDataMessage("Invalid frame payload data"); const std::string WebSocketCloseConstants::kProtocolErrorCodeDataOpcodeOutOfSequence(
"Fragmentation: data message out of sequence");
const std::string WebSocketCloseConstants::kProtocolErrorCodeContinuationOpCodeOutOfSequence(
"Fragmentation: continuation opcode out of sequence");
const std::string WebSocketCloseConstants::kInvalidFramePayloadDataMessage(
"Invalid frame payload data");
const std::string WebSocketCloseConstants::kInvalidCloseCodeMessage("Invalid close code"); const std::string WebSocketCloseConstants::kInvalidCloseCodeMessage("Invalid close code");
} } // namespace ix

View File

@ -5,48 +5,43 @@
*/ */
#include "IXWebSocketHandshake.h" #include "IXWebSocketHandshake.h"
#include "IXHttp.h"
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include "IXUrlParser.h" #include "IXUrlParser.h"
#include "IXHttp.h"
#include "IXUserAgent.h" #include "IXUserAgent.h"
#include "libwshandshake.hpp" #include "libwshandshake.hpp"
#include <sstream>
#include <random>
#include <algorithm> #include <algorithm>
#include <random>
#include <sstream>
namespace ix namespace ix
{ {
WebSocketHandshake::WebSocketHandshake(std::atomic<bool>& requestInitCancellation, WebSocketHandshake::WebSocketHandshake(
std::atomic<bool>& requestInitCancellation,
std::shared_ptr<Socket> socket, std::shared_ptr<Socket> socket,
WebSocketPerMessageDeflate& perMessageDeflate, WebSocketPerMessageDeflate& perMessageDeflate,
WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
std::atomic<bool>& enablePerMessageDeflate) : std::atomic<bool>& enablePerMessageDeflate)
_requestInitCancellation(requestInitCancellation), : _requestInitCancellation(requestInitCancellation)
_socket(socket), , _socket(socket)
_perMessageDeflate(perMessageDeflate), , _perMessageDeflate(perMessageDeflate)
_perMessageDeflateOptions(perMessageDeflateOptions), , _perMessageDeflateOptions(perMessageDeflateOptions)
_enablePerMessageDeflate(enablePerMessageDeflate) , _enablePerMessageDeflate(enablePerMessageDeflate)
{ {
} }
bool WebSocketHandshake::insensitiveStringCompare(const std::string& a, const std::string& b) bool WebSocketHandshake::insensitiveStringCompare(const std::string& a, const std::string& b)
{ {
return std::equal(a.begin(), a.end(), return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) {
b.begin(), b.end(),
[](char a, char b)
{
return tolower(a) == tolower(b); return tolower(a) == tolower(b);
}); });
} }
std::string WebSocketHandshake::genRandomString(const int len) std::string WebSocketHandshake::genRandomString(const int len)
{ {
std::string alphanum = std::string alphanum = "0123456789"
"0123456789"
"ABCDEFGH" "ABCDEFGH"
"abcdefgh"; "abcdefgh";
@ -88,7 +83,8 @@ namespace ix
return WebSocketInitResult(false, code, reason); return WebSocketInitResult(false, code, reason);
} }
WebSocketInitResult WebSocketHandshake::clientHandshake(const std::string& url, WebSocketInitResult WebSocketHandshake::clientHandshake(
const std::string& url,
const WebSocketHttpHeaders& extraHeaders, const WebSocketHttpHeaders& extraHeaders,
const std::string& host, const std::string& host,
const std::string& path, const std::string& path,
@ -105,9 +101,7 @@ namespace ix
if (!success) if (!success)
{ {
std::stringstream ss; std::stringstream ss;
ss << "Unable to connect to " << host ss << "Unable to connect to " << host << " on port " << port << ", error: " << errMsg;
<< " on port " << port
<< ", error: " << errMsg;
return WebSocketInitResult(false, 0, ss.str()); return WebSocketInitResult(false, 0, ss.str());
} }
@ -149,7 +143,8 @@ namespace ix
if (!_socket->writeBytes(ss.str(), isCancellationRequested)) if (!_socket->writeBytes(ss.str(), isCancellationRequested))
{ {
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 HTTP status line // Read HTTP status line
@ -159,8 +154,8 @@ namespace ix
if (!lineValid) if (!lineValid)
{ {
return WebSocketInitResult(false, 0, return WebSocketInitResult(
std::string("Failed reading HTTP status line from ") + url); false, 0, std::string("Failed reading HTTP status line from ") + url);
} }
// Validate status // Validate status
@ -173,8 +168,7 @@ namespace ix
{ {
std::stringstream ss; std::stringstream ss;
ss << "Expecting HTTP/1.1, got " << httpVersion << ". " ss << "Expecting HTTP/1.1, got " << httpVersion << ". "
<< "Rejecting connection to " << host << ":" << port << "Rejecting connection to " << host << ":" << port << ", status: " << status
<< ", status: " << status
<< ", HTTP Status line: " << line; << ", HTTP Status line: " << line;
return WebSocketInitResult(false, status, ss.str()); return WebSocketInitResult(false, status, ss.str());
} }
@ -183,8 +177,7 @@ namespace ix
if (status != 101) if (status != 101)
{ {
std::stringstream ss; std::stringstream ss;
ss << "Got bad status connecting to " << host << ":" << port ss << "Got bad status connecting to " << host << ":" << port << ", status: " << status
<< ", status: " << status
<< ", HTTP Status line: " << line; << ", HTTP Status line: " << line;
return WebSocketInitResult(false, status, ss.str()); return WebSocketInitResult(false, status, ss.str());
} }
@ -280,7 +273,8 @@ namespace ix
if (httpVersion != "HTTP/1.1") if (httpVersion != "HTTP/1.1")
{ {
return sendErrorResponse(400, "Invalid HTTP version, need HTTP/1.1, got: " + httpVersion); return sendErrorResponse(400,
"Invalid HTTP version, need HTTP/1.1, got: " + httpVersion);
} }
// Retrieve and validate HTTP headers // Retrieve and validate HTTP headers
@ -305,8 +299,10 @@ namespace ix
if (!insensitiveStringCompare(headers["upgrade"], "WebSocket")) if (!insensitiveStringCompare(headers["upgrade"], "WebSocket"))
{ {
return sendErrorResponse(400, "Invalid Upgrade header, " return sendErrorResponse(400,
"need WebSocket, got " + headers["upgrade"]); "Invalid Upgrade header, "
"need WebSocket, got " +
headers["upgrade"]);
} }
if (headers.find("sec-websocket-version") == headers.end()) if (headers.find("sec-websocket-version") == headers.end())
@ -322,8 +318,10 @@ namespace ix
if (version != 13) if (version != 13)
{ {
return sendErrorResponse(400, "Invalid Sec-WebSocket-Version, " return sendErrorResponse(400,
"need 13, got " + ss.str()); "Invalid Sec-WebSocket-Version, "
"need 13, got " +
ss.str());
} }
} }
@ -358,9 +356,10 @@ namespace ix
if (!_socket->writeBytes(ss.str(), isCancellationRequested)) if (!_socket->writeBytes(ss.str(), isCancellationRequested))
{ {
return WebSocketInitResult(false, 0, std::string("Failed sending response to ") + remote); return WebSocketInitResult(
false, 0, std::string("Failed sending response to ") + remote);
} }
return WebSocketInitResult(true, 200, "", headers, uri); return WebSocketInitResult(true, 200, "", headers, uri);
} }
} } // namespace ix

View File

@ -49,8 +49,7 @@ namespace ix
WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
std::atomic<bool>& enablePerMessageDeflate); std::atomic<bool>& enablePerMessageDeflate);
WebSocketInitResult clientHandshake( WebSocketInitResult clientHandshake(const std::string& url,
const std::string& url,
const WebSocketHttpHeaders& extraHeaders, const WebSocketHttpHeaders& extraHeaders,
const std::string& host, const std::string& host,
const std::string& path, const std::string& path,

View File

@ -5,13 +5,15 @@
*/ */
#include "IXWebSocketHttpHeaders.h" #include "IXWebSocketHttpHeaders.h"
#include "IXSocket.h" #include "IXSocket.h"
#include <algorithm> #include <algorithm>
#include <locale> #include <locale>
namespace ix namespace ix
{ {
bool CaseInsensitiveLess::NocaseCompare::operator()(const unsigned char & c1, const unsigned char & c2) const bool CaseInsensitiveLess::NocaseCompare::operator()(const unsigned char& c1,
const unsigned char& c2) const
{ {
#ifdef _WIN32 #ifdef _WIN32
return std::tolower(c1, std::locale()) < std::tolower(c2, std::locale()); return std::tolower(c1, std::locale()) < std::tolower(c2, std::locale());
@ -22,15 +24,15 @@ namespace ix
bool CaseInsensitiveLess::operator()(const std::string& s1, const std::string& s2) const bool CaseInsensitiveLess::operator()(const std::string& s1, const std::string& s2) const
{ {
return std::lexicographical_compare return std::lexicographical_compare(s1.begin(),
(s1.begin(), s1.end(), // source range s1.end(), // source range
s2.begin(), s2.end(), // dest range s2.begin(),
s2.end(), // dest range
NocaseCompare()); // comparison NocaseCompare()); // comparison
} }
std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders( std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders(
std::shared_ptr<Socket> socket, std::shared_ptr<Socket> socket, const CancellationRequest& isCancellationRequested)
const CancellationRequest& isCancellationRequested)
{ {
WebSocketHttpHeaders headers; WebSocketHttpHeaders headers;
@ -41,9 +43,7 @@ namespace ix
{ {
int colon = 0; int colon = 0;
for (i = 0; for (i = 0; i < 2 || (i < 1023 && line[i - 2] != '\r' && line[i - 1] != '\n'); ++i)
i < 2 || (i < 1023 && line[i-2] != '\r' && line[i-1] != '\n');
++i)
{ {
if (!socket->readByte(line + i, isCancellationRequested)) if (!socket->readByte(line + i, isCancellationRequested))
{ {
@ -79,4 +79,4 @@ namespace ix
return std::make_pair(true, headers); return std::make_pair(true, headers);
} }
} } // namespace ix

View File

@ -8,7 +8,6 @@
namespace ix namespace ix
{ {
WebSocketMessageQueue::WebSocketMessageQueue(WebSocket* websocket) WebSocketMessageQueue::WebSocketMessageQueue(WebSocket* websocket)
{ {
bindWebsocket(websocket); bindWebsocket(websocket);
@ -40,8 +39,7 @@ namespace ix
// bind new // bind new
if (_websocket) if (_websocket)
{ {
_websocket->setOnMessageCallback([this](const WebSocketMessagePtr& msg) _websocket->setOnMessageCallback([this](const WebSocketMessagePtr& msg) {
{
std::lock_guard<std::mutex> lock(_messagesMutex); std::lock_guard<std::mutex> lock(_messagesMutex);
_messages.emplace_back(std::move(msg)); _messages.emplace_back(std::move(msg));
}); });
@ -74,8 +72,7 @@ namespace ix
void WebSocketMessageQueue::poll(int count) void WebSocketMessageQueue::poll(int count)
{ {
if (!_onMessageUserCallback) if (!_onMessageUserCallback) return;
return;
WebSocketMessagePtr message; WebSocketMessagePtr message;
@ -86,4 +83,4 @@ namespace ix
} }
} }
} } // namespace ix

View File

@ -41,19 +41,21 @@
* - Added more documentation. * - Added more documentation.
* *
* Per message Deflate RFC: https://tools.ietf.org/html/rfc7692 * Per message Deflate RFC: https://tools.ietf.org/html/rfc7692
* Chrome websocket -> https://github.com/chromium/chromium/tree/2ca8c5037021c9d2ecc00b787d58a31ed8fc8bcb/net/websockets * Chrome websocket ->
* https://github.com/chromium/chromium/tree/2ca8c5037021c9d2ecc00b787d58a31ed8fc8bcb/net/websockets
* *
*/ */
#include "IXWebSocketPerMessageDeflate.h" #include "IXWebSocketPerMessageDeflate.h"
#include "IXWebSocketPerMessageDeflateOptions.h"
#include "IXWebSocketPerMessageDeflateCodec.h" #include "IXWebSocketPerMessageDeflateCodec.h"
#include "IXWebSocketPerMessageDeflateOptions.h"
namespace ix namespace ix
{ {
WebSocketPerMessageDeflate::WebSocketPerMessageDeflate() : WebSocketPerMessageDeflate::WebSocketPerMessageDeflate()
_compressor(std::make_unique<WebSocketPerMessageDeflateCompressor>()), : _compressor(std::make_unique<WebSocketPerMessageDeflateCompressor>())
_decompressor(std::make_unique<WebSocketPerMessageDeflateDecompressor>()) , _decompressor(std::make_unique<WebSocketPerMessageDeflateDecompressor>())
{ {
; ;
} }
@ -63,10 +65,10 @@ namespace ix
; ;
} }
bool WebSocketPerMessageDeflate::init(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions) bool WebSocketPerMessageDeflate::init(
const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions)
{ {
bool clientNoContextTakeover = bool clientNoContextTakeover = perMessageDeflateOptions.getClientNoContextTakeover();
perMessageDeflateOptions.getClientNoContextTakeover();
uint8_t deflateBits = perMessageDeflateOptions.getClientMaxWindowBits(); uint8_t deflateBits = perMessageDeflateOptions.getClientMaxWindowBits();
uint8_t inflateBits = perMessageDeflateOptions.getServerMaxWindowBits(); uint8_t inflateBits = perMessageDeflateOptions.getServerMaxWindowBits();
@ -75,16 +77,14 @@ namespace ix
_decompressor->init(inflateBits, clientNoContextTakeover); _decompressor->init(inflateBits, clientNoContextTakeover);
} }
bool WebSocketPerMessageDeflate::compress(const std::string& in, bool WebSocketPerMessageDeflate::compress(const std::string& in, std::string& out)
std::string& out)
{ {
return _compressor->compress(in, out); return _compressor->compress(in, out);
} }
bool WebSocketPerMessageDeflate::decompress(const std::string& in, bool WebSocketPerMessageDeflate::decompress(const std::string& in, std::string& out)
std::string &out)
{ {
return _decompressor->decompress(in, out); return _decompressor->decompress(in, out);
} }
} } // namespace ix

View File

@ -5,8 +5,8 @@
*/ */
#include "IXWebSocketPerMessageDeflateCodec.h" #include "IXWebSocketPerMessageDeflateCodec.h"
#include "IXWebSocketPerMessageDeflateOptions.h"
#include "IXWebSocketPerMessageDeflateOptions.h"
#include <cassert> #include <cassert>
#include <string.h> #include <string.h>
@ -18,7 +18,7 @@ namespace
const std::string kEmptyUncompressedBlock = std::string("\x00\x00\xff\xff", 4); const std::string kEmptyUncompressedBlock = std::string("\x00\x00\xff\xff", 4);
const int kBufferSize = 1 << 14; const int kBufferSize = 1 << 14;
} } // namespace
namespace ix namespace ix
{ {
@ -43,22 +43,18 @@ namespace ix
bool WebSocketPerMessageDeflateCompressor::init(uint8_t deflateBits, bool WebSocketPerMessageDeflateCompressor::init(uint8_t deflateBits,
bool clientNoContextTakeOver) bool clientNoContextTakeOver)
{ {
int ret = deflateInit2( int ret = deflateInit2(&_deflateState,
&_deflateState,
Z_DEFAULT_COMPRESSION, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, Z_DEFLATED,
-1 * deflateBits, -1 * deflateBits,
4, // memory level 1-9 4, // memory level 1-9
Z_DEFAULT_STRATEGY Z_DEFAULT_STRATEGY);
);
if (ret != Z_OK) return false; if (ret != Z_OK) return false;
_compressBuffer = std::make_unique<unsigned char[]>(_compressBufferSize); _compressBuffer = std::make_unique<unsigned char[]>(_compressBufferSize);
_flush = (clientNoContextTakeOver) _flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH;
? Z_FULL_FLUSH
: Z_SYNC_FLUSH;
return true; return true;
} }
@ -70,8 +66,7 @@ namespace ix
return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
} }
bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in, bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in, std::string& out)
std::string& out)
{ {
// //
// 7.2.1. Compression // 7.2.1. Compression
@ -146,24 +141,18 @@ namespace ix
bool WebSocketPerMessageDeflateDecompressor::init(uint8_t inflateBits, bool WebSocketPerMessageDeflateDecompressor::init(uint8_t inflateBits,
bool clientNoContextTakeOver) bool clientNoContextTakeOver)
{ {
int ret = inflateInit2( int ret = inflateInit2(&_inflateState, -1 * inflateBits);
&_inflateState,
-1*inflateBits
);
if (ret != Z_OK) return false; if (ret != Z_OK) return false;
_compressBuffer = std::make_unique<unsigned char[]>(_compressBufferSize); _compressBuffer = std::make_unique<unsigned char[]>(_compressBufferSize);
_flush = (clientNoContextTakeOver) _flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH;
? Z_FULL_FLUSH
: Z_SYNC_FLUSH;
return true; return true;
} }
bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string& in, bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string& in, std::string& out)
std::string& out)
{ {
// //
// 7.2.2. Decompression // 7.2.2. Decompression
@ -193,13 +182,10 @@ namespace ix
return false; // zlib error return false; // zlib error
} }
out.append( out.append(reinterpret_cast<char*>(_compressBuffer.get()),
reinterpret_cast<char *>(_compressBuffer.get()), _compressBufferSize - _inflateState.avail_out);
_compressBufferSize - _inflateState.avail_out
);
} while (_inflateState.avail_out == 0); } while (_inflateState.avail_out == 0);
return true; return true;
} }
} } // namespace ix

View File

@ -6,9 +6,9 @@
#include "IXWebSocketPerMessageDeflateOptions.h" #include "IXWebSocketPerMessageDeflateOptions.h"
#include <sstream>
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <sstream>
namespace ix namespace ix
{ {
@ -48,7 +48,8 @@ namespace ix
// //
// Server response could look like that: // Server response could look like that:
// //
// Sec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover; server_no_context_takeover // Sec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover;
// server_no_context_takeover
// //
WebSocketPerMessageDeflateOptions::WebSocketPerMessageDeflateOptions(std::string extension) WebSocketPerMessageDeflateOptions::WebSocketPerMessageDeflateOptions(std::string extension)
{ {
@ -92,8 +93,7 @@ namespace ix
// Sanitize values to be in the proper range [8, 15] in // Sanitize values to be in the proper range [8, 15] in
// case a server would give us bogus values // case a server would give us bogus values
_serverMaxWindowBits = _serverMaxWindowBits =
std::min(maxServerMaxWindowBits, std::min(maxServerMaxWindowBits, std::max(x, minServerMaxWindowBits));
std::max(x, minServerMaxWindowBits));
} }
if (startsWith(token, "client_max_window_bits=")) if (startsWith(token, "client_max_window_bits="))
@ -107,8 +107,7 @@ namespace ix
// Sanitize values to be in the proper range [8, 15] in // Sanitize values to be in the proper range [8, 15] in
// case a server would give us bogus values // case a server would give us bogus values
_clientMaxWindowBits = _clientMaxWindowBits =
std::min(maxClientMaxWindowBits, std::min(maxClientMaxWindowBits, std::max(x, minClientMaxWindowBits));
std::max(x, minClientMaxWindowBits));
sanitizeClientMaxWindowBits(); sanitizeClientMaxWindowBits();
} }
@ -175,11 +174,10 @@ namespace ix
std::string WebSocketPerMessageDeflateOptions::removeSpaces(const std::string& str) std::string WebSocketPerMessageDeflateOptions::removeSpaces(const std::string& str)
{ {
std::string out(str); std::string out(str);
out.erase(std::remove_if(out.begin(), out.erase(
out.end(), std::remove_if(out.begin(), out.end(), [](unsigned char x) { return std::isspace(x); }),
[](unsigned char x){ return std::isspace(x); }),
out.end()); out.end());
return out; return out;
} }
} } // namespace ix

View File

@ -5,13 +5,13 @@
*/ */
#include "IXWebSocketServer.h" #include "IXWebSocketServer.h"
#include "IXWebSocketTransport.h"
#include "IXWebSocket.h"
#include "IXSocketConnect.h"
#include "IXNetSystem.h"
#include <sstream> #include "IXNetSystem.h"
#include "IXSocketConnect.h"
#include "IXWebSocket.h"
#include "IXWebSocketTransport.h"
#include <future> #include <future>
#include <sstream>
#include <string.h> #include <string.h>
namespace ix namespace ix
@ -23,11 +23,11 @@ namespace ix
const std::string& host, const std::string& host,
int backlog, int backlog,
size_t maxConnections, size_t maxConnections,
int handshakeTimeoutSecs) : SocketServer(port, host, backlog, maxConnections), int handshakeTimeoutSecs)
_handshakeTimeoutSecs(handshakeTimeoutSecs), : SocketServer(port, host, backlog, maxConnections)
_enablePong(kDefaultEnablePong) , _handshakeTimeoutSecs(handshakeTimeoutSecs)
, _enablePong(kDefaultEnablePong)
{ {
} }
WebSocketServer::~WebSocketServer() WebSocketServer::~WebSocketServer()
@ -63,9 +63,7 @@ namespace ix
_onConnectionCallback = callback; _onConnectionCallback = callback;
} }
void WebSocketServer::handleConnection( void WebSocketServer::handleConnection(int fd, std::shared_ptr<ConnectionState> connectionState)
int fd,
std::shared_ptr<ConnectionState> connectionState)
{ {
auto webSocket = std::make_shared<WebSocket>(); auto webSocket = std::make_shared<WebSocket>();
_onConnectionCallback(webSocket, connectionState); _onConnectionCallback(webSocket, connectionState);
@ -93,10 +91,8 @@ namespace ix
else else
{ {
std::stringstream ss; std::stringstream ss;
ss << "WebSocketServer::handleConnection() HTTP status: " ss << "WebSocketServer::handleConnection() HTTP status: " << status.http_status
<< status.http_status << " error: " << status.errorStr;
<< " error: "
<< status.errorStr;
logError(ss.str()); logError(ss.str());
} }
@ -126,4 +122,4 @@ namespace ix
std::lock_guard<std::mutex> lock(_clientsMutex); std::lock_guard<std::mutex> lock(_clientsMutex);
return _clients.size(); return _clients.size();
} }
} } // namespace ix

View File

@ -32,24 +32,23 @@
// Adapted from https://github.com/dhbaird/easywsclient // Adapted from https://github.com/dhbaird/easywsclient
// //
#include "IXSocketTLSOptions.h"
#include "IXWebSocketTransport.h" #include "IXWebSocketTransport.h"
#include "IXSocketFactory.h"
#include "IXSocketTLSOptions.h"
#include "IXUrlParser.h"
#include "IXUtf8Validator.h"
#include "IXWebSocketHandshake.h" #include "IXWebSocketHandshake.h"
#include "IXWebSocketHttpHeaders.h" #include "IXWebSocketHttpHeaders.h"
#include "IXUrlParser.h"
#include "IXSocketFactory.h"
#include "IXUtf8Validator.h"
#include <string.h>
#include <stdlib.h>
#include <cstdlib>
#include <vector>
#include <string>
#include <cstdarg>
#include <sstream>
#include <chrono> #include <chrono>
#include <cstdarg>
#include <cstdlib>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <thread> #include <thread>
#include <vector>
namespace namespace
@ -65,7 +64,7 @@ namespace
return a; return a;
} }
} } // namespace
namespace ix namespace ix
{ {
@ -76,24 +75,24 @@ namespace ix
const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300); const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300);
constexpr size_t WebSocketTransport::kChunkSize; constexpr size_t WebSocketTransport::kChunkSize;
WebSocketTransport::WebSocketTransport() : WebSocketTransport::WebSocketTransport()
_useMask(true), : _useMask(true)
_compressedMessage(false), , _compressedMessage(false)
_readyState(ReadyState::CLOSED), , _readyState(ReadyState::CLOSED)
_closeCode(WebSocketCloseConstants::kInternalErrorCode), , _closeCode(WebSocketCloseConstants::kInternalErrorCode)
_closeReason(WebSocketCloseConstants::kInternalErrorMessage), , _closeReason(WebSocketCloseConstants::kInternalErrorMessage)
_closeWireSize(0), , _closeWireSize(0)
_closeRemote(false), , _closeRemote(false)
_enablePerMessageDeflate(false), , _enablePerMessageDeflate(false)
_requestInitCancellation(false), , _requestInitCancellation(false)
_closingTimePoint(std::chrono::steady_clock::now()), , _closingTimePoint(std::chrono::steady_clock::now())
_enablePong(kDefaultEnablePong), , _enablePong(kDefaultEnablePong)
_pingIntervalSecs(kDefaultPingIntervalSecs), , _pingIntervalSecs(kDefaultPingIntervalSecs)
_pingTimeoutSecs(kDefaultPingTimeoutSecs), , _pingTimeoutSecs(kDefaultPingTimeoutSecs)
_pingIntervalOrTimeoutGCDSecs(-1), , _pingIntervalOrTimeoutGCDSecs(-1)
_nextGCDTimePoint(std::chrono::steady_clock::now()), , _nextGCDTimePoint(std::chrono::steady_clock::now())
_lastSendPingTimePoint(std::chrono::steady_clock::now()), , _lastSendPingTimePoint(std::chrono::steady_clock::now())
_lastReceivePongTimePoint(std::chrono::steady_clock::now()) , _lastReceivePongTimePoint(std::chrono::steady_clock::now())
{ {
_readbuf.resize(kChunkSize); _readbuf.resize(kChunkSize);
} }
@ -103,7 +102,8 @@ namespace ix
; ;
} }
void WebSocketTransport::configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, void WebSocketTransport::configure(
const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
const SocketTLSOptions& socketTLSOptions, const SocketTLSOptions& socketTLSOptions,
bool enablePong, bool enablePong,
int pingIntervalSecs, int pingIntervalSecs,
@ -118,8 +118,8 @@ namespace ix
if (pingIntervalSecs > 0 && pingTimeoutSecs > 0) if (pingIntervalSecs > 0 && pingTimeoutSecs > 0)
{ {
_pingIntervalOrTimeoutGCDSecs = greatestCommonDivisor(pingIntervalSecs, _pingIntervalOrTimeoutGCDSecs =
pingTimeoutSecs); greatestCommonDivisor(pingIntervalSecs, pingTimeoutSecs);
} }
else if (_pingTimeoutSecs > 0) else if (_pingTimeoutSecs > 0)
{ {
@ -132,8 +132,7 @@ namespace ix
} }
// Client // Client
WebSocketInitResult WebSocketTransport::connectToUrl( WebSocketInitResult WebSocketTransport::connectToUrl(const std::string& url,
const std::string& url,
const WebSocketHttpHeaders& headers, const WebSocketHttpHeaders& headers,
int timeoutSecs) int timeoutSecs)
{ {
@ -144,8 +143,7 @@ namespace ix
if (!UrlParser::parse(url, protocol, host, path, query, port)) if (!UrlParser::parse(url, protocol, host, path, query, port))
{ {
return WebSocketInitResult(false, 0, return WebSocketInitResult(false, 0, std::string("Could not parse URL ") + url);
std::string("Could not parse URL ") + url);
} }
std::string errorMsg; std::string errorMsg;
@ -163,8 +161,8 @@ namespace ix
_perMessageDeflateOptions, _perMessageDeflateOptions,
_enablePerMessageDeflate); _enablePerMessageDeflate);
auto result = webSocketHandshake.clientHandshake(url, headers, host, path, auto result =
port, timeoutSecs); webSocketHandshake.clientHandshake(url, headers, host, path, port, timeoutSecs);
if (result.success) if (result.success)
{ {
setReadyState(ReadyState::OPEN); setReadyState(ReadyState::OPEN);
@ -247,15 +245,15 @@ namespace ix
if (_pingIntervalOrTimeoutGCDSecs > 0) if (_pingIntervalOrTimeoutGCDSecs > 0)
{ {
_nextGCDTimePoint = std::chrono::steady_clock::now() + std::chrono::seconds(_pingIntervalOrTimeoutGCDSecs); _nextGCDTimePoint = std::chrono::steady_clock::now() +
std::chrono::seconds(_pingIntervalOrTimeoutGCDSecs);
} }
} }
// Only consider send PING time points for that computation. // Only consider send PING time points for that computation.
bool WebSocketTransport::pingIntervalExceeded() bool WebSocketTransport::pingIntervalExceeded()
{ {
if (_pingIntervalSecs <= 0) if (_pingIntervalSecs <= 0) return false;
return false;
std::lock_guard<std::mutex> lock(_lastSendPingTimePointMutex); std::lock_guard<std::mutex> lock(_lastSendPingTimePointMutex);
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
@ -264,8 +262,7 @@ namespace ix
bool WebSocketTransport::pingTimeoutExceeded() bool WebSocketTransport::pingTimeoutExceeded()
{ {
if (_pingTimeoutSecs <= 0) if (_pingTimeoutSecs <= 0) return false;
return false;
std::lock_guard<std::mutex> lock(_lastReceivePongTimePointMutex); std::lock_guard<std::mutex> lock(_lastReceivePongTimePointMutex);
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
@ -302,7 +299,8 @@ namespace ix
// No timeout if state is not OPEN, otherwise computed // No timeout if state is not OPEN, otherwise computed
// pingIntervalOrTimeoutGCD (equals to -1 if no ping and no ping timeout are set) // pingIntervalOrTimeoutGCD (equals to -1 if no ping and no ping timeout are set)
int lastingTimeoutDelayInMs = (_readyState != ReadyState::OPEN) ? 0 : _pingIntervalOrTimeoutGCDSecs; int lastingTimeoutDelayInMs =
(_readyState != ReadyState::OPEN) ? 0 : _pingIntervalOrTimeoutGCDSecs;
if (_pingIntervalOrTimeoutGCDSecs > 0) if (_pingIntervalOrTimeoutGCDSecs > 0)
{ {
@ -317,7 +315,10 @@ namespace ix
} }
else else
{ {
lastingTimeoutDelayInMs = (int)std::chrono::duration_cast<std::chrono::milliseconds>(_nextGCDTimePoint - now).count(); lastingTimeoutDelayInMs =
(int) std::chrono::duration_cast<std::chrono::milliseconds>(_nextGCDTimePoint -
now)
.count();
} }
} }
@ -373,8 +374,9 @@ namespace ix
} }
else if (ret <= 0) else if (ret <= 0)
{ {
// if there are received data pending to be processed, then delay the abnormal closure // if there are received data pending to be processed, then delay the abnormal
// to after dispatch (other close code/reason could be read from the buffer) // closure to after dispatch (other close code/reason could be read from the
// buffer)
closeSocket(); closeSocket();
@ -382,9 +384,7 @@ namespace ix
} }
else else
{ {
_rxbuf.insert(_rxbuf.end(), _rxbuf.insert(_rxbuf.end(), _readbuf.begin(), _readbuf.begin() + ret);
_readbuf.begin(),
_readbuf.begin() + ret);
} }
} }
} }
@ -482,7 +482,8 @@ namespace ix
ws.opcode = (wsheader_type::opcode_type)(data[0] & 0x0f); ws.opcode = (wsheader_type::opcode_type)(data[0] & 0x0f);
ws.mask = (data[1] & 0x80) == 0x80; ws.mask = (data[1] & 0x80) == 0x80;
ws.N0 = (data[1] & 0x7f); ws.N0 = (data[1] & 0x7f);
ws.header_size = 2 + (ws.N0 == 126? 2 : 0) + (ws.N0 == 127? 8 : 0) + (ws.mask? 4 : 0); ws.header_size =
2 + (ws.N0 == 126 ? 2 : 0) + (ws.N0 == 127 ? 8 : 0) + (ws.mask ? 4 : 0);
if (_rxbuf.size() < ws.header_size) break; /* Need: ws.header_size - _rxbuf.size() */ if (_rxbuf.size() < ws.header_size) break; /* Need: ws.header_size - _rxbuf.size() */
if ((ws.rsv1 && !_enablePerMessageDeflate) || ws.rsv2 || ws.rsv3) if ((ws.rsv1 && !_enablePerMessageDeflate) || ws.rsv2 || ws.rsv3)
@ -551,11 +552,9 @@ namespace ix
return; /* Need: ws.header_size+ws.N - _rxbuf.size() */ return; /* Need: ws.header_size+ws.N - _rxbuf.size() */
} }
if (!ws.fin && ( if (!ws.fin && (ws.opcode == wsheader_type::PING || ws.opcode == wsheader_type::PONG ||
ws.opcode == wsheader_type::PING ws.opcode == wsheader_type::CLOSE))
|| ws.opcode == wsheader_type::PONG {
|| ws.opcode == wsheader_type::CLOSE
)){
// Control messages should not be fragmented // Control messages should not be fragmented
close(WebSocketCloseConstants::kProtocolErrorCode, close(WebSocketCloseConstants::kProtocolErrorCode,
WebSocketCloseConstants::kProtocolErrorCodeControlMessageFragmented); WebSocketCloseConstants::kProtocolErrorCodeControlMessageFragmented);
@ -567,16 +566,13 @@ namespace ix
_rxbuf.begin() + ws.header_size + (size_t) ws.N); _rxbuf.begin() + ws.header_size + (size_t) ws.N);
// We got a whole message, now do something with it: // We got a whole message, now do something with it:
if ( if (ws.opcode == wsheader_type::TEXT_FRAME ||
ws.opcode == wsheader_type::TEXT_FRAME ws.opcode == wsheader_type::BINARY_FRAME ||
|| ws.opcode == wsheader_type::BINARY_FRAME ws.opcode == wsheader_type::CONTINUATION)
|| ws.opcode == wsheader_type::CONTINUATION {
) {
if (ws.opcode != wsheader_type::CONTINUATION) if (ws.opcode != wsheader_type::CONTINUATION)
{ {
_fragmentedMessageKind = _fragmentedMessageKind = (ws.opcode == wsheader_type::TEXT_FRAME)
(ws.opcode == wsheader_type::TEXT_FRAME)
? MessageKind::MSG_TEXT ? MessageKind::MSG_TEXT
: MessageKind::MSG_BINARY; : MessageKind::MSG_BINARY;
@ -592,7 +588,8 @@ namespace ix
else if (_chunks.empty()) else if (_chunks.empty())
{ {
// Continuation message need to follow a non-fin TEXT or BINARY message // Continuation message need to follow a non-fin TEXT or BINARY message
close(WebSocketCloseConstants::kProtocolErrorCode, close(
WebSocketCloseConstants::kProtocolErrorCode,
WebSocketCloseConstants::kProtocolErrorCodeContinuationOpCodeOutOfSequence); WebSocketCloseConstants::kProtocolErrorCodeContinuationOpCodeOutOfSequence);
} }
@ -601,10 +598,8 @@ namespace ix
// //
if (ws.fin && _chunks.empty()) if (ws.fin && _chunks.empty())
{ {
emitMessage(_fragmentedMessageKind, emitMessage(
frameData, _fragmentedMessageKind, frameData, _compressedMessage, onMessageCallback);
_compressedMessage,
onMessageCallback);
_compressedMessage = false; _compressedMessage = false;
} }
@ -621,8 +616,10 @@ namespace ix
if (ws.fin) if (ws.fin)
{ {
emitMessage(_fragmentedMessageKind, getMergedChunks(), emitMessage(_fragmentedMessageKind,
_compressedMessage, onMessageCallback); getMergedChunks(),
_compressedMessage,
onMessageCallback);
_chunks.clear(); _chunks.clear();
_compressedMessage = false; _compressedMessage = false;
@ -690,13 +687,11 @@ namespace ix
// Full list of status code and status range is defined in the dedicated // Full list of status code and status range is defined in the dedicated
// RFC section at https://tools.ietf.org/html/rfc6455#page-45 // RFC section at https://tools.ietf.org/html/rfc6455#page-45
// //
if (code < 1000 || code == 1004 || code == 1006 || if (code < 1000 || code == 1004 || code == 1006 || (code > 1013 && code < 3000))
(code > 1013 && code < 3000))
{ {
// build up an error message containing the bad error code // build up an error message containing the bad error code
std::stringstream ss; std::stringstream ss;
ss << WebSocketCloseConstants::kInvalidCloseCodeMessage ss << WebSocketCloseConstants::kInvalidCloseCodeMessage << ": " << code;
<< ": " << code;
reason = ss.str(); reason = ss.str();
code = WebSocketCloseConstants::kProtocolErrorCode; code = WebSocketCloseConstants::kProtocolErrorCode;
@ -722,8 +717,8 @@ namespace ix
} }
else else
{ {
// we got the CLOSE frame answer from our close, so we can close the connection if // we got the CLOSE frame answer from our close, so we can close the connection
// the code/reason are the same // if the code/reason are the same
bool identicalReason; bool identicalReason;
{ {
std::lock_guard<std::mutex> lock(_closeDataMutex); std::lock_guard<std::mutex> lock(_closeDataMutex);
@ -746,8 +741,7 @@ namespace ix
} }
// Erase the message that has been processed from the input/read buffer // Erase the message that has been processed from the input/read buffer
_rxbuf.erase(_rxbuf.begin(), _rxbuf.erase(_rxbuf.begin(), _rxbuf.begin() + ws.header_size + (size_t) ws.N);
_rxbuf.begin() + ws.header_size + (size_t) ws.N);
} }
// if an abnormal closure was raised in poll, and nothing else triggered a CLOSED state in // if an abnormal closure was raised in poll, and nothing else triggered a CLOSED state in
@ -756,7 +750,8 @@ namespace ix
{ {
_rxbuf.clear(); _rxbuf.clear();
// if we previously closed the connection (CLOSING state), then set state to CLOSED (code/reason were set before) // if we previously closed the connection (CLOSING state), then set state to CLOSED
// (code/reason were set before)
if (_readyState == ReadyState::CLOSING) if (_readyState == ReadyState::CLOSING)
{ {
closeSocket(); closeSocket();
@ -767,7 +762,8 @@ namespace ix
{ {
closeSocketAndSwitchToClosedState(WebSocketCloseConstants::kAbnormalCloseCode, closeSocketAndSwitchToClosedState(WebSocketCloseConstants::kAbnormalCloseCode,
WebSocketCloseConstants::kAbnormalCloseMessage, WebSocketCloseConstants::kAbnormalCloseMessage,
0, false); 0,
false);
} }
} }
} }
@ -832,13 +828,11 @@ namespace ix
{ {
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
auto seconds = auto seconds =
std::chrono::duration_cast<std::chrono::seconds>( std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
now.time_since_epoch()).count();
return static_cast<unsigned>(seconds); return static_cast<unsigned>(seconds);
} }
WebSocketSendInfo WebSocketTransport::sendData( WebSocketSendInfo WebSocketTransport::sendData(wsheader_type::opcode_type type,
wsheader_type::opcode_type type,
const std::string& message, const std::string& message,
bool compress, bool compress,
const OnProgressCallback& onProgressCallback) const OnProgressCallback& onProgressCallback)
@ -950,10 +944,9 @@ namespace ix
masking_key[3] = (x) &0xff; masking_key[3] = (x) &0xff;
std::vector<uint8_t> header; std::vector<uint8_t> header;
header.assign(2 + header.assign(2 + (message_size >= 126 ? 2 : 0) + (message_size >= 65536 ? 6 : 0) +
(message_size >= 126 ? 2 : 0) + (_useMask ? 4 : 0),
(message_size >= 65536 ? 6 : 0) + 0);
(_useMask ? 4 : 0), 0);
header[0] = type; header[0] = type;
// The fin bit indicate that this is the last fragment. Fin is French for end. // The fin bit indicate that this is the last fragment. Fin is French for end.
@ -1017,8 +1010,7 @@ namespace ix
} }
// _txbuf will keep growing until it can be transmitted over the socket: // _txbuf will keep growing until it can be transmitted over the socket:
appendToSendBuffer(header, message_begin, message_end, appendToSendBuffer(header, message_begin, message_end, message_size, masking_key);
message_size, masking_key);
// Now actually send this data // Now actually send this data
sendOnSocket(); sendOnSocket();
@ -1038,22 +1030,20 @@ namespace ix
return info; return info;
} }
WebSocketSendInfo WebSocketTransport::sendBinary( WebSocketSendInfo WebSocketTransport::sendBinary(const std::string& message,
const std::string& message,
const OnProgressCallback& onProgressCallback) const OnProgressCallback& onProgressCallback)
{ {
return sendData(wsheader_type::BINARY_FRAME, message, return sendData(
_enablePerMessageDeflate, onProgressCallback); wsheader_type::BINARY_FRAME, message, _enablePerMessageDeflate, onProgressCallback);
} }
WebSocketSendInfo WebSocketTransport::sendText( WebSocketSendInfo WebSocketTransport::sendText(const std::string& message,
const std::string& message,
const OnProgressCallback& onProgressCallback) const OnProgressCallback& onProgressCallback)
{ {
return sendData(wsheader_type::TEXT_FRAME, message, return sendData(
_enablePerMessageDeflate, onProgressCallback); wsheader_type::TEXT_FRAME, message, _enablePerMessageDeflate, onProgressCallback);
} }
ssize_t WebSocketTransport::send() ssize_t WebSocketTransport::send()
@ -1116,8 +1106,10 @@ namespace ix
_socket->close(); _socket->close();
} }
void WebSocketTransport::closeSocketAndSwitchToClosedState( void WebSocketTransport::closeSocketAndSwitchToClosedState(uint16_t code,
uint16_t code, const std::string& reason, size_t closeWireSize, bool remote) const std::string& reason,
size_t closeWireSize,
bool remote)
{ {
closeSocket(); closeSocket();
@ -1133,8 +1125,10 @@ namespace ix
_requestInitCancellation = false; _requestInitCancellation = false;
} }
void WebSocketTransport::close( void WebSocketTransport::close(uint16_t code,
uint16_t code, const std::string& reason, size_t closeWireSize, bool remote) const std::string& reason,
size_t closeWireSize,
bool remote)
{ {
_requestInitCancellation = true; _requestInitCancellation = true;

View File

@ -25,7 +25,6 @@
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <vector> #include <vector>
namespace ix namespace ix

View File

@ -44,13 +44,22 @@ static bool IsSchemeValid( const std::string& SchemeName )
bool LUrlParser::clParseURL::GetPort(int* OutPort) const bool LUrlParser::clParseURL::GetPort(int* OutPort) const
{ {
if ( !IsValid() ) { return false; } if (!IsValid())
{
return false;
}
int Port = atoi(m_Port.c_str()); int Port = atoi(m_Port.c_str());
if ( Port <= 0 || Port > 65535 ) { return false; } if (Port <= 0 || Port > 65535)
{
return false;
}
if ( OutPort ) { *OutPort = Port; } if (OutPort)
{
*OutPort = Port;
}
return true; return true;
} }
@ -65,7 +74,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
/* /*
* <scheme>:<scheme-specific-part> * <scheme>:<scheme-specific-part>
* <scheme> := [a-z\+\-\.]+ * <scheme> := [a-z\+\-\.]+
* For resiliency, programs interpreting URLs should treat upper case letters as equivalent to lower case in scheme names * For resiliency, programs interpreting URLs should treat upper case letters as equivalent to
*lower case in scheme names
*/ */
// try to read scheme // try to read scheme
@ -86,7 +96,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
} }
// scheme should be lowercase // scheme should be lowercase
std::transform( Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower ); std::transform(
Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower);
// skip ':' // skip ':'
CurrentString = LocalString + 1; CurrentString = LocalString + 1;
@ -130,7 +141,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
if (bHasUserName) if (bHasUserName)
{ {
// read user name // read user name
while ( *LocalString && *LocalString != ':' && *LocalString != '@' ) LocalString++; while (*LocalString && *LocalString != ':' && *LocalString != '@')
LocalString++;
Result.m_UserName = std::string(CurrentString, LocalString - CurrentString); Result.m_UserName = std::string(CurrentString, LocalString - CurrentString);
@ -145,7 +157,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// read password // read password
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString && *LocalString != '@' ) LocalString++; while (*LocalString && *LocalString != '@')
LocalString++;
Result.m_Password = std::string(CurrentString, LocalString - CurrentString); Result.m_Password = std::string(CurrentString, LocalString - CurrentString);
@ -195,7 +208,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// read port number // read port number
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString && *LocalString != '/' ) LocalString++; while (*LocalString && *LocalString != '/')
LocalString++;
Result.m_Port = std::string(CurrentString, LocalString - CurrentString); Result.m_Port = std::string(CurrentString, LocalString - CurrentString);
@ -221,7 +235,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// parse the path // parse the path
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString && *LocalString != '#' && *LocalString != '?' ) LocalString++; while (*LocalString && *LocalString != '#' && *LocalString != '?')
LocalString++;
Result.m_Path = std::string(CurrentString, LocalString - CurrentString); Result.m_Path = std::string(CurrentString, LocalString - CurrentString);
@ -236,7 +251,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// read query // read query
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString && *LocalString != '#' ) LocalString++; while (*LocalString && *LocalString != '#')
LocalString++;
Result.m_Query = std::string(CurrentString, LocalString - CurrentString); Result.m_Query = std::string(CurrentString, LocalString - CurrentString);
@ -252,7 +268,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL
// read fragment // read fragment
LocalString = CurrentString; LocalString = CurrentString;
while ( *LocalString ) LocalString++; while (*LocalString)
LocalString++;
Result.m_Fragment = std::string(CurrentString, LocalString - CurrentString); Result.m_Fragment = std::string(CurrentString, LocalString - CurrentString);
} }

View File

@ -62,7 +62,10 @@ namespace LUrlParser
} }
/// return 'true' if the parsing was successful /// return 'true' if the parsing was successful
bool IsValid() const { return m_ErrorCode == LUrlParserError_Ok; } bool IsValid() const
{
return m_ErrorCode == LUrlParserError_Ok;
}
/// helper to convert the port number to int, return 'true' if the port is valid (within the /// helper to convert the port number to int, return 'true' if the port is valid (within the
/// 0..65535 range) /// 0..65535 range)

View File

@ -17,4 +17,4 @@ namespace ix
// //
pthread_setname_np(name.substr(0, 63).c_str()); pthread_setname_np(name.substr(0, 63).c_str());
} }
} } // namespace ix

View File

@ -15,7 +15,6 @@ namespace ix
// See prctl and PR_SET_NAME property in // See prctl and PR_SET_NAME property in
// http://man7.org/linux/man-pages/man2/prctl.2.html // http://man7.org/linux/man-pages/man2/prctl.2.html
// //
pthread_setname_np(pthread_self(), pthread_setname_np(pthread_self(), name.substr(0, 15).c_str());
name.substr(0, 15).c_str());
}
} }
} // namespace ix

View File

@ -4,6 +4,7 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include "../IXSetThreadName.h" #include "../IXSetThreadName.h"
#include <Windows.h> #include <Windows.h>
namespace ix namespace ix
@ -30,7 +31,8 @@ namespace ix
__try __try
{ {
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)& info); RaiseException(
MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*) &info);
} }
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
@ -41,4 +43,4 @@ namespace ix
{ {
SetThreadName(-1, name.c_str()); SetThreadName(-1, name.c_str());
} }
} } // namespace ix

View File

@ -4,14 +4,13 @@
* Copyright (c) 2017 Machine Zone. All rights reserved. * Copyright (c) 2017 Machine Zone. All rights reserved.
*/ */
#include <iostream> #include "IXSnakeServer.h"
#include "IXTest.h"
#include "catch.hpp"
#include <chrono> #include <chrono>
#include <iostream>
#include <ixcobra/IXCobraConnection.h> #include <ixcobra/IXCobraConnection.h>
#include <ixcrypto/IXUuid.h> #include <ixcrypto/IXUuid.h>
#include "IXTest.h"
#include "IXSnakeServer.h"
#include "catch.hpp"
using namespace ix; using namespace ix;
@ -22,9 +21,7 @@ namespace
void setupTrafficTrackerCallback() void setupTrafficTrackerCallback()
{ {
ix::CobraConnection::setTrafficTrackerCallback( ix::CobraConnection::setTrafficTrackerCallback([](size_t size, bool incoming) {
[](size_t size, bool incoming)
{
if (incoming) if (incoming)
{ {
incomingBytes += size; incomingBytes += size;
@ -33,8 +30,7 @@ namespace
{ {
outgoingBytes += size; outgoingBytes += size;
} }
} });
);
} }
class SatoriChat class SatoriChat
@ -77,12 +73,12 @@ namespace
SatoriChat::SatoriChat(const std::string& user, SatoriChat::SatoriChat(const std::string& user,
const std::string& session, const std::string& session,
const std::string& endpoint) : const std::string& endpoint)
_user(user), : _user(user)
_session(session), , _session(session)
_endpoint(endpoint), , _endpoint(endpoint)
_stop(false), , _stop(false)
_connectedAndSubscribed(false) , _connectedAndSubscribed(false)
{ {
} }
@ -127,9 +123,7 @@ namespace
void SatoriChat::subscribe(const std::string& channel) void SatoriChat::subscribe(const std::string& channel)
{ {
std::string filter; std::string filter;
_conn.subscribe(channel, filter, _conn.subscribe(channel, filter, [this](const Json::Value& msg) {
[this](const Json::Value& msg)
{
std::cout << msg.toStyledString() << std::endl; std::cout << msg.toStyledString() << std::endl;
if (!msg.isObject()) return; if (!msg.isObject()) return;
if (!msg.isMember("user")) return; if (!msg.isMember("user")) return;
@ -150,10 +144,7 @@ namespace
_receivedQueue.push(msg); _receivedQueue.push(msg);
std::stringstream ss; std::stringstream ss;
ss << std::endl ss << std::endl << msg_user << " > " << msg_text << std::endl << _user << " > ";
<< msg_user << " > " << msg_text
<< std::endl
<< _user << " > ";
log(ss.str()); log(ss.str());
}); });
} }
@ -189,18 +180,15 @@ namespace
std::string role = "_sub"; std::string role = "_sub";
std::string secret = "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba"; std::string secret = "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba";
_conn.configure(appkey, _endpoint, role, secret, _conn.configure(
ix::WebSocketPerMessageDeflateOptions(true)); appkey, _endpoint, role, secret, ix::WebSocketPerMessageDeflateOptions(true));
_conn.connect(); _conn.connect();
_conn.setEventCallback( _conn.setEventCallback([this, channel](ix::CobraConnectionEventType eventType,
[this, channel]
(ix::CobraConnectionEventType eventType,
const std::string& errMsg, const std::string& errMsg,
const ix::WebSocketHttpHeaders& /*headers*/, const ix::WebSocketHttpHeaders& /*headers*/,
const std::string& subscriptionId, const std::string& subscriptionId,
CobraConnection::MsgId msgId) CobraConnection::MsgId msgId) {
{
if (eventType == ix::CobraConnection_EventType_Open) if (eventType == ix::CobraConnection_EventType_Open)
{ {
log("Subscriber connected: " + _user); log("Subscriber connected: " + _user);
@ -231,8 +219,7 @@ namespace
{ {
Logger() << "Subscriber: published message acked: " << msgId; Logger() << "Subscriber: published message acked: " << msgId;
} }
} });
);
while (!_stop) while (!_stop)
{ {
@ -261,19 +248,15 @@ namespace
ix::msleep(50); ix::msleep(50);
_conn.disconnect(); _conn.disconnect();
_conn.setEventCallback([] _conn.setEventCallback([](ix::CobraConnectionEventType /*eventType*/,
(ix::CobraConnectionEventType /*eventType*/,
const std::string& /*errMsg*/, const std::string& /*errMsg*/,
const ix::WebSocketHttpHeaders& /*headers*/, const ix::WebSocketHttpHeaders& /*headers*/,
const std::string& /*subscriptionId*/, const std::string& /*subscriptionId*/,
CobraConnection::MsgId /*msgId*/) CobraConnection::MsgId /*msgId*/) { ; });
{
;
});
snakeServer.stop(); snakeServer.stop();
} }
} } // namespace
TEST_CASE("Cobra_chat", "[cobra_chat]") TEST_CASE("Cobra_chat", "[cobra_chat]")
{ {

View File

@ -3,14 +3,13 @@
* Copyright (c) 2018 Machine Zone. All rights reserved. * Copyright (c) 2018 Machine Zone. All rights reserved.
*/ */
#include <iostream>
#include <set>
#include <ixcrypto/IXUuid.h>
#include <ixcobra/IXCobraMetricsPublisher.h>
#include "IXTest.h"
#include "IXSnakeServer.h" #include "IXSnakeServer.h"
#include "IXTest.h"
#include "catch.hpp" #include "catch.hpp"
#include <iostream>
#include <ixcobra/IXCobraMetricsPublisher.h>
#include <ixcrypto/IXUuid.h>
#include <set>
using namespace ix; using namespace ix;
@ -45,18 +44,18 @@ namespace
gMessageCount = 0; gMessageCount = 0;
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure(APPKEY, endpoint, SUBSCRIBER_ROLE, SUBSCRIBER_SECRET, conn.configure(APPKEY,
endpoint,
SUBSCRIBER_ROLE,
SUBSCRIBER_SECRET,
ix::WebSocketPerMessageDeflateOptions(true)); ix::WebSocketPerMessageDeflateOptions(true));
conn.connect(); conn.connect();
conn.setEventCallback( conn.setEventCallback([&conn](ix::CobraConnectionEventType eventType,
[&conn]
(ix::CobraConnectionEventType eventType,
const std::string& errMsg, const std::string& errMsg,
const ix::WebSocketHttpHeaders& /*headers*/, const ix::WebSocketHttpHeaders& /*headers*/,
const std::string& subscriptionId, const std::string& subscriptionId,
CobraConnection::MsgId msgId) CobraConnection::MsgId msgId) {
{
if (eventType == ix::CobraConnection_EventType_Open) if (eventType == ix::CobraConnection_EventType_Open)
{ {
Logger() << "Subscriber connected:"; Logger() << "Subscriber connected:";
@ -69,9 +68,7 @@ namespace
{ {
log("Subscriber authenticated"); log("Subscriber authenticated");
std::string filter; std::string filter;
conn.subscribe(CHANNEL, filter, conn.subscribe(CHANNEL, filter, [](const Json::Value& msg) {
[](const Json::Value& msg)
{
log(msg.toStyledString()); log(msg.toStyledString());
std::string id = msg["id"].asString(); std::string id = msg["id"].asString();
@ -107,8 +104,7 @@ namespace
{ {
Logger() << "Subscriber: published message acked: " << msgId; Logger() << "Subscriber: published message acked: " << msgId;
} }
} });
);
while (!gStop) while (!gStop)
{ {
@ -121,7 +117,7 @@ namespace
gUniqueMessageIdsCount = gIds.size(); gUniqueMessageIdsCount = gIds.size();
} }
} } // namespace
TEST_CASE("Cobra_Metrics_Publisher", "[cobra]") TEST_CASE("Cobra_Metrics_Publisher", "[cobra]")
{ {
@ -158,8 +154,8 @@ TEST_CASE("Cobra_Metrics_Publisher", "[cobra]")
ix::CobraMetricsPublisher cobraMetricsPublisher; ix::CobraMetricsPublisher cobraMetricsPublisher;
bool perMessageDeflate = true; bool perMessageDeflate = true;
cobraMetricsPublisher.configure(APPKEY, endpoint, CHANNEL, cobraMetricsPublisher.configure(
PUBLISHER_ROLE, PUBLISHER_SECRET, perMessageDeflate); APPKEY, endpoint, CHANNEL, PUBLISHER_ROLE, PUBLISHER_SECRET, perMessageDeflate);
cobraMetricsPublisher.setSession(uuid4()); cobraMetricsPublisher.setSession(uuid4());
cobraMetricsPublisher.enable(true); // disabled by default, needs to be enabled to be active cobraMetricsPublisher.enable(true); // disabled by default, needs to be enabled to be active

View File

@ -4,11 +4,10 @@
* Copyright (c) 2018 Machine Zone. All rights reserved. * Copyright (c) 2018 Machine Zone. All rights reserved.
*/ */
#include "catch.hpp"
#include "IXTest.h" #include "IXTest.h"
#include <ixwebsocket/IXDNSLookup.h> #include "catch.hpp"
#include <iostream> #include <iostream>
#include <ixwebsocket/IXDNSLookup.h>
using namespace ix; using namespace ix;
@ -32,7 +31,11 @@ TEST_CASE("dns", "[net]")
auto dnsLookup = std::make_shared<DNSLookup>("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww", 80); auto dnsLookup = std::make_shared<DNSLookup>("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww", 80);
std::string errMsg; std::string errMsg;
struct addrinfo* res = dnsLookup->resolve(errMsg, [] { return false; }); struct addrinfo* res = dnsLookup->resolve(errMsg,
[]
{
return false;
});
std::cerr << "Error message: " << errMsg << std::endl; std::cerr << "Error message: " << errMsg << std::endl;
REQUIRE(res == nullptr); REQUIRE(res == nullptr);
} }
@ -43,7 +46,11 @@ TEST_CASE("dns", "[net]")
std::string errMsg; std::string errMsg;
// The callback returning true means we are requesting cancellation // The callback returning true means we are requesting cancellation
struct addrinfo* res = dnsLookup->resolve(errMsg, [] { return true; }); struct addrinfo* res = dnsLookup->resolve(errMsg,
[]
{
return true;
});
std::cerr << "Error message: " << errMsg << std::endl; std::cerr << "Error message: " << errMsg << std::endl;
REQUIRE(res == nullptr); REQUIRE(res == nullptr);
} }

View File

@ -5,11 +5,11 @@
*/ */
#include "IXGetFreePort.h" #include "IXGetFreePort.h"
#include <ixwebsocket/IXNetSystem.h> #include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXSocket.h> #include <ixwebsocket/IXSocket.h>
#include <string>
#include <random> #include <random>
#include <string>
namespace ix namespace ix
{ {
@ -30,8 +30,7 @@ namespace ix
} }
int enable = 1; int enable = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*) &enable, sizeof(enable)) < 0)
(char*) &enable, sizeof(enable)) < 0)
{ {
return getAnyFreePortRandom(); return getAnyFreePortRandom();
} }

View File

@ -4,11 +4,10 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include "catch.hpp"
#include <iostream> #include <iostream>
#include <ixwebsocket/IXHttpClient.h> #include <ixwebsocket/IXHttpClient.h>
#include "catch.hpp"
using namespace ix; using namespace ix;
TEST_CASE("http client", "[http]") TEST_CASE("http client", "[http]")
@ -28,14 +27,10 @@ TEST_CASE("http client", "[http]")
args->maxRedirects = 10; args->maxRedirects = 10;
args->verbose = true; args->verbose = true;
args->compress = true; args->compress = true;
args->logger = [](const std::string& msg) args->logger = [](const std::string& msg) { std::cout << msg; };
{ args->onProgressCallback = [](int current, int total) -> bool {
std::cout << msg; std::cerr << "\r"
}; << "Downloaded " << current << " bytes out of " << total;
args->onProgressCallback = [](int current, int total) -> bool
{
std::cerr << "\r" << "Downloaded "
<< current << " bytes out of " << total;
return true; return true;
}; };
@ -70,14 +65,10 @@ TEST_CASE("http client", "[http]")
args->maxRedirects = 10; args->maxRedirects = 10;
args->verbose = true; args->verbose = true;
args->compress = true; args->compress = true;
args->logger = [](const std::string& msg) args->logger = [](const std::string& msg) { std::cout << msg; };
{ args->onProgressCallback = [](int current, int total) -> bool {
std::cout << msg; std::cerr << "\r"
}; << "Downloaded " << current << " bytes out of " << total;
args->onProgressCallback = [](int current, int total) -> bool
{
std::cerr << "\r" << "Downloaded "
<< current << " bytes out of " << total;
return true; return true;
}; };
@ -113,23 +104,18 @@ TEST_CASE("http client", "[http]")
args->maxRedirects = 10; args->maxRedirects = 10;
args->verbose = true; args->verbose = true;
args->compress = true; args->compress = true;
args->logger = [](const std::string& msg) args->logger = [](const std::string& msg) { std::cout << msg; };
{ args->onProgressCallback = [](int current, int total) -> bool {
std::cout << msg; std::cerr << "\r"
}; << "Downloaded " << current << " bytes out of " << total;
args->onProgressCallback = [](int current, int total) -> bool
{
std::cerr << "\r" << "Downloaded "
<< current << " bytes out of " << total;
return true; return true;
}; };
std::atomic<bool> requestCompleted(false); std::atomic<bool> requestCompleted(false);
std::atomic<int> statusCode(0); std::atomic<int> statusCode(0);
httpClient.performRequest(args, [&requestCompleted, &statusCode] httpClient.performRequest(
(const HttpResponsePtr& response) args, [&requestCompleted, &statusCode](const HttpResponsePtr& response) {
{
std::cerr << "Upload size: " << response->uploadSize << std::endl; std::cerr << "Upload size: " << response->uploadSize << std::endl;
std::cerr << "Download size: " << response->downloadSize << std::endl; std::cerr << "Download size: " << response->downloadSize << std::endl;
std::cerr << "Status: " << response->statusCode << std::endl; std::cerr << "Status: " << response->statusCode << std::endl;
@ -138,8 +124,7 @@ TEST_CASE("http client", "[http]")
// In case of failure, print response->errorMsg // In case of failure, print response->errorMsg
statusCode = response->statusCode; statusCode = response->statusCode;
requestCompleted = true; requestCompleted = true;
} });
);
int wait = 0; int wait = 0;
while (wait < 5000) while (wait < 5000)
@ -171,14 +156,10 @@ TEST_CASE("http client", "[http]")
args->maxRedirects = 10; args->maxRedirects = 10;
args->verbose = true; args->verbose = true;
args->compress = true; args->compress = true;
args->logger = [](const std::string& msg) args->logger = [](const std::string& msg) { std::cout << msg; };
{ args->onProgressCallback = [](int current, int total) -> bool {
std::cout << msg; std::cerr << "\r"
}; << "Downloaded " << current << " bytes out of " << total;
args->onProgressCallback = [](int current, int total) -> bool
{
std::cerr << "\r" << "Downloaded "
<< current << " bytes out of " << total;
return true; return true;
}; };
@ -189,9 +170,10 @@ TEST_CASE("http client", "[http]")
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
httpClient.performRequest(args, [i, &requestCompleted, &statusCode0, &statusCode1, &statusCode2] httpClient.performRequest(
(const HttpResponsePtr& response) args,
{ [i, &requestCompleted, &statusCode0, &statusCode1, &statusCode2](
const HttpResponsePtr& response) {
std::cerr << "Upload size: " << response->uploadSize << std::endl; std::cerr << "Upload size: " << response->uploadSize << std::endl;
std::cerr << "Download size: " << response->downloadSize << std::endl; std::cerr << "Download size: " << response->downloadSize << std::endl;
std::cerr << "Status: " << response->statusCode << std::endl; std::cerr << "Status: " << response->statusCode << std::endl;
@ -211,8 +193,7 @@ TEST_CASE("http client", "[http]")
statusCode2 = response->statusCode; statusCode2 = response->statusCode;
requestCompleted = true; requestCompleted = true;
} }
} });
);
} }
int wait = 0; int wait = 0;

View File

@ -4,12 +4,11 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include "IXGetFreePort.h"
#include "catch.hpp"
#include <iostream> #include <iostream>
#include <ixwebsocket/IXHttpClient.h> #include <ixwebsocket/IXHttpClient.h>
#include <ixwebsocket/IXHttpServer.h> #include <ixwebsocket/IXHttpServer.h>
#include "IXGetFreePort.h"
#include "catch.hpp"
using namespace ix; using namespace ix;
@ -39,14 +38,10 @@ TEST_CASE("http server", "[httpd]")
args->maxRedirects = 10; args->maxRedirects = 10;
args->verbose = true; args->verbose = true;
args->compress = true; args->compress = true;
args->logger = [](const std::string& msg) args->logger = [](const std::string& msg) { std::cout << msg; };
{ args->onProgressCallback = [](int current, int total) -> bool {
std::cout << msg; std::cerr << "\r"
}; << "Downloaded " << current << " bytes out of " << total;
args->onProgressCallback = [](int current, int total) -> bool
{
std::cerr << "\r" << "Downloaded "
<< current << " bytes out of " << total;
return true; return true;
}; };

View File

@ -4,15 +4,13 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include "catch.hpp"
#include <iostream> #include <iostream>
#include <ixwebsocket/IXHttp.h> #include <ixwebsocket/IXHttp.h>
#include "catch.hpp"
#include <string.h> #include <string.h>
namespace ix namespace ix
{ {
TEST_CASE("http", "[http]") TEST_CASE("http", "[http]")
{ {
SECTION("Normal case") SECTION("Normal case")
@ -52,4 +50,4 @@ TEST_CASE("http", "[http]")
} }
} }
} } // namespace ix

View File

@ -4,11 +4,10 @@
* Copyright (c) 2018 Machine Zone. All rights reserved. * Copyright (c) 2018 Machine Zone. All rights reserved.
*/ */
#include "catch.hpp"
#include "IXTest.h" #include "IXTest.h"
#include <ixwebsocket/IXSocketConnect.h> #include "catch.hpp"
#include <iostream> #include <iostream>
#include <ixwebsocket/IXSocketConnect.h>
using namespace ix; using namespace ix;

View File

@ -4,13 +4,12 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include <iostream>
#include <ixwebsocket/IXSocketFactory.h>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXCancellationRequest.h>
#include "IXTest.h" #include "IXTest.h"
#include "catch.hpp" #include "catch.hpp"
#include <iostream>
#include <ixwebsocket/IXCancellationRequest.h>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXSocketFactory.h>
#include <string.h> #include <string.h>
using namespace ix; using namespace ix;
@ -33,8 +32,7 @@ namespace ix
Logger() << "errMsg: " << errMsg; Logger() << "errMsg: " << errMsg;
REQUIRE(success); REQUIRE(success);
Logger() << "Sending request: " << request Logger() << "Sending request: " << request << "to " << host << ":" << port;
<< "to " << host << ":" << port;
REQUIRE(socket->writeBytes(request, isCancellationRequested)); REQUIRE(socket->writeBytes(request, isCancellationRequested));
auto lineResult = socket->readLine(isCancellationRequested); auto lineResult = socket->readLine(isCancellationRequested);
@ -49,11 +47,12 @@ namespace ix
REQUIRE(sscanf(line.c_str(), "HTTP/1.1 %d", &status) == 1); REQUIRE(sscanf(line.c_str(), "HTTP/1.1 %d", &status) == 1);
REQUIRE(status == expectedStatus); REQUIRE(status == expectedStatus);
} }
} } // namespace ix
TEST_CASE("socket", "[socket]") TEST_CASE("socket", "[socket]")
{ {
SECTION("Connect to a local websocket server over a free port. Send GET request without header. Should return 400") SECTION("Connect to a local websocket server over a free port. Send GET request without "
"header. Should return 400")
{ {
// Start a server first which we'll hit with our socket code // Start a server first which we'll hit with our socket code
int port = getFreePort(); int port = getFreePort();
@ -78,7 +77,8 @@ TEST_CASE("socket", "[socket]")
} }
#if defined(IXWEBSOCKET_USE_TLS) #if defined(IXWEBSOCKET_USE_TLS)
SECTION("Connect to google HTTPS server over port 443. Send GET request without header. Should return 200") SECTION("Connect to google HTTPS server over port 443. Send GET request without header. Should "
"return 200")
{ {
std::string errMsg; std::string errMsg;
bool tls = true; bool tls = true;

View File

@ -5,19 +5,19 @@
*/ */
#include "IXTest.h" #include "IXTest.h"
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXNetSystem.h>
#include <chrono> #include <chrono>
#include <thread>
#include <mutex>
#include <string>
#include <fstream> #include <fstream>
#include <iostream>
#include <stdlib.h>
#include <stack>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h>
#include <mutex>
#include <random> #include <random>
#include <stack>
#include <stdlib.h>
#include <string>
#include <thread>
namespace ix namespace ix
@ -29,9 +29,7 @@ namespace ix
void setupWebSocketTrafficTrackerCallback() void setupWebSocketTrafficTrackerCallback()
{ {
ix::WebSocket::setTrafficTrackerCallback( ix::WebSocket::setTrafficTrackerCallback([](size_t size, bool incoming) {
[](size_t size, bool incoming)
{
if (incoming) if (incoming)
{ {
incomingBytes += size; incomingBytes += size;
@ -40,8 +38,7 @@ namespace ix
{ {
outgoingBytes += size; outgoingBytes += size;
} }
} });
);
} }
void reportWebSocketTraffic() void reportWebSocketTraffic()
@ -61,8 +58,7 @@ namespace ix
{ {
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
auto seconds = auto seconds =
std::chrono::duration_cast<std::chrono::seconds>( std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
now.time_since_epoch()).count();
return std::to_string(seconds); return std::to_string(seconds);
} }
@ -72,17 +68,14 @@ namespace ix
Logger() << msg; Logger() << msg;
} }
void hexDump(const std::string& prefix, void hexDump(const std::string& prefix, const std::string& s)
const std::string& s)
{ {
std::ostringstream ss; std::ostringstream ss;
bool upper_case = false; bool upper_case = false;
for (std::string::size_type i = 0; i < s.length(); ++i) for (std::string::size_type i = 0; i < s.length(); ++i)
{ {
ss << std::hex ss << std::hex << std::setfill('0') << std::setw(2)
<< std::setfill('0')
<< std::setw(2)
<< (upper_case ? std::uppercase : std::nouppercase) << (int) s[i]; << (upper_case ? std::uppercase : std::nouppercase) << (int) s[i];
} }
@ -91,13 +84,10 @@ namespace ix
bool startWebSocketEchoServer(ix::WebSocketServer& server) bool startWebSocketEchoServer(ix::WebSocketServer& server)
{ {
server.setOnConnectionCallback( server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket,
[&server](std::shared_ptr<ix::WebSocket> webSocket, std::shared_ptr<ConnectionState> connectionState) {
std::shared_ptr<ConnectionState> connectionState)
{
webSocket->setOnMessageCallback( webSocket->setOnMessageCallback(
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) [webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) {
{
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
Logger() << "New connection"; Logger() << "New connection";
@ -122,10 +112,8 @@ namespace ix
} }
} }
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -190,4 +178,4 @@ namespace ix
return appConfig; return appConfig;
} }
} } // namespace ix

View File

@ -6,10 +6,10 @@
#pragma once #pragma once
#include "IXAppConfig.h"
#include "IXGetFreePort.h" #include "IXGetFreePort.h"
#include <iostream> #include <iostream>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include "IXAppConfig.h"
#include <mutex> #include <mutex>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <sstream> #include <sstream>

View File

@ -4,6 +4,7 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include "catch.hpp"
#include <ixwebsocket/IXCancellationRequest.h> #include <ixwebsocket/IXCancellationRequest.h>
#include <ixwebsocket/IXConnectionState.h> #include <ixwebsocket/IXConnectionState.h>
#include <ixwebsocket/IXDNSLookup.h> #include <ixwebsocket/IXDNSLookup.h>
@ -39,8 +40,6 @@
#include <ixwebsocket/LUrlParser.h> #include <ixwebsocket/LUrlParser.h>
#include <ixwebsocket/libwshandshake.hpp> #include <ixwebsocket/libwshandshake.hpp>
#include "catch.hpp"
using namespace ix; using namespace ix;
TEST_CASE("unity build", "[unity_build]") TEST_CASE("unity build", "[unity_build]")

View File

@ -4,18 +4,16 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include <iostream>
#include <ixwebsocket/IXUrlParser.h>
#include "IXTest.h" #include "IXTest.h"
#include "catch.hpp" #include "catch.hpp"
#include <iostream>
#include <ixwebsocket/IXUrlParser.h>
#include <string.h> #include <string.h>
using namespace ix; using namespace ix;
namespace ix namespace ix
{ {
TEST_CASE("urlParser", "[urlParser]") TEST_CASE("urlParser", "[urlParser]")
{ {
SECTION("http://google.com") SECTION("http://google.com")
@ -88,7 +86,12 @@ TEST_CASE("urlParser", "[urlParser]")
SECTION("real test") SECTION("real test")
{ {
std::string url = "ws://127.0.0.1:7350/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf"; std::string url =
"ws://127.0.0.1:7350/"
"ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
"eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZi"
"IsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status="
"true&format=protobuf";
std::string protocol, host, path, query; std::string protocol, host, path, query;
int port; int port;
bool res; bool res;
@ -98,11 +101,18 @@ TEST_CASE("urlParser", "[urlParser]")
REQUIRE(res); REQUIRE(res);
REQUIRE(protocol == "ws"); REQUIRE(protocol == "ws");
REQUIRE(host == "127.0.0.1"); REQUIRE(host == "127.0.0.1");
REQUIRE(path == "/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf"); REQUIRE(path ==
REQUIRE(query == "token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf"); "/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
"eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNW"
"QxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&"
"status=true&format=protobuf");
REQUIRE(query ==
"token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
"eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNW"
"QxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&"
"status=true&format=protobuf");
REQUIRE(port == 7350); REQUIRE(port == 7350);
} }
} }
} } // namespace ix

View File

@ -9,17 +9,15 @@
// websocket_chat_server/broacast-server.js // websocket_chat_server/broacast-server.js
// //
#include "IXTest.h"
#include "catch.hpp"
#include "msgpack11.hpp"
#include <iostream> #include <iostream>
#include <sstream>
#include <vector>
#include <mutex>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include "msgpack11.hpp" #include <mutex>
#include <sstream>
#include "IXTest.h" #include <vector>
#include "catch.hpp"
using msgpack11::MsgPack; using msgpack11::MsgPack;
using namespace ix; using namespace ix;
@ -29,9 +27,7 @@ namespace
class WebSocketChat class WebSocketChat
{ {
public: public:
WebSocketChat(const std::string& user, WebSocketChat(const std::string& user, const std::string& session, int port);
const std::string& session,
int port);
void subscribe(const std::string& channel); void subscribe(const std::string& channel);
void start(); void start();
@ -57,12 +53,10 @@ namespace
mutable std::mutex _mutex; mutable std::mutex _mutex;
}; };
WebSocketChat::WebSocketChat(const std::string& user, WebSocketChat::WebSocketChat(const std::string& user, const std::string& session, int port)
const std::string& session, : _user(user)
int port) : , _session(session)
_user(user), , _port(port)
_session(session),
_port(port)
{ {
; ;
} }
@ -100,10 +94,7 @@ namespace
std::string url; std::string url;
{ {
std::stringstream ss; std::stringstream ss;
ss << "ws://127.0.0.1:" ss << "ws://127.0.0.1:" << _port << "/" << _user;
<< _port
<< "/"
<< _user;
url = ss.str(); url = ss.str();
} }
@ -113,22 +104,16 @@ namespace
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + url); log(std::string("Connecting to url: ") + url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) {
[this](const ix::WebSocketMessagePtr& msg)
{
std::stringstream ss; std::stringstream ss;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
ss << "cmd_websocket_chat: user " ss << "cmd_websocket_chat: user " << _user << " Connected !";
<< _user
<< " Connected !";
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
ss << "cmd_websocket_chat: user " ss << "cmd_websocket_chat: user " << _user << " disconnected !";
<< _user
<< " disconnected !";
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Message) else if (msg->type == ix::WebSocketMessageType::Message)
@ -148,10 +133,7 @@ namespace
payload = "<message too large>"; payload = "<message too large>";
} }
ss << std::endl ss << std::endl << result.first << " > " << payload << std::endl << _user << " > ";
<< result.first << " > " << payload
<< std::endl
<< _user << " > ";
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Error) else if (msg->type == ix::WebSocketMessageType::Error)
@ -211,13 +193,10 @@ namespace
bool startServer(ix::WebSocketServer& server) bool startServer(ix::WebSocketServer& server)
{ {
server.setOnConnectionCallback( server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket,
[&server](std::shared_ptr<ix::WebSocket> webSocket, std::shared_ptr<ConnectionState> connectionState) {
std::shared_ptr<ConnectionState> connectionState)
{
webSocket->setOnMessageCallback( webSocket->setOnMessageCallback(
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) [webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) {
{
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
Logger() << "New connection"; Logger() << "New connection";
@ -243,10 +222,8 @@ namespace
} }
} }
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -258,7 +235,7 @@ namespace
server.start(); server.start();
return true; return true;
} }
} } // namespace
TEST_CASE("Websocket_chat", "[websocket_chat]") TEST_CASE("Websocket_chat", "[websocket_chat]")
{ {
@ -305,8 +282,7 @@ TEST_CASE("Websocket_chat", "[websocket_chat]")
// Wait until all messages are received. 10s timeout // Wait until all messages are received. 10s timeout
int attempts = 0; int attempts = 0;
while (chatA.getReceivedMessagesCount() != 3 || while (chatA.getReceivedMessagesCount() != 3 || chatB.getReceivedMessagesCount() != 3)
chatB.getReceivedMessagesCount() != 3)
{ {
REQUIRE(attempts++ < 10); REQUIRE(attempts++ < 10);
ix::msleep(1000); ix::msleep(1000);

View File

@ -4,15 +4,13 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include "IXTest.h"
#include "catch.hpp"
#include <iostream> #include <iostream>
#include <sstream>
#include <queue>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include <queue>
#include "IXTest.h" #include <sstream>
#include "catch.hpp"
using namespace ix; using namespace ix;
@ -102,9 +100,7 @@ namespace
std::string url; std::string url;
{ {
std::stringstream ss; std::stringstream ss;
ss << "ws://localhost:" ss << "ws://localhost:" << _port << "/";
<< _port
<< "/";
url = ss.str(); url = ss.str();
} }
@ -115,9 +111,7 @@ namespace
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + url); log(std::string("Connecting to url: ") + url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) {
[this](const ix::WebSocketMessagePtr& msg)
{
std::stringstream ss; std::stringstream ss;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
@ -126,10 +120,7 @@ namespace
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
std::stringstream ss; std::stringstream ss;
ss << "client disconnected(" ss << "client disconnected(" << msg->closeInfo.code << "," << msg->closeInfo.reason
<< msg->closeInfo.code
<< ","
<< msg->closeInfo.reason
<< ")"; << ")";
log(ss.str()); log(ss.str());
@ -178,12 +169,15 @@ namespace
{ {
// A dev/null server // A dev/null server
server.setOnConnectionCallback( server.setOnConnectionCallback(
[&receivedCloseCode, &receivedCloseReason, &receivedCloseRemote, &mutexWrite](std::shared_ptr<ix::WebSocket> webSocket, [&receivedCloseCode, &receivedCloseReason, &receivedCloseRemote, &mutexWrite](
std::shared_ptr<ConnectionState> connectionState) std::shared_ptr<ix::WebSocket> webSocket,
{ std::shared_ptr<ConnectionState> connectionState) {
webSocket->setOnMessageCallback( webSocket->setOnMessageCallback([webSocket,
[webSocket, connectionState, &receivedCloseCode, &receivedCloseReason, &receivedCloseRemote, &mutexWrite](const ix::WebSocketMessagePtr& msg) connectionState,
{ &receivedCloseCode,
&receivedCloseReason,
&receivedCloseRemote,
&mutexWrite](const ix::WebSocketMessagePtr& msg) {
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
Logger() << "New server connection"; Logger() << "New server connection";
@ -198,11 +192,8 @@ namespace
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
std::stringstream ss; std::stringstream ss;
ss << "Server closed connection(" ss << "Server closed connection(" << msg->closeInfo.code << ","
<< msg->closeInfo.code << msg->closeInfo.reason << ")";
<< ","
<< msg->closeInfo.reason
<< ")";
log(ss.str()); log(ss.str());
std::lock_guard<std::mutex> lck(mutexWrite); std::lock_guard<std::mutex> lck(mutexWrite);
@ -211,10 +202,8 @@ namespace
receivedCloseReason = std::string(msg->closeInfo.reason); receivedCloseReason = std::string(msg->closeInfo.reason);
receivedCloseRemote = msg->closeInfo.remote; receivedCloseRemote = msg->closeInfo.remote;
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -226,7 +215,7 @@ namespace
server.start(); server.start();
return true; return true;
} }
} } // namespace
TEST_CASE("Websocket_client_close_default", "[close]") TEST_CASE("Websocket_client_close_default", "[close]")
{ {
@ -242,7 +231,11 @@ TEST_CASE("Websocket_client_close_default", "[close]")
std::string serverReceivedCloseReason(""); std::string serverReceivedCloseReason("");
std::mutex mutexWrite; std::mutex mutexWrite;
REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite)); REQUIRE(startServer(server,
serverReceivedCloseCode,
serverReceivedCloseReason,
serverReceivedCloseRemote,
mutexWrite));
std::string session = ix::generateSessionId(); std::string session = ix::generateSessionId();
WebSocketClient webSocketClient(port); WebSocketClient webSocketClient(port);
@ -301,7 +294,11 @@ TEST_CASE("Websocket_client_close_params_given", "[close]")
std::string serverReceivedCloseReason(""); std::string serverReceivedCloseReason("");
std::mutex mutexWrite; std::mutex mutexWrite;
REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite)); REQUIRE(startServer(server,
serverReceivedCloseCode,
serverReceivedCloseReason,
serverReceivedCloseRemote,
mutexWrite));
std::string session = ix::generateSessionId(); std::string session = ix::generateSessionId();
WebSocketClient webSocketClient(port); WebSocketClient webSocketClient(port);
@ -359,7 +356,11 @@ TEST_CASE("Websocket_server_close", "[close]")
std::string serverReceivedCloseReason(""); std::string serverReceivedCloseReason("");
std::mutex mutexWrite; std::mutex mutexWrite;
REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite)); REQUIRE(startServer(server,
serverReceivedCloseCode,
serverReceivedCloseReason,
serverReceivedCloseRemote,
mutexWrite));
std::string session = ix::generateSessionId(); std::string session = ix::generateSessionId();
WebSocketClient webSocketClient(port); WebSocketClient webSocketClient(port);
@ -417,7 +418,11 @@ TEST_CASE("Websocket_server_close_immediatly", "[close]")
std::string serverReceivedCloseReason(""); std::string serverReceivedCloseReason("");
std::mutex mutexWrite; std::mutex mutexWrite;
REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite)); REQUIRE(startServer(server,
serverReceivedCloseCode,
serverReceivedCloseReason,
serverReceivedCloseRemote,
mutexWrite));
std::string session = ix::generateSessionId(); std::string session = ix::generateSessionId();
WebSocketClient webSocketClient(port); WebSocketClient webSocketClient(port);

View File

@ -4,12 +4,11 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXWebSocketServer.h>
#include <ixwebsocket/IXWebSocketMessageQueue.h>
#include "IXTest.h" #include "IXTest.h"
#include "catch.hpp" #include "catch.hpp"
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXWebSocketMessageQueue.h>
#include <ixwebsocket/IXWebSocketServer.h>
#include <thread> #include <thread>
using namespace ix; using namespace ix;
@ -18,13 +17,10 @@ namespace
{ {
bool startServer(ix::WebSocketServer& server) bool startServer(ix::WebSocketServer& server)
{ {
server.setOnConnectionCallback( server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket,
[&server](std::shared_ptr<ix::WebSocket> webSocket, std::shared_ptr<ConnectionState> connectionState) {
std::shared_ptr<ConnectionState> connectionState)
{
webSocket->setOnMessageCallback( webSocket->setOnMessageCallback(
[connectionState, &server](const WebSocketMessagePtr& msg) [connectionState, &server](const WebSocketMessagePtr& msg) {
{
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
Logger() << "New connection"; Logger() << "New connection";
@ -50,10 +46,8 @@ namespace
client->send(msg->str); client->send(msg->str);
} }
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -73,8 +67,7 @@ namespace
{ {
msgQ.bindWebsocket(&ws); msgQ.bindWebsocket(&ws);
msgQ.setOnMessageCallback([this](const WebSocketMessagePtr& msg) msgQ.setOnMessageCallback([this](const WebSocketMessagePtr& msg) {
{
REQUIRE(mainThreadId == std::this_thread::get_id()); REQUIRE(mainThreadId == std::this_thread::get_id());
std::stringstream ss; std::stringstream ss;
@ -153,7 +146,10 @@ namespace
} }
} }
bool isSucceeded() const { return succeeded; } bool isSucceeded() const
{
return succeeded;
}
private: private:
WebSocket ws; WebSocket ws;
@ -163,7 +159,7 @@ namespace
std::thread::id mainThreadId; std::thread::id mainThreadId;
bool succeeded = false; bool succeeded = false;
}; };
} } // namespace
TEST_CASE("Websocket_message_queue", "[websocket_message_q]") TEST_CASE("Websocket_message_queue", "[websocket_message_q]")
{ {

View File

@ -4,15 +4,13 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include "IXTest.h"
#include "catch.hpp"
#include <iostream> #include <iostream>
#include <sstream>
#include <queue>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include <queue>
#include "IXTest.h" #include <sstream>
#include "catch.hpp"
using namespace ix; using namespace ix;
@ -35,8 +33,8 @@ namespace
}; };
WebSocketClient::WebSocketClient(int port, bool useHeartBeatMethod) WebSocketClient::WebSocketClient(int port, bool useHeartBeatMethod)
: _port(port), : _port(port)
_useHeartBeatMethod(useHeartBeatMethod) , _useHeartBeatMethod(useHeartBeatMethod)
{ {
; ;
} }
@ -56,9 +54,7 @@ namespace
std::string url; std::string url;
{ {
std::stringstream ss; std::stringstream ss;
ss << "ws://127.0.0.1:" ss << "ws://127.0.0.1:" << _port << "/";
<< _port
<< "/";
url = ss.str(); url = ss.str();
} }
@ -79,14 +75,12 @@ namespace
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + url); log(std::string("Connecting to url: ") + url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([](ix::WebSocketMessageType messageType,
[](ix::WebSocketMessageType messageType,
const std::string& str, const std::string& str,
size_t wireSize, size_t wireSize,
const ix::WebSocketErrorInfo& error, const ix::WebSocketErrorInfo& error,
const ix::WebSocketOpenInfo& openInfo, const ix::WebSocketOpenInfo& openInfo,
const ix::WebSocketCloseInfo& closeInfo) const ix::WebSocketCloseInfo& closeInfo) {
{
std::stringstream ss; std::stringstream ss;
if (messageType == ix::WebSocketMessageType::Open) if (messageType == ix::WebSocketMessageType::Open)
{ {
@ -135,16 +129,15 @@ namespace
// A dev/null server // A dev/null server
server.setOnConnectionCallback( server.setOnConnectionCallback(
[&server, &receivedPingMessages](std::shared_ptr<ix::WebSocket> webSocket, [&server, &receivedPingMessages](std::shared_ptr<ix::WebSocket> webSocket,
std::shared_ptr<ConnectionState> connectionState) std::shared_ptr<ConnectionState> connectionState) {
{
webSocket->setOnMessageCallback( webSocket->setOnMessageCallback(
[webSocket, connectionState, &server, &receivedPingMessages](ix::WebSocketMessageType messageType, [webSocket, connectionState, &server, &receivedPingMessages](
ix::WebSocketMessageType messageType,
const std::string& str, const std::string& str,
size_t wireSize, size_t wireSize,
const ix::WebSocketErrorInfo& error, const ix::WebSocketErrorInfo& error,
const ix::WebSocketOpenInfo& openInfo, const ix::WebSocketOpenInfo& openInfo,
const ix::WebSocketCloseInfo& closeInfo) const ix::WebSocketCloseInfo& closeInfo) {
{
if (messageType == ix::WebSocketMessageType::Open) if (messageType == ix::WebSocketMessageType::Open)
{ {
Logger() << "New server connection"; Logger() << "New server connection";
@ -173,10 +166,8 @@ namespace
client->sendText("reply"); client->sendText("reply");
} }
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -188,7 +179,7 @@ namespace
server.start(); server.start();
return true; return true;
} }
} } // namespace
TEST_CASE("Websocket_ping_no_data_sent_setPingInterval", "[setPingInterval]") TEST_CASE("Websocket_ping_no_data_sent_setPingInterval", "[setPingInterval]")
{ {
@ -282,7 +273,8 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval", "[setPingInterval]")
TEST_CASE("Websocket_ping_data_sent_setPingInterval_half_full", "[setPingInterval]") TEST_CASE("Websocket_ping_data_sent_setPingInterval_half_full", "[setPingInterval]")
{ {
SECTION("Make sure that ping messages are sent, even if other messages are sent continuously during a given time") SECTION("Make sure that ping messages are sent, even if other messages are sent continuously "
"during a given time")
{ {
ix::setupWebSocketTrafficTrackerCallback(); ix::setupWebSocketTrafficTrackerCallback();
@ -335,7 +327,8 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval_half_full", "[setPingInterva
TEST_CASE("Websocket_ping_data_sent_setPingInterval_full", "[setPingInterval]") TEST_CASE("Websocket_ping_data_sent_setPingInterval_full", "[setPingInterval]")
{ {
SECTION("Make sure that ping messages are sent, even if other messages are sent continuously for longer than ping interval") SECTION("Make sure that ping messages are sent, even if other messages are sent continuously "
"for longer than ping interval")
{ {
ix::setupWebSocketTrafficTrackerCallback(); ix::setupWebSocketTrafficTrackerCallback();

View File

@ -4,15 +4,13 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include "IXTest.h"
#include "catch.hpp"
#include <iostream> #include <iostream>
#include <sstream>
#include <queue>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include <queue>
#include "IXTest.h" #include <sstream>
#include "catch.hpp"
using namespace ix; using namespace ix;
@ -41,11 +39,11 @@ namespace
}; };
WebSocketClient::WebSocketClient(int port, int pingInterval, int pingTimeout) WebSocketClient::WebSocketClient(int port, int pingInterval, int pingTimeout)
: _port(port), : _port(port)
_receivedPongMessages(0), , _receivedPongMessages(0)
_closedDueToPingTimeout(false), , _closedDueToPingTimeout(false)
_pingInterval(pingInterval), , _pingInterval(pingInterval)
_pingTimeout(pingTimeout) , _pingTimeout(pingTimeout)
{ {
; ;
} }
@ -70,9 +68,7 @@ namespace
std::string url; std::string url;
{ {
std::stringstream ss; std::stringstream ss;
ss << "ws://127.0.0.1:" ss << "ws://127.0.0.1:" << _port << "/";
<< _port
<< "/";
url = ss.str(); url = ss.str();
} }
@ -88,19 +84,16 @@ namespace
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + url); log(std::string("Connecting to url: ") + url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](ix::WebSocketMessageType messageType,
[this](ix::WebSocketMessageType messageType,
const std::string& str, const std::string& str,
size_t wireSize, size_t wireSize,
const ix::WebSocketErrorInfo& error, const ix::WebSocketErrorInfo& error,
const ix::WebSocketOpenInfo& openInfo, const ix::WebSocketOpenInfo& openInfo,
const ix::WebSocketCloseInfo& closeInfo) const ix::WebSocketCloseInfo& closeInfo) {
{
std::stringstream ss; std::stringstream ss;
if (messageType == ix::WebSocketMessageType::Open) if (messageType == ix::WebSocketMessageType::Open)
{ {
log("client connected"); log("client connected");
} }
else if (messageType == ix::WebSocketMessageType::Close) else if (messageType == ix::WebSocketMessageType::Close)
{ {
@ -110,7 +103,6 @@ namespace
{ {
_closedDueToPingTimeout = true; _closedDueToPingTimeout = true;
} }
} }
else if (messageType == ix::WebSocketMessageType::Error) else if (messageType == ix::WebSocketMessageType::Error)
{ {
@ -159,21 +151,22 @@ namespace
return _closedDueToPingTimeout; return _closedDueToPingTimeout;
} }
bool startServer(ix::WebSocketServer& server, std::atomic<int>& receivedPingMessages, bool enablePong) bool startServer(ix::WebSocketServer& server,
std::atomic<int>& receivedPingMessages,
bool enablePong)
{ {
// A dev/null server // A dev/null server
server.setOnConnectionCallback( server.setOnConnectionCallback(
[&server, &receivedPingMessages](std::shared_ptr<ix::WebSocket> webSocket, [&server, &receivedPingMessages](std::shared_ptr<ix::WebSocket> webSocket,
std::shared_ptr<ConnectionState> connectionState) std::shared_ptr<ConnectionState> connectionState) {
{
webSocket->setOnMessageCallback( webSocket->setOnMessageCallback(
[webSocket, connectionState, &server, &receivedPingMessages](ix::WebSocketMessageType messageType, [webSocket, connectionState, &server, &receivedPingMessages](
ix::WebSocketMessageType messageType,
const std::string& str, const std::string& str,
size_t wireSize, size_t wireSize,
const ix::WebSocketErrorInfo& error, const ix::WebSocketErrorInfo& error,
const ix::WebSocketOpenInfo& openInfo, const ix::WebSocketOpenInfo& openInfo,
const ix::WebSocketCloseInfo& closeInfo) const ix::WebSocketCloseInfo& closeInfo) {
{
if (messageType == ix::WebSocketMessageType::Open) if (messageType == ix::WebSocketMessageType::Open)
{ {
Logger() << "New server connection"; Logger() << "New server connection";
@ -194,10 +187,8 @@ namespace
log("Server received a ping"); log("Server received a ping");
receivedPingMessages++; receivedPingMessages++;
} }
} });
); });
}
);
if (!enablePong) if (!enablePong)
{ {
@ -215,7 +206,7 @@ namespace
server.start(); server.start();
return true; return true;
} }
} } // namespace
TEST_CASE("Websocket_ping_timeout_not_checked", "[setPingTimeout]") TEST_CASE("Websocket_ping_timeout_not_checked", "[setPingTimeout]")
{ {

View File

@ -4,15 +4,13 @@
* Copyright (c) 2019 Machine Zone. All rights reserved. * Copyright (c) 2019 Machine Zone. All rights reserved.
*/ */
#include "IXTest.h"
#include "catch.hpp"
#include <iostream> #include <iostream>
#include <ixwebsocket/IXSocket.h> #include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXSocketFactory.h>
#include <ixwebsocket/IXWebSocket.h> #include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include <ixwebsocket/IXSocketFactory.h>
#include "IXTest.h"
#include "catch.hpp"
using namespace ix; using namespace ix;
@ -28,23 +26,18 @@ namespace ix
} }
}; };
bool startServer(ix::WebSocketServer& server, bool startServer(ix::WebSocketServer& server, std::string& connectionId)
std::string& connectionId)
{
auto factory = []() -> std::shared_ptr<ConnectionState>
{ {
auto factory = []() -> std::shared_ptr<ConnectionState> {
return std::make_shared<ConnectionStateCustom>(); return std::make_shared<ConnectionStateCustom>();
}; };
server.setConnectionStateFactory(factory); server.setConnectionStateFactory(factory);
server.setOnConnectionCallback( server.setOnConnectionCallback([&server, &connectionId](
[&server, &connectionId](std::shared_ptr<ix::WebSocket> webSocket, std::shared_ptr<ix::WebSocket> webSocket,
std::shared_ptr<ConnectionState> connectionState) std::shared_ptr<ConnectionState> connectionState) {
{ webSocket->setOnMessageCallback([webSocket, connectionState, &connectionId, &server](
webSocket->setOnMessageCallback( const ix::WebSocketMessagePtr& msg) {
[webSocket, connectionState,
&connectionId, &server](const ix::WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
Logger() << "New connection"; Logger() << "New connection";
@ -73,10 +66,8 @@ namespace ix
} }
} }
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -88,7 +79,7 @@ namespace ix
server.start(); server.start();
return true; return true;
} }
} } // namespace ix
TEST_CASE("Websocket_server", "[websocket_server]") TEST_CASE("Websocket_server", "[websocket_server]")
{ {
@ -103,10 +94,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
bool tls = false; bool tls = false;
std::shared_ptr<Socket> socket = createSocket(tls, errMsg); std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
std::string host("127.0.0.1"); std::string host("127.0.0.1");
auto isCancellationRequested = []() -> bool auto isCancellationRequested = []() -> bool { return false; };
{
return false;
};
bool success = socket->connect(host, port, errMsg, isCancellationRequested); bool success = socket->connect(host, port, errMsg, isCancellationRequested);
REQUIRE(success); REQUIRE(success);
@ -139,10 +127,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
bool tls = false; bool tls = false;
std::shared_ptr<Socket> socket = createSocket(tls, errMsg); std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
std::string host("127.0.0.1"); std::string host("127.0.0.1");
auto isCancellationRequested = []() -> bool auto isCancellationRequested = []() -> bool { return false; };
{
return false;
};
bool success = socket->connect(host, port, errMsg, isCancellationRequested); bool success = socket->connect(host, port, errMsg, isCancellationRequested);
REQUIRE(success); REQUIRE(success);
@ -178,10 +163,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
bool tls = false; bool tls = false;
std::shared_ptr<Socket> socket = createSocket(tls, errMsg); std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
std::string host("127.0.0.1"); std::string host("127.0.0.1");
auto isCancellationRequested = []() -> bool auto isCancellationRequested = []() -> bool { return false; };
{
return false;
};
bool success = socket->connect(host, port, errMsg, isCancellationRequested); bool success = socket->connect(host, port, errMsg, isCancellationRequested);
REQUIRE(success); REQUIRE(success);

View File

@ -4,13 +4,12 @@
* Copyright (c) 2017 Machine Zone. All rights reserved. * Copyright (c) 2017 Machine Zone. All rights reserved.
*/ */
#include <iostream>
#include <sstream>
#include <set>
#include <ixwebsocket/IXWebSocket.h>
#include "IXTest.h" #include "IXTest.h"
#include "catch.hpp" #include "catch.hpp"
#include <iostream>
#include <ixwebsocket/IXWebSocket.h>
#include <set>
#include <sstream>
using namespace ix; using namespace ix;
@ -19,7 +18,7 @@ namespace
const std::string WEBSOCKET_DOT_ORG_URL("wss://echo.websocket.org"); const std::string WEBSOCKET_DOT_ORG_URL("wss://echo.websocket.org");
const std::string GOOGLE_URL("wss://google.com"); const std::string GOOGLE_URL("wss://google.com");
const std::string UNKNOWN_URL("wss://asdcasdcaasdcasdcasdcasdcasdcasdcasassdd.com"); const std::string UNKNOWN_URL("wss://asdcasdcaasdcasdcasdcasdcasdcasdcasassdd.com");
} } // namespace
namespace namespace
{ {
@ -51,9 +50,7 @@ namespace
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + url); log(std::string("Connecting to url: ") + url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg) {
[](const ix::WebSocketMessagePtr& msg)
{
std::stringstream ss; std::stringstream ss;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
@ -100,11 +97,12 @@ namespace
// Start the connection // Start the connection
_webSocket.start(); _webSocket.start();
} }
} } // namespace
// //
// We try to connect to different servers, and make sure there are no crashes. // We try to connect to different servers, and make sure there are no crashes.
// FIXME: We could do more checks (make sure that we were not able to connect to unknown servers, etc...) // FIXME: We could do more checks (make sure that we were not able to connect to unknown servers,
// etc...)
// //
TEST_CASE("websocket_connections", "[websocket]") TEST_CASE("websocket_connections", "[websocket]")
{ {
@ -121,7 +119,8 @@ TEST_CASE("websocket_connections", "[websocket]")
test.stop(); test.stop();
} }
SECTION("Try to connect and disconnect with different timing, not enough time to succesfully connect") SECTION("Try to connect and disconnect with different timing, not enough time to succesfully "
"connect")
{ {
IXWebSocketTestConnectionDisconnection test; IXWebSocketTestConnectionDisconnection test;
log(std::string("50 Runs")); log(std::string("50 Runs"));
@ -141,7 +140,8 @@ TEST_CASE("websocket_connections", "[websocket]")
// This test breaks on travis CI - Ubuntu Xenial + gcc + tsan // This test breaks on travis CI - Ubuntu Xenial + gcc + tsan
// We should fix this. // We should fix this.
SECTION("Try to connect and disconnect with different timing, from not enough time to successfull connect") SECTION("Try to connect and disconnect with different timing, from not enough time to "
"successfull connect")
{ {
IXWebSocketTestConnectionDisconnection test; IXWebSocketTestConnectionDisconnection test;
log(std::string("20 Runs")); log(std::string("20 Runs"));

View File

@ -6,20 +6,15 @@
#define CATCH_CONFIG_RUNNER #define CATCH_CONFIG_RUNNER
#include "catch.hpp" #include "catch.hpp"
#include <spdlog/spdlog.h>
#include <ixwebsocket/IXNetSystem.h>
#include <ixcore/utils/IXCoreLogger.h> #include <ixcore/utils/IXCoreLogger.h>
#include <ixwebsocket/IXNetSystem.h>
#include <spdlog/spdlog.h>
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
ix::initNetSystem(); ix::initNetSystem();
ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) { spdlog::info(msg); };
{
spdlog::info(msg);
};
ix::IXCoreLogger::setLogFunction(logFunc); ix::IXCoreLogger::setLogFunction(logFunc);
int result = Catch::Session().run(argc, argv); int result = Catch::Session().run(argc, argv);

View File

@ -5,14 +5,14 @@
*/ */
#include "IXRedisClient.h" #include "IXRedisClient.h"
#include <ixwebsocket/IXSocketFactory.h>
#include <ixwebsocket/IXSocket.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <cstring> #include <cstring>
#include <iomanip>
#include <iostream>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXSocketFactory.h>
#include <sstream>
#include <vector>
namespace ix namespace ix
{ {
@ -31,8 +31,7 @@ namespace ix
return _socket->connect(hostname, port, errMsg, nullptr); return _socket->connect(hostname, port, errMsg, nullptr);
} }
bool RedisClient::auth(const std::string& password, bool RedisClient::auth(const std::string& password, std::string& response)
std::string& response)
{ {
response.clear(); response.clear();
@ -246,4 +245,4 @@ namespace ix
{ {
_stop = true; _stop = true;
} }
} } // namespace ix

View File

@ -6,9 +6,9 @@
#pragma once #pragma once
#include <atomic>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <atomic>
namespace ix namespace ix
{ {
@ -20,7 +20,10 @@ namespace ix
using OnRedisSubscribeResponseCallback = std::function<void(const std::string&)>; using OnRedisSubscribeResponseCallback = std::function<void(const std::string&)>;
using OnRedisSubscribeCallback = std::function<void(const std::string&)>; using OnRedisSubscribeCallback = std::function<void(const std::string&)>;
RedisClient() : _stop(false) {} RedisClient()
: _stop(false)
{
}
~RedisClient() = default; ~RedisClient() = default;
bool connect(const std::string& hostname, int port); bool connect(const std::string& hostname, int port);

View File

@ -8,17 +8,16 @@
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <spdlog/spdlog.h>
#include <ixwebsocket/IXWebSocketHttpHeaders.h> #include <ixwebsocket/IXWebSocketHttpHeaders.h>
#include <spdlog/spdlog.h>
namespace ix namespace ix
{ {
SentryClient::SentryClient(const std::string& dsn) : SentryClient::SentryClient(const std::string& dsn)
_dsn(dsn), : _dsn(dsn)
_validDsn(false), , _validDsn(false)
_luaFrameRegex("\t([^/]+):([0-9]+): in function '([^/]+)'") , _luaFrameRegex("\t([^/]+):([0-9]+): in function '([^/]+)'")
{ {
const std::regex dsnRegex("(http[s]?)://([^:]+):([^@]+)@([^/]+)/([0-9]+)"); const std::regex dsnRegex("(http[s]?)://([^:]+):([^@]+)@([^/]+)/([0-9]+)");
std::smatch group; std::smatch group;
@ -168,8 +167,7 @@ namespace ix
return _jsonWriter.write(payload); return _jsonWriter.write(payload);
} }
std::pair<HttpResponsePtr, std::string> SentryClient::send(const Json::Value& msg, std::pair<HttpResponsePtr, std::string> SentryClient::send(const Json::Value& msg, bool verbose)
bool verbose)
{ {
auto args = _httpClient.createRequest(); auto args = _httpClient.createRequest();
args->extraHeaders["X-Sentry-Auth"] = SentryClient::computeAuthHeader(); args->extraHeaders["X-Sentry-Auth"] = SentryClient::computeAuthHeader();
@ -177,10 +175,7 @@ namespace ix
args->transferTimeout = 5 * 60; args->transferTimeout = 5 * 60;
args->followRedirects = true; args->followRedirects = true;
args->verbose = verbose; args->verbose = verbose;
args->logger = [](const std::string& msg) args->logger = [](const std::string& msg) { spdlog::info("request logger: {}", msg); };
{
spdlog::info("request logger: {}", msg);
};
std::string body = computePayload(msg); std::string body = computePayload(msg);
HttpResponsePtr response = _httpClient.post(_url, body, args); HttpResponsePtr response = _httpClient.post(_url, body, args);

View File

@ -4,24 +4,20 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include "IXSnakeProtocol.h"
#include "IXAppConfig.h" #include "IXAppConfig.h"
#include "IXSnakeProtocol.h"
#include <iostream> #include <iostream>
#include <ixcrypto/IXUuid.h> #include <ixcrypto/IXUuid.h>
namespace snake namespace snake
{ {
bool isAppKeyValid( bool isAppKeyValid(const AppConfig& appConfig, std::string appkey)
const AppConfig& appConfig,
std::string appkey)
{ {
return appConfig.apps.count(appkey) != 0; return appConfig.apps.count(appkey) != 0;
} }
std::string getRoleSecret( std::string getRoleSecret(const AppConfig& appConfig, std::string appkey, std::string role)
const AppConfig& appConfig,
std::string appkey,
std::string role)
{ {
if (!isAppKeyValid(appConfig, appkey)) if (!isAppKeyValid(appConfig, appkey))
{ {
@ -49,4 +45,4 @@ namespace snake
std::cout << "redis password: " << appConfig.redisPassword << std::endl; std::cout << "redis password: " << appConfig.redisPassword << std::endl;
std::cout << "redis port: " << appConfig.redisPort << std::endl; std::cout << "redis port: " << appConfig.redisPort << std::endl;
} }
} } // namespace snake

View File

@ -16,16 +16,37 @@ namespace snake
class SnakeConnectionState : public ix::ConnectionState class SnakeConnectionState : public ix::ConnectionState
{ {
public: public:
std::string getNonce() { return _nonce; } std::string getNonce()
void setNonce(const std::string& nonce) { _nonce = nonce; } {
return _nonce;
}
void setNonce(const std::string& nonce)
{
_nonce = nonce;
}
std::string appkey() { return _appkey; } std::string appkey()
void setAppkey(const std::string& appkey) { _appkey = appkey; } {
return _appkey;
}
void setAppkey(const std::string& appkey)
{
_appkey = appkey;
}
std::string role() { return _role; } std::string role()
void setRole(const std::string& role) { _role = role; } {
return _role;
}
void setRole(const std::string& role)
{
_role = role;
}
ix::RedisClient& redisClient() { return _redisClient; } ix::RedisClient& redisClient()
{
return _redisClient;
}
std::future<void> fut; std::future<void> fut;

View File

@ -6,20 +6,17 @@
#include "IXSnakeProtocol.h" #include "IXSnakeProtocol.h"
#include <ixwebsocket/IXWebSocket.h>
#include <ixcrypto/IXHMac.h>
#include "IXSnakeConnectionState.h"
#include "IXAppConfig.h" #include "IXAppConfig.h"
#include "IXSnakeConnectionState.h"
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
#include <sstream>
#include <iostream> #include <iostream>
#include <ixcrypto/IXHMac.h>
#include <ixwebsocket/IXWebSocket.h>
#include <sstream>
namespace snake namespace snake
{ {
void handleError( void handleError(const std::string& action,
const std::string& action,
std::shared_ptr<ix::WebSocket> ws, std::shared_ptr<ix::WebSocket> ws,
nlohmann::json pdu, nlohmann::json pdu,
const std::string& errMsg) const std::string& errMsg)
@ -28,17 +25,11 @@ namespace snake
actionError += "/error"; actionError += "/error";
nlohmann::json response = { nlohmann::json response = {
{"action", actionError}, {"action", actionError}, {"id", pdu.value("id", 1)}, {"body", {{"reason", errMsg}}}};
{"id", pdu.value("id", 1)},
{"body", {
{"reason", errMsg}
}}
};
ws->sendText(response.dump()); ws->sendText(response.dump());
} }
void handleHandshake( void handleHandshake(std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<ix::WebSocket> ws, std::shared_ptr<ix::WebSocket> ws,
const nlohmann::json& pdu) const nlohmann::json& pdu)
{ {
@ -50,13 +41,10 @@ namespace snake
nlohmann::json response = { nlohmann::json response = {
{"action", "auth/handshake/ok"}, {"action", "auth/handshake/ok"},
{"id", pdu.value("id", 1)}, {"id", pdu.value("id", 1)},
{"body", { {"body",
{"data", { {
{"nonce", state->getNonce()}, {"data", {{"nonce", state->getNonce()}, {"connection_id", state->getId()}}},
{"connection_id", state->getId()} }}};
}},
}}
};
auto serializedResponse = response.dump(); auto serializedResponse = response.dump();
std::cout << "response = " << serializedResponse << std::endl; std::cout << "response = " << serializedResponse << std::endl;
@ -64,8 +52,7 @@ namespace snake
ws->sendText(serializedResponse); ws->sendText(serializedResponse);
} }
void handleAuth( void handleAuth(std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<ix::WebSocket> ws, std::shared_ptr<ix::WebSocket> ws,
const AppConfig& appConfig, const AppConfig& appConfig,
const nlohmann::json& pdu) const nlohmann::json& pdu)
@ -78,11 +65,7 @@ namespace snake
nlohmann::json response = { nlohmann::json response = {
{"action", "auth/authenticate/error"}, {"action", "auth/authenticate/error"},
{"id", pdu.value("id", 1)}, {"id", pdu.value("id", 1)},
{"body", { {"body", {{"error", "authentication_failed"}, {"reason", "invalid secret"}}}};
{"error", "authentication_failed"},
{"reason", "invalid secret"}
}}
};
ws->sendText(response.dump()); ws->sendText(response.dump());
return; return;
} }
@ -102,26 +85,18 @@ namespace snake
nlohmann::json response = { nlohmann::json response = {
{"action", "auth/authenticate/error"}, {"action", "auth/authenticate/error"},
{"id", pdu.value("id", 1)}, {"id", pdu.value("id", 1)},
{"body", { {"body", {{"error", "authentication_failed"}, {"reason", "invalid hash"}}}};
{"error", "authentication_failed"},
{"reason", "invalid hash"}
}}
};
ws->sendText(response.dump()); ws->sendText(response.dump());
return; return;
} }
nlohmann::json response = { nlohmann::json response = {
{"action", "auth/authenticate/ok"}, {"action", "auth/authenticate/ok"}, {"id", pdu.value("id", 1)}, {"body", {}}};
{"id", pdu.value("id", 1)},
{"body", {}}
};
ws->sendText(response.dump()); ws->sendText(response.dump());
} }
void handlePublish( void handlePublish(std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<ix::WebSocket> ws, std::shared_ptr<ix::WebSocket> ws,
const nlohmann::json& pdu) const nlohmann::json& pdu)
{ {
@ -150,9 +125,7 @@ namespace snake
for (auto&& channel : channels) for (auto&& channel : channels)
{ {
std::stringstream ss; std::stringstream ss;
ss << state->appkey() ss << state->appkey() << "::" << channel;
<< "::"
<< channel;
std::string errMsg; std::string errMsg;
if (!state->redisClient().publish(ss.str(), pdu.dump(), errMsg)) if (!state->redisClient().publish(ss.str(), pdu.dump(), errMsg))
@ -165,10 +138,7 @@ namespace snake
} }
nlohmann::json response = { nlohmann::json response = {
{"action", "rtm/publish/ok"}, {"action", "rtm/publish/ok"}, {"id", pdu.value("id", 1)}, {"body", {}}};
{"id", pdu.value("id", 1)},
{"body", {}}
};
ws->sendText(response.dump()); ws->sendText(response.dump());
} }
@ -176,8 +146,7 @@ namespace snake
// //
// FIXME: this is not cancellable. We should be able to cancel the redis subscription // FIXME: this is not cancellable. We should be able to cancel the redis subscription
// //
void handleRedisSubscription( void handleRedisSubscription(std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<ix::WebSocket> ws, std::shared_ptr<ix::WebSocket> ws,
const AppConfig& appConfig, const AppConfig& appConfig,
const nlohmann::json& pdu) const nlohmann::json& pdu)
@ -186,9 +155,7 @@ namespace snake
std::string subscriptionId = channel; std::string subscriptionId = channel;
std::stringstream ss; std::stringstream ss;
ss << state->appkey() ss << state->appkey() << "::" << channel;
<< "::"
<< channel;
std::string appChannel(ss.str()); std::string appChannel(ss.str());
@ -224,8 +191,7 @@ namespace snake
} }
int id = 0; int id = 0;
auto callback = [ws, &id, &subscriptionId](const std::string& messageStr) auto callback = [ws, &id, &subscriptionId](const std::string& messageStr) {
{
auto msg = nlohmann::json::parse(messageStr); auto msg = nlohmann::json::parse(messageStr);
msg = msg["body"]["message"]; msg = msg["body"]["message"];
@ -233,27 +199,18 @@ namespace snake
nlohmann::json response = { nlohmann::json response = {
{"action", "rtm/subscription/data"}, {"action", "rtm/subscription/data"},
{"id", id++}, {"id", id++},
{"body", { {"body", {{"subscription_id", subscriptionId}, {"messages", {msg}}}}};
{"subscription_id", subscriptionId},
{"messages", {msg}}
}}
};
ws->sendText(response.dump()); ws->sendText(response.dump());
}; };
auto responseCallback = [ws, pdu, &subscriptionId](const std::string& redisResponse) auto responseCallback = [ws, pdu, &subscriptionId](const std::string& redisResponse) {
{
std::cout << "Redis subscribe response: " << redisResponse << std::endl; std::cout << "Redis subscribe response: " << redisResponse << std::endl;
// Success // Success
nlohmann::json response = { nlohmann::json response = {{"action", "rtm/subscribe/ok"},
{"action", "rtm/subscribe/ok"},
{"id", pdu.value("id", 1)}, {"id", pdu.value("id", 1)},
{"body", { {"body", {{"subscription_id", subscriptionId}}}};
{"subscription_id", subscriptionId}
}}
};
ws->sendText(response.dump()); ws->sendText(response.dump());
}; };
@ -267,22 +224,16 @@ namespace snake
} }
} }
void handleSubscribe( void handleSubscribe(std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<ix::WebSocket> ws, std::shared_ptr<ix::WebSocket> ws,
const AppConfig& appConfig, const AppConfig& appConfig,
const nlohmann::json& pdu) const nlohmann::json& pdu)
{ {
state->fut = std::async(std::launch::async, state->fut =
handleRedisSubscription, std::async(std::launch::async, handleRedisSubscription, state, ws, appConfig, pdu);
state,
ws,
appConfig,
pdu);
} }
void handleUnSubscribe( void handleUnSubscribe(std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<ix::WebSocket> ws, std::shared_ptr<ix::WebSocket> ws,
const nlohmann::json& pdu) const nlohmann::json& pdu)
{ {
@ -292,18 +243,13 @@ namespace snake
state->redisClient().stop(); state->redisClient().stop();
nlohmann::json response = { nlohmann::json response = {{"action", "rtm/unsubscribe/ok"},
{"action", "rtm/unsubscribe/ok"},
{"id", pdu.value("id", 1)}, {"id", pdu.value("id", 1)},
{"body", { {"body", {{"subscription_id", subscriptionId}}}};
{"subscription_id", subscriptionId}
}}
};
ws->sendText(response.dump()); ws->sendText(response.dump());
} }
void processCobraMessage( void processCobraMessage(std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<SnakeConnectionState> state,
std::shared_ptr<ix::WebSocket> ws, std::shared_ptr<ix::WebSocket> ws,
const AppConfig& appConfig, const AppConfig& appConfig,
const std::string& str) const std::string& str)
@ -339,4 +285,4 @@ namespace snake
std::cerr << "Unhandled action: " << action << std::endl; std::cerr << "Unhandled action: " << action << std::endl;
} }
} }
} } // namespace snake

View File

@ -5,18 +5,18 @@
*/ */
#include "IXSnakeServer.h" #include "IXSnakeServer.h"
#include "IXSnakeProtocol.h"
#include "IXSnakeConnectionState.h"
#include "IXAppConfig.h"
#include "IXAppConfig.h"
#include "IXSnakeConnectionState.h"
#include "IXSnakeProtocol.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
namespace snake namespace snake
{ {
SnakeServer::SnakeServer(const AppConfig& appConfig) : SnakeServer::SnakeServer(const AppConfig& appConfig)
_appConfig(appConfig), : _appConfig(appConfig)
_server(appConfig.port, appConfig.hostname) , _server(appConfig.port, appConfig.hostname)
{ {
; ;
} }
@ -45,21 +45,18 @@ namespace snake
{ {
std::cout << "Listening on " << _appConfig.hostname << ":" << _appConfig.port << std::endl; std::cout << "Listening on " << _appConfig.hostname << ":" << _appConfig.port << std::endl;
auto factory = []() -> std::shared_ptr<ix::ConnectionState> auto factory = []() -> std::shared_ptr<ix::ConnectionState> {
{
return std::make_shared<SnakeConnectionState>(); return std::make_shared<SnakeConnectionState>();
}; };
_server.setConnectionStateFactory(factory); _server.setConnectionStateFactory(factory);
_server.setOnConnectionCallback( _server.setOnConnectionCallback(
[this](std::shared_ptr<ix::WebSocket> webSocket, [this](std::shared_ptr<ix::WebSocket> webSocket,
std::shared_ptr<ix::ConnectionState> connectionState) std::shared_ptr<ix::ConnectionState> connectionState) {
{
auto state = std::dynamic_pointer_cast<SnakeConnectionState>(connectionState); auto state = std::dynamic_pointer_cast<SnakeConnectionState>(connectionState);
webSocket->setOnMessageCallback( webSocket->setOnMessageCallback(
[this, webSocket, state](const ix::WebSocketMessagePtr& msg) [this, webSocket, state](const ix::WebSocketMessagePtr& msg) {
{
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
std::cerr << "New connection" << std::endl; std::cerr << "New connection" << std::endl;
@ -84,8 +81,8 @@ namespace snake
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
std::cerr << "Closed connection" std::cerr << "Closed connection"
<< " code " << msg->closeInfo.code << " code " << msg->closeInfo.code << " reason "
<< " reason " << msg->closeInfo.reason << std::endl; << msg->closeInfo.reason << std::endl;
} }
else if (msg->type == ix::WebSocketMessageType::Error) else if (msg->type == ix::WebSocketMessageType::Error)
{ {
@ -105,10 +102,8 @@ namespace snake
std::cerr << "Received " << msg->wireSize << " bytes" << std::endl; std::cerr << "Received " << msg->wireSize << " bytes" << std::endl;
processCobraMessage(state, webSocket, _appConfig, msg->str); processCobraMessage(state, webSocket, _appConfig, msg->str);
} }
} });
); });
}
);
auto res = _server.listen(); auto res = _server.listen();
if (!res.first) if (!res.first)
@ -133,4 +128,4 @@ namespace snake
{ {
_server.stop(); _server.stop();
} }
} } // namespace snake

108
ws/ws.cpp
View File

@ -9,27 +9,22 @@
// //
#include "ws.h" #include "ws.h"
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <cli11/CLI11.hpp> #include <cli11/CLI11.hpp>
#include <spdlog/spdlog.h> #include <fstream>
#include <iostream>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXNetSystem.h>
#include <ixcore/utils/IXCoreLogger.h> #include <ixcore/utils/IXCoreLogger.h>
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXSocket.h>
#include <spdlog/spdlog.h>
#include <sstream>
#include <string>
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
ix::initNetSystem(); ix::initNetSystem();
ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) { spdlog::info(msg); };
{
spdlog::info(msg);
};
ix::IXCoreLogger::setLogFunction(logFunc); ix::IXCoreLogger::setLogFunction(logFunc);
// Display command. // Display command.
@ -94,12 +89,15 @@ int main(int argc, char** argv)
CLI::App* sendApp = app.add_subcommand("send", "Send a file"); CLI::App* sendApp = app.add_subcommand("send", "Send a file");
sendApp->add_option("url", url, "Connection url")->required(); sendApp->add_option("url", url, "Connection url")->required();
sendApp->add_option("path", path, "Path to the file to send") sendApp->add_option("path", path, "Path to the file to send")
->required()->check(CLI::ExistingPath); ->required()
->check(CLI::ExistingPath);
sendApp->add_option("--pidfile", pidfile, "Pid file"); sendApp->add_option("--pidfile", pidfile, "Pid file");
CLI::App* receiveApp = app.add_subcommand("receive", "Receive a file"); CLI::App* receiveApp = app.add_subcommand("receive", "Receive a file");
receiveApp->add_option("url", url, "Connection url")->required(); receiveApp->add_option("url", url, "Connection url")->required();
receiveApp->add_option("--delay", delayMs, "Delay (ms) to wait after receiving a fragment" receiveApp->add_option("--delay",
delayMs,
"Delay (ms) to wait after receiving a fragment"
" to artificially slow down the receiver"); " to artificially slow down the receiver");
receiveApp->add_option("--pidfile", pidfile, "Pid file"); receiveApp->add_option("--pidfile", pidfile, "Pid file");
@ -114,7 +112,9 @@ int main(int argc, char** argv)
connectApp->add_flag("-d", disableAutomaticReconnection, "Disable Automatic Reconnection"); connectApp->add_flag("-d", disableAutomaticReconnection, "Disable Automatic Reconnection");
connectApp->add_flag("-x", disablePerMessageDeflate, "Disable per message deflate"); connectApp->add_flag("-x", disablePerMessageDeflate, "Disable per message deflate");
connectApp->add_flag("-b", binaryMode, "Send in binary mode"); connectApp->add_flag("-b", binaryMode, "Send in binary mode");
connectApp->add_option("--max_wait", maxWaitBetweenReconnectionRetries, "Max Wait Time between reconnection retries"); connectApp->add_option("--max_wait",
maxWaitBetweenReconnectionRetries,
"Max Wait Time between reconnection retries");
CLI::App* chatApp = app.add_subcommand("chat", "Group chat"); CLI::App* chatApp = app.add_subcommand("chat", "Group chat");
chatApp->add_option("url", url, "Connection url")->required(); chatApp->add_option("url", url, "Connection url")->required();
@ -181,9 +181,11 @@ int main(int argc, char** argv)
cobraPublish->add_option("channel", channel, "Channel")->required(); cobraPublish->add_option("channel", channel, "Channel")->required();
cobraPublish->add_option("--pidfile", pidfile, "Pid file"); cobraPublish->add_option("--pidfile", pidfile, "Pid file");
cobraPublish->add_option("path", path, "Path to the file to send") cobraPublish->add_option("path", path, "Path to the file to send")
->required()->check(CLI::ExistingPath); ->required()
->check(CLI::ExistingPath);
CLI::App* cobraMetricsPublish = app.add_subcommand("cobra_metrics_publish", "Cobra metrics publisher"); CLI::App* cobraMetricsPublish =
app.add_subcommand("cobra_metrics_publish", "Cobra metrics publisher");
cobraMetricsPublish->add_option("--appkey", appkey, "Appkey"); cobraMetricsPublish->add_option("--appkey", appkey, "Appkey");
cobraMetricsPublish->add_option("--endpoint", endpoint, "Endpoint"); cobraMetricsPublish->add_option("--endpoint", endpoint, "Endpoint");
cobraMetricsPublish->add_option("--rolename", rolename, "Role name"); cobraMetricsPublish->add_option("--rolename", rolename, "Role name");
@ -191,7 +193,8 @@ int main(int argc, char** argv)
cobraMetricsPublish->add_option("channel", channel, "Channel")->required(); cobraMetricsPublish->add_option("channel", channel, "Channel")->required();
cobraMetricsPublish->add_option("--pidfile", pidfile, "Pid file"); cobraMetricsPublish->add_option("--pidfile", pidfile, "Pid file");
cobraMetricsPublish->add_option("path", path, "Path to the file to send") cobraMetricsPublish->add_option("path", path, "Path to the file to send")
->required()->check(CLI::ExistingPath); ->required()
->check(CLI::ExistingPath);
cobraMetricsPublish->add_flag("--stress", stress, "Stress mode"); cobraMetricsPublish->add_flag("--stress", stress, "Stress mode");
CLI::App* cobra2statsd = app.add_subcommand("cobra_to_statsd", "Cobra to statsd"); CLI::App* cobra2statsd = app.add_subcommand("cobra_to_statsd", "Cobra to statsd");
@ -269,8 +272,11 @@ int main(int argc, char** argv)
} }
else if (app.got_subcommand("connect")) else if (app.got_subcommand("connect"))
{ {
ret = ix::ws_connect_main(url, headers, disableAutomaticReconnection, ret = ix::ws_connect_main(url,
disablePerMessageDeflate, binaryMode, headers,
disableAutomaticReconnection,
disablePerMessageDeflate,
binaryMode,
maxWaitBetweenReconnectionRetries); maxWaitBetweenReconnectionRetries);
} }
else if (app.got_subcommand("chat")) else if (app.got_subcommand("chat"))
@ -291,15 +297,22 @@ int main(int argc, char** argv)
} }
else if (app.got_subcommand("curl")) else if (app.got_subcommand("curl"))
{ {
ret = ix::ws_http_client_main(url, headers, data, headersOnly, ret = ix::ws_http_client_main(url,
connectTimeOut, transferTimeout, headers,
followRedirects, maxRedirects, verbose, data,
save, output, compress); headersOnly,
connectTimeOut,
transferTimeout,
followRedirects,
maxRedirects,
verbose,
save,
output,
compress);
} }
else if (app.got_subcommand("redis_publish")) else if (app.got_subcommand("redis_publish"))
{ {
ret = ix::ws_redis_publish_main(hostname, redisPort, password, ret = ix::ws_redis_publish_main(hostname, redisPort, password, channel, message, count);
channel, message, count);
} }
else if (app.got_subcommand("redis_subscribe")) else if (app.got_subcommand("redis_subscribe"))
{ {
@ -307,42 +320,41 @@ int main(int argc, char** argv)
} }
else if (app.got_subcommand("cobra_subscribe")) else if (app.got_subcommand("cobra_subscribe"))
{ {
ret = ix::ws_cobra_subscribe_main(appkey, endpoint, ret = ix::ws_cobra_subscribe_main(
rolename, rolesecret, appkey, endpoint, rolename, rolesecret, channel, filter, quiet);
channel, filter, quiet);
} }
else if (app.got_subcommand("cobra_publish")) else if (app.got_subcommand("cobra_publish"))
{ {
ret = ix::ws_cobra_publish_main(appkey, endpoint, ret = ix::ws_cobra_publish_main(appkey, endpoint, rolename, rolesecret, channel, path);
rolename, rolesecret,
channel, path);
} }
else if (app.got_subcommand("cobra_metrics_publish")) else if (app.got_subcommand("cobra_metrics_publish"))
{ {
ret = ix::ws_cobra_metrics_publish_main(appkey, endpoint, ret = ix::ws_cobra_metrics_publish_main(
rolename, rolesecret, appkey, endpoint, rolename, rolesecret, channel, path, stress);
channel, path, stress);
} }
else if (app.got_subcommand("cobra_to_statsd")) else if (app.got_subcommand("cobra_to_statsd"))
{ {
ret = ix::ws_cobra_to_statsd_main(appkey, endpoint, ret = ix::ws_cobra_to_statsd_main(appkey,
rolename, rolesecret, endpoint,
channel, filter, hostname, statsdPort, rolename,
prefix, fields, verbose); rolesecret,
channel,
filter,
hostname,
statsdPort,
prefix,
fields,
verbose);
} }
else if (app.got_subcommand("cobra_to_sentry")) else if (app.got_subcommand("cobra_to_sentry"))
{ {
ret = ix::ws_cobra_to_sentry_main(appkey, endpoint, ret = ix::ws_cobra_to_sentry_main(
rolename, rolesecret, appkey, endpoint, rolename, rolesecret, channel, filter, dsn, verbose, strict, jobs);
channel, filter, dsn,
verbose, strict, jobs);
} }
else if (app.got_subcommand("snake")) else if (app.got_subcommand("snake"))
{ {
ret = ix::ws_snake_main(port, hostname, ret = ix::ws_snake_main(
redisHosts, redisPort, port, hostname, redisHosts, redisPort, redisPassword, verbose, appsConfigPath);
redisPassword, verbose,
appsConfigPath);
} }
else if (app.got_subcommand("httpd")) else if (app.got_subcommand("httpd"))
{ {

View File

@ -21,7 +21,8 @@
// //
// //
// 2 Run the test server (using docker) // 2 Run the test server (using docker)
// docker run -it --rm -v "${PWD}/config:/config" -v "${PWD}/reports:/reports" -p 9001:9001 --name fuzzingserver crossbario/autobahn-testsuite // docker run -it --rm -v "${PWD}/config:/config" -v "${PWD}/reports:/reports" -p 9001:9001 --name
// fuzzingserver crossbario/autobahn-testsuite
// //
// 3. Run this command // 3. Run this command
// ws autobahn -q --url ws://localhost:9001 // ws autobahn -q --url ws://localhost:9001
@ -29,15 +30,14 @@
// 4. A HTML report will be generated, you can inspect it to see if you are compliant or not // 4. A HTML report will be generated, you can inspect it to see if you are compliant or not
// //
#include <iostream>
#include <sstream>
#include <atomic> #include <atomic>
#include <mutex>
#include <condition_variable> #include <condition_variable>
#include <ixwebsocket/IXWebSocket.h> #include <iostream>
#include <ixwebsocket/IXSocket.h> #include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXWebSocket.h>
#include <mutex>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <sstream>
namespace namespace
@ -53,7 +53,7 @@ namespace
return str.substr(0, n) + "..."; return str.substr(0, n) + "...";
} }
} }
} } // namespace
namespace ix namespace ix
{ {
@ -75,9 +75,9 @@ namespace ix
std::condition_variable _condition; std::condition_variable _condition;
}; };
AutobahnTestCase::AutobahnTestCase(const std::string& url, bool quiet) : AutobahnTestCase::AutobahnTestCase(const std::string& url, bool quiet)
_url(url), : _url(url)
_quiet(quiet) , _quiet(quiet)
{ {
_webSocket.disableAutomaticReconnection(); _webSocket.disableAutomaticReconnection();
@ -102,9 +102,7 @@ namespace ix
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + _url); log(std::string("Connecting to url: ") + _url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) {
[this](const ix::WebSocketMessagePtr& msg)
{
std::stringstream ss; std::stringstream ss;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
@ -128,9 +126,7 @@ namespace ix
{ {
ss << "Received " << msg->wireSize << " bytes" << std::endl; ss << "Received " << msg->wireSize << " bytes" << std::endl;
ss << "autobahn: received message: " ss << "autobahn: received message: " << truncate(msg->str, 40) << std::endl;
<< truncate(msg->str, 40)
<< std::endl;
_webSocket.send(msg->str, msg->binary); _webSocket.send(msg->str, msg->binary);
} }
@ -184,9 +180,7 @@ namespace ix
std::atomic<bool> success(true); std::atomic<bool> success(true);
std::condition_variable condition; std::condition_variable condition;
webSocket.setOnMessageCallback( webSocket.setOnMessageCallback([&condition, &success](const ix::WebSocketMessagePtr& msg) {
[&condition, &success](const ix::WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Close) if (msg->type == ix::WebSocketMessageType::Close)
{ {
std::cerr << "Report generated" << std::endl; std::cerr << "Report generated" << std::endl;
@ -203,8 +197,7 @@ namespace ix
success = false; success = false;
} }
} });
);
webSocket.start(); webSocket.start();
std::mutex mutex; std::mutex mutex;
@ -231,9 +224,7 @@ namespace ix
int count = -1; int count = -1;
std::condition_variable condition; std::condition_variable condition;
webSocket.setOnMessageCallback( webSocket.setOnMessageCallback([&condition, &count](const ix::WebSocketMessagePtr& msg) {
[&condition, &count](const ix::WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Close) if (msg->type == ix::WebSocketMessageType::Close)
{ {
condition.notify_one(); condition.notify_one();
@ -256,8 +247,7 @@ namespace ix
ss << msg->str; ss << msg->str;
ss >> count; ss >> count;
} }
} });
);
webSocket.start(); webSocket.start();
std::mutex mutex; std::mutex mutex;
@ -296,10 +286,7 @@ namespace ix
int caseNumber = i; int caseNumber = i;
std::stringstream ss; std::stringstream ss;
ss << url ss << url << "/runCase?case=" << caseNumber << "&agent=ixwebsocket";
<< "/runCase?case="
<< caseNumber
<< "&agent=ixwebsocket";
std::string url(ss.str()); std::string url(ss.str());
@ -309,4 +296,4 @@ namespace ix
return generateReport(url) ? 0 : 1; return generateReport(url) ? 0 : 1;
} }
} } // namespace ix

View File

@ -5,8 +5,8 @@
*/ */
#include <iostream> #include <iostream>
#include <sstream>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include <sstream>
namespace ix namespace ix
{ {
@ -16,13 +16,10 @@ namespace ix
ix::WebSocketServer server(port, hostname); ix::WebSocketServer server(port, hostname);
server.setOnConnectionCallback( server.setOnConnectionCallback([&server](std::shared_ptr<WebSocket> webSocket,
[&server](std::shared_ptr<WebSocket> webSocket, std::shared_ptr<ConnectionState> connectionState) {
std::shared_ptr<ConnectionState> connectionState) webSocket->setOnMessageCallback([webSocket, connectionState, &server](
{ const WebSocketMessagePtr& msg) {
webSocket->setOnMessageCallback(
[webSocket, connectionState, &server](const WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
std::cerr << "New connection" << std::endl; std::cerr << "New connection" << std::endl;
@ -37,8 +34,8 @@ namespace ix
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
std::cerr << "Closed connection" std::cerr << "Closed connection"
<< " code " << msg->closeInfo.code << " code " << msg->closeInfo.code << " reason "
<< " reason " << msg->closeInfo.reason << std::endl; << msg->closeInfo.reason << std::endl;
} }
else if (msg->type == ix::WebSocketMessageType::Error) else if (msg->type == ix::WebSocketMessageType::Error)
{ {
@ -61,19 +58,16 @@ namespace ix
{ {
if (client != webSocket) if (client != webSocket)
{ {
client->send(msg->str, client->send(msg->str, msg->binary, [](int current, int total) -> bool {
msg->binary, std::cerr << "Step " << current << " out of " << total << std::endl;
[](int current, int total) -> bool
{
std::cerr << "Step " << current
<< " out of " << total << std::endl;
return true; return true;
}); });
do do
{ {
size_t bufferedAmount = client->bufferedAmount(); size_t bufferedAmount = client->bufferedAmount();
std::cerr << bufferedAmount << " bytes left to be sent" << std::endl; std::cerr << bufferedAmount << " bytes left to be sent"
<< std::endl;
std::chrono::duration<double, std::milli> duration(10); std::chrono::duration<double, std::milli> duration(10);
std::this_thread::sleep_for(duration); std::this_thread::sleep_for(duration);
@ -81,10 +75,8 @@ namespace ix
} }
} }
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -98,4 +90,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -9,13 +9,12 @@
// Broadcast server can be ran with `ws broadcast_server` // Broadcast server can be ran with `ws broadcast_server`
// //
#include <iostream>
#include <sstream>
#include <queue>
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXSocket.h>
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
#include <iostream>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXWebSocket.h>
#include <queue>
#include <sstream>
// for convenience // for convenience
using json = nlohmann::json; using json = nlohmann::json;
@ -25,8 +24,7 @@ namespace ix
class WebSocketChat class WebSocketChat
{ {
public: public:
WebSocketChat(const std::string& url, WebSocketChat(const std::string& url, const std::string& user);
const std::string& user);
void subscribe(const std::string& channel); void subscribe(const std::string& channel);
void start(); void start();
@ -48,10 +46,9 @@ namespace ix
void log(const std::string& msg); void log(const std::string& msg);
}; };
WebSocketChat::WebSocketChat(const std::string& url, WebSocketChat::WebSocketChat(const std::string& url, const std::string& user)
const std::string& user) : : _url(url)
_url(url), , _user(user)
_user(user)
{ {
; ;
} }
@ -83,9 +80,7 @@ namespace ix
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + _url); log(std::string("Connecting to url: ") + _url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](const WebSocketMessagePtr& msg) {
[this](const WebSocketMessagePtr& msg)
{
std::stringstream ss; std::stringstream ss;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
@ -97,18 +92,13 @@ namespace ix
std::cout << it.first << ": " << it.second << std::endl; std::cout << it.first << ": " << it.second << std::endl;
} }
ss << "ws chat: user " ss << "ws chat: user " << _user << " Connected !";
<< _user
<< " Connected !";
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
ss << "ws chat: user " ss << "ws chat: user " << _user << " disconnected !"
<< _user << " code " << msg->closeInfo.code << " reason " << msg->closeInfo.reason;
<< " disconnected !"
<< " code " << msg->closeInfo.code
<< " reason " << msg->closeInfo.reason;
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Message) else if (msg->type == ix::WebSocketMessageType::Message)
@ -122,8 +112,8 @@ namespace ix
_receivedQueue.push(result.second); _receivedQueue.push(result.second);
ss << std::endl ss << std::endl
<< result.first << "(" << msg->wireSize << " bytes)" << " > " << result.second << result.first << "(" << msg->wireSize << " bytes)"
<< std::endl << " > " << result.second << std::endl
<< _user << " > "; << _user << " > ";
log(ss.str()); log(ss.str());
} }
@ -170,8 +160,7 @@ namespace ix
_webSocket.sendText(encodeMessage(text)); _webSocket.sendText(encodeMessage(text));
} }
int ws_chat_main(const std::string& url, int ws_chat_main(const std::string& url, const std::string& user)
const std::string& user)
{ {
std::cout << "Type Ctrl-D to exit prompt..." << std::endl; std::cout << "Type Ctrl-D to exit prompt..." << std::endl;
WebSocketChat webSocketChat(url, user); WebSocketChat webSocketChat(url, user);
@ -196,4 +185,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,15 +4,15 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <thread>
#include <atomic> #include <atomic>
#include <jsoncpp/json/json.h> #include <chrono>
#include <fstream>
#include <iostream>
#include <ixcobra/IXCobraMetricsPublisher.h> #include <ixcobra/IXCobraMetricsPublisher.h>
#include <jsoncpp/json/json.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <sstream>
#include <thread>
namespace ix namespace ix
{ {
@ -27,25 +27,23 @@ namespace ix
std::atomic<int> sentMessages(0); std::atomic<int> sentMessages(0);
std::atomic<int> ackedMessages(0); std::atomic<int> ackedMessages(0);
CobraConnection::setPublishTrackerCallback( CobraConnection::setPublishTrackerCallback(
[&sentMessages, &ackedMessages](bool sent, bool acked) [&sentMessages, &ackedMessages](bool sent, bool acked) {
{
if (sent) sentMessages++; if (sent) sentMessages++;
if (acked) ackedMessages++; if (acked) ackedMessages++;
} });
);
CobraMetricsPublisher cobraMetricsPublisher; CobraMetricsPublisher cobraMetricsPublisher;
cobraMetricsPublisher.enable(true); cobraMetricsPublisher.enable(true);
bool enablePerMessageDeflate = true; bool enablePerMessageDeflate = true;
cobraMetricsPublisher.configure(appkey, endpoint, channel, cobraMetricsPublisher.configure(
rolename, rolesecret, enablePerMessageDeflate); appkey, endpoint, channel, rolename, rolesecret, enablePerMessageDeflate);
while (!cobraMetricsPublisher.isAuthenticated()) ; while (!cobraMetricsPublisher.isAuthenticated())
;
std::ifstream f(path); std::ifstream f(path);
std::string str((std::istreambuf_iterator<char>(f)), std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
std::istreambuf_iterator<char>());
Json::Value data; Json::Value data;
Json::Reader reader; Json::Reader reader;
@ -70,7 +68,8 @@ namespace ix
cobraMetricsPublisher.resume(); cobraMetricsPublisher.resume();
// FIXME: investigate why without this check we trigger a lock // FIXME: investigate why without this check we trigger a lock
while (!cobraMetricsPublisher.isAuthenticated()) ; while (!cobraMetricsPublisher.isAuthenticated())
;
} }
} }
@ -83,5 +82,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,17 +4,17 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <thread>
#include <atomic> #include <atomic>
#include <mutex> #include <chrono>
#include <condition_variable> #include <condition_variable>
#include <jsoncpp/json/json.h> #include <fstream>
#include <iostream>
#include <ixcobra/IXCobraMetricsPublisher.h> #include <ixcobra/IXCobraMetricsPublisher.h>
#include <jsoncpp/json/json.h>
#include <mutex>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <sstream>
#include <thread>
namespace ix namespace ix
{ {
@ -26,8 +26,7 @@ namespace ix
const std::string& path) const std::string& path)
{ {
std::ifstream f(path); std::ifstream f(path);
std::string str((std::istreambuf_iterator<char>(f)), std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
std::istreambuf_iterator<char>());
Json::Value data; Json::Value data;
Json::Reader reader; Json::Reader reader;
@ -38,9 +37,8 @@ namespace ix
} }
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure(appkey, endpoint, conn.configure(
rolename, rolesecret, appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
ix::WebSocketPerMessageDeflateOptions(true));
conn.connect(); conn.connect();
// Display incoming messages // Display incoming messages
@ -48,14 +46,12 @@ namespace ix
std::atomic<bool> messageAcked(false); std::atomic<bool> messageAcked(false);
std::condition_variable condition; std::condition_variable condition;
conn.setEventCallback( conn.setEventCallback([&conn, &channel, &data, &authenticated, &messageAcked, &condition](
[&conn, &channel, &data, &authenticated, &messageAcked, &condition] ix::CobraConnectionEventType eventType,
(ix::CobraConnectionEventType eventType,
const std::string& errMsg, const std::string& errMsg,
const ix::WebSocketHttpHeaders& headers, const ix::WebSocketHttpHeaders& headers,
const std::string& subscriptionId, const std::string& subscriptionId,
CobraConnection::MsgId msgId) CobraConnection::MsgId msgId) {
{
if (eventType == ix::CobraConnection_EventType_Open) if (eventType == ix::CobraConnection_EventType_Open)
{ {
spdlog::info("Publisher connected"); spdlog::info("Publisher connected");
@ -95,12 +91,13 @@ namespace ix
messageAcked = true; messageAcked = true;
condition.notify_one(); condition.notify_one();
} }
} });
);
while (!authenticated) ; while (!authenticated)
while (!messageAcked) ; ;
while (!messageAcked)
;
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,14 +4,13 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <sstream>
#include <chrono>
#include <thread>
#include <atomic> #include <atomic>
#include <chrono>
#include <iostream>
#include <ixcobra/IXCobraConnection.h> #include <ixcobra/IXCobraConnection.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <sstream>
#include <thread>
namespace ix namespace ix
{ {
@ -24,9 +23,8 @@ namespace ix
bool quiet) bool quiet)
{ {
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure(appkey, endpoint, conn.configure(
rolename, rolesecret, appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
ix::WebSocketPerMessageDeflateOptions(true));
conn.connect(); conn.connect();
Json::FastWriter jsonWriter; Json::FastWriter jsonWriter;
@ -35,13 +33,11 @@ namespace ix
std::atomic<int> msgPerSeconds(0); std::atomic<int> msgPerSeconds(0);
std::atomic<int> msgCount(0); std::atomic<int> msgCount(0);
auto timer = [&msgPerSeconds, &msgCount] auto timer = [&msgPerSeconds, &msgCount] {
{
while (true) while (true)
{ {
std::cout << "#messages " << msgCount << " " std::cout << "#messages " << msgCount << " "
<< "msg/s " << msgPerSeconds << "msg/s " << msgPerSeconds << std::endl;
<< std::endl;
msgPerSeconds = 0; msgPerSeconds = 0;
auto duration = std::chrono::seconds(1); auto duration = std::chrono::seconds(1);
@ -52,13 +48,12 @@ namespace ix
std::thread t(timer); std::thread t(timer);
conn.setEventCallback( conn.setEventCallback(
[&conn, &channel, &jsonWriter, &filter, &msgCount, &msgPerSeconds, &quiet] [&conn, &channel, &jsonWriter, &filter, &msgCount, &msgPerSeconds, &quiet](
(ix::CobraConnectionEventType eventType, ix::CobraConnectionEventType eventType,
const std::string& errMsg, const std::string& errMsg,
const ix::WebSocketHttpHeaders& headers, const ix::WebSocketHttpHeaders& headers,
const std::string& subscriptionId, const std::string& subscriptionId,
CobraConnection::MsgId msgId) CobraConnection::MsgId msgId) {
{
if (eventType == ix::CobraConnection_EventType_Open) if (eventType == ix::CobraConnection_EventType_Open)
{ {
spdlog::info("Subscriber connected"); spdlog::info("Subscriber connected");
@ -71,10 +66,10 @@ namespace ix
else if (eventType == ix::CobraConnection_EventType_Authenticated) else if (eventType == ix::CobraConnection_EventType_Authenticated)
{ {
spdlog::info("Subscriber authenticated"); spdlog::info("Subscriber authenticated");
conn.subscribe(channel, filter, conn.subscribe(
[&jsonWriter, &quiet, channel,
&msgPerSeconds, &msgCount](const Json::Value& msg) filter,
{ [&jsonWriter, &quiet, &msgPerSeconds, &msgCount](const Json::Value& msg) {
if (!quiet) if (!quiet)
{ {
std::cout << jsonWriter.write(msg) << std::endl; std::cout << jsonWriter.write(msg) << std::endl;
@ -100,8 +95,7 @@ namespace ix
{ {
spdlog::error("Published message hacked: {}", msgId); spdlog::error("Published message hacked: {}", msgId);
} }
} });
);
while (true) while (true)
{ {
@ -111,4 +105,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,19 +4,18 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <sstream>
#include <chrono>
#include <thread>
#include <atomic>
#include <vector>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <ixcobra/IXCobraConnection.h>
#include <spdlog/spdlog.h>
#include "IXSentryClient.h" #include "IXSentryClient.h"
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <ixcobra/IXCobraConnection.h>
#include <mutex>
#include <queue>
#include <spdlog/spdlog.h>
#include <sstream>
#include <thread>
#include <vector>
namespace ix namespace ix
{ {
@ -32,9 +31,8 @@ namespace ix
int jobs) int jobs)
{ {
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure(appkey, endpoint, conn.configure(
rolename, rolesecret, appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
ix::WebSocketPerMessageDeflateOptions(true));
conn.connect(); conn.connect();
Json::FastWriter jsonWriter; Json::FastWriter jsonWriter;
@ -48,10 +46,15 @@ namespace ix
std::condition_variable progressCondition; std::condition_variable progressCondition;
std::queue<Json::Value> queue; std::queue<Json::Value> queue;
auto sentrySender = [&condition, &progressCondition, &conditionVariableMutex, auto sentrySender = [&condition,
&queue, verbose, &errorSending, &sentCount, &progressCondition,
&stop, &dsn] &conditionVariableMutex,
{ &queue,
verbose,
&errorSending,
&sentCount,
&stop,
&dsn] {
SentryClient sentryClient(dsn); SentryClient sentryClient(dsn);
while (true) while (true)
@ -94,17 +97,21 @@ namespace ix
pool.push_back(std::thread(sentrySender)); pool.push_back(std::thread(sentrySender));
} }
conn.setEventCallback( conn.setEventCallback([&conn,
[&conn, &channel, &filter, &jsonWriter, &channel,
verbose, &receivedCount, &sentCount, &filter,
&condition, &conditionVariableMutex, &jsonWriter,
&progressCondition, &queue] verbose,
(ix::CobraConnectionEventType eventType, &receivedCount,
&sentCount,
&condition,
&conditionVariableMutex,
&progressCondition,
&queue](ix::CobraConnectionEventType eventType,
const std::string& errMsg, const std::string& errMsg,
const ix::WebSocketHttpHeaders& headers, const ix::WebSocketHttpHeaders& headers,
const std::string& subscriptionId, const std::string& subscriptionId,
CobraConnection::MsgId msgId) CobraConnection::MsgId msgId) {
{
if (eventType == ix::CobraConnection_EventType_Open) if (eventType == ix::CobraConnection_EventType_Open)
{ {
spdlog::info("Subscriber connected"); spdlog::info("Subscriber connected");
@ -121,13 +128,16 @@ namespace ix
else if (eventType == ix::CobraConnection_EventType_Authenticated) else if (eventType == ix::CobraConnection_EventType_Authenticated)
{ {
std::cerr << "Subscriber authenticated" << std::endl; std::cerr << "Subscriber authenticated" << std::endl;
conn.subscribe(channel, filter, conn.subscribe(channel,
[&jsonWriter, verbose, filter,
&sentCount, &receivedCount, [&jsonWriter,
&condition, &conditionVariableMutex, verbose,
&progressCondition, &queue] &sentCount,
(const Json::Value& msg) &receivedCount,
{ &condition,
&conditionVariableMutex,
&progressCondition,
&queue](const Json::Value& msg) {
if (verbose) if (verbose)
{ {
spdlog::info(jsonWriter.write(msg)); spdlog::info(jsonWriter.write(msg));
@ -136,8 +146,7 @@ namespace ix
// If we cannot send to sentry fast enough, drop the message // If we cannot send to sentry fast enough, drop the message
const uint64_t scaleFactor = 2; const uint64_t scaleFactor = 2;
if (sentCount != 0 && if (sentCount != 0 && receivedCount != 0 &&
receivedCount != 0 &&
(sentCount * scaleFactor < receivedCount)) (sentCount * scaleFactor < receivedCount))
{ {
spdlog::warn("message dropped: sending is backlogged !"); spdlog::warn("message dropped: sending is backlogged !");
@ -174,8 +183,7 @@ namespace ix
{ {
spdlog::error("Published message hacked: {}", msgId); spdlog::error("Published message hacked: {}", msgId);
} }
} });
);
std::mutex progressConditionVariableMutex; std::mutex progressConditionVariableMutex;
while (true) while (true)
@ -200,4 +208,4 @@ namespace ix
return (strict && errorSending) ? 1 : 0; return (strict && errorSending) ? 1 : 0;
} }
} } // namespace ix

View File

@ -4,15 +4,14 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <sstream>
#include <chrono>
#include <thread>
#include <atomic> #include <atomic>
#include <vector> #include <chrono>
#include <iostream>
#include <ixcobra/IXCobraConnection.h> #include <ixcobra/IXCobraConnection.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <sstream>
#include <thread>
#include <vector>
#ifndef _WIN32 #ifndef _WIN32
#include <statsd_client.h> #include <statsd_client.h>
@ -41,8 +40,7 @@ namespace ix
// Extract an attribute from a Json Value. // Extract an attribute from a Json Value.
// extractAttr("foo.bar", {"foo": {"bar": "baz"}}) => baz // extractAttr("foo.bar", {"foo": {"bar": "baz"}}) => baz
// //
std::string extractAttr(const std::string& attr, std::string extractAttr(const std::string& attr, const Json::Value& jsonValue)
const Json::Value& jsonValue)
{ {
// Split by . // Split by .
std::string token; std::string token;
@ -71,9 +69,8 @@ namespace ix
bool verbose) bool verbose)
{ {
ix::CobraConnection conn; ix::CobraConnection conn;
conn.configure(appkey, endpoint, conn.configure(
rolename, rolesecret, appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true));
ix::WebSocketPerMessageDeflateOptions(true));
conn.connect(); conn.connect();
auto tokens = parseFields(fields); auto tokens = parseFields(fields);
@ -90,14 +87,19 @@ namespace ix
Json::FastWriter jsonWriter; Json::FastWriter jsonWriter;
uint64_t msgCount = 0; uint64_t msgCount = 0;
conn.setEventCallback( conn.setEventCallback([&conn,
[&conn, &channel, &filter, &jsonWriter, &statsdClient, verbose, &tokens, &prefix, &msgCount] &channel,
(ix::CobraConnectionEventType eventType, &filter,
&jsonWriter,
&statsdClient,
verbose,
&tokens,
&prefix,
&msgCount](ix::CobraConnectionEventType eventType,
const std::string& errMsg, const std::string& errMsg,
const ix::WebSocketHttpHeaders& headers, const ix::WebSocketHttpHeaders& headers,
const std::string& subscriptionId, const std::string& subscriptionId,
CobraConnection::MsgId msgId) CobraConnection::MsgId msgId) {
{
if (eventType == ix::CobraConnection_EventType_Open) if (eventType == ix::CobraConnection_EventType_Open)
{ {
spdlog::info("Subscriber connected"); spdlog::info("Subscriber connected");
@ -114,11 +116,10 @@ namespace ix
else if (eventType == ix::CobraConnection_EventType_Authenticated) else if (eventType == ix::CobraConnection_EventType_Authenticated)
{ {
spdlog::info("Subscriber authenticated"); spdlog::info("Subscriber authenticated");
conn.subscribe(channel, filter, conn.subscribe(channel,
[&jsonWriter, &statsdClient, filter,
verbose, &tokens, &prefix, &msgCount] [&jsonWriter, &statsdClient, verbose, &tokens, &prefix, &msgCount](
(const Json::Value& msg) const Json::Value& msg) {
{
if (verbose) if (verbose)
{ {
spdlog::info(jsonWriter.write(msg)); spdlog::info(jsonWriter.write(msg));
@ -154,8 +155,7 @@ namespace ix
{ {
spdlog::error("Published message hacked: {}", msgId); spdlog::error("Published message hacked: {}", msgId);
} }
} });
);
while (true) while (true)
{ {
@ -165,4 +165,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,12 +4,11 @@
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <sstream>
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXSocket.h>
#include "linenoise.hpp" #include "linenoise.hpp"
#include <iostream>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXWebSocket.h>
#include <sstream>
namespace ix namespace ix
@ -46,10 +45,10 @@ namespace ix
bool disableAutomaticReconnection, bool disableAutomaticReconnection,
bool disablePerMessageDeflate, bool disablePerMessageDeflate,
bool binaryMode, bool binaryMode,
uint32_t maxWaitBetweenReconnectionRetries) : uint32_t maxWaitBetweenReconnectionRetries)
_url(url), : _url(url)
_disablePerMessageDeflate(disablePerMessageDeflate), , _disablePerMessageDeflate(disablePerMessageDeflate)
_binaryMode(binaryMode) , _binaryMode(binaryMode)
{ {
if (disableAutomaticReconnection) if (disableAutomaticReconnection)
{ {
@ -114,9 +113,7 @@ namespace ix
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + _url); log(std::string("Connecting to url: ") + _url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) {
[this](const ix::WebSocketMessagePtr& msg)
{
std::stringstream ss; std::stringstream ss;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
@ -139,8 +136,7 @@ namespace ix
{ {
std::cerr << "Received " << msg->wireSize << " bytes" << std::endl; std::cerr << "Received " << msg->wireSize << " bytes" << std::endl;
ss << "ws_connect: received message: " ss << "ws_connect: received message: " << msg->str;
<< msg->str;
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Error) else if (msg->type == ix::WebSocketMessageType::Error)
@ -237,5 +233,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -5,8 +5,8 @@
*/ */
#include <iostream> #include <iostream>
#include <sstream>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include <sstream>
namespace ix namespace ix
{ {
@ -18,11 +18,9 @@ namespace ix
server.setOnConnectionCallback( server.setOnConnectionCallback(
[greetings](std::shared_ptr<ix::WebSocket> webSocket, [greetings](std::shared_ptr<ix::WebSocket> webSocket,
std::shared_ptr<ConnectionState> connectionState) std::shared_ptr<ConnectionState> connectionState) {
{
webSocket->setOnMessageCallback( webSocket->setOnMessageCallback(
[webSocket, connectionState, greetings](const WebSocketMessagePtr& msg) [webSocket, connectionState, greetings](const WebSocketMessagePtr& msg) {
{
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
std::cerr << "New connection" << std::endl; std::cerr << "New connection" << std::endl;
@ -42,8 +40,8 @@ namespace ix
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
std::cerr << "Closed connection" std::cerr << "Closed connection"
<< " code " << msg->closeInfo.code << " code " << msg->closeInfo.code << " reason "
<< " reason " << msg->closeInfo.reason << std::endl; << msg->closeInfo.reason << std::endl;
} }
else if (msg->type == ix::WebSocketMessageType::Error) else if (msg->type == ix::WebSocketMessageType::Error)
{ {
@ -56,15 +54,11 @@ namespace ix
} }
else if (msg->type == ix::WebSocketMessageType::Message) else if (msg->type == ix::WebSocketMessageType::Message)
{ {
std::cerr << "Received " std::cerr << "Received " << msg->wireSize << " bytes" << std::endl;
<< msg->wireSize << " bytes"
<< std::endl;
webSocket->send(msg->str, msg->binary); webSocket->send(msg->str, msg->binary);
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -78,4 +72,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,11 +4,11 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <sstream>
#include <fstream> #include <fstream>
#include <iostream>
#include <ixwebsocket/IXHttpClient.h> #include <ixwebsocket/IXHttpClient.h>
#include <ixwebsocket/IXWebSocketHttpHeaders.h> #include <ixwebsocket/IXWebSocketHttpHeaders.h>
#include <sstream>
namespace ix namespace ix
{ {
@ -104,14 +104,10 @@ namespace ix
args->maxRedirects = maxRedirects; args->maxRedirects = maxRedirects;
args->verbose = verbose; args->verbose = verbose;
args->compress = compress; args->compress = compress;
args->logger = [](const std::string& msg) args->logger = [](const std::string& msg) { std::cout << msg; };
{ args->onProgressCallback = [](int current, int total) -> bool {
std::cout << msg; std::cerr << "\r"
}; << "Downloaded " << current << " bytes out of " << total;
args->onProgressCallback = [](int current, int total) -> bool
{
std::cerr << "\r" << "Downloaded "
<< current << " bytes out of " << total;
return true; return true;
}; };
@ -173,11 +169,12 @@ namespace ix
{ {
std::cerr << "Binary output can mess up your terminal." << std::endl; std::cerr << "Binary output can mess up your terminal." << std::endl;
std::cerr << "Use the -O flag to save the file to disk." << std::endl; std::cerr << "Use the -O flag to save the file to disk." << std::endl;
std::cerr << "You can also use the --output option to specify a filename." << std::endl; std::cerr << "You can also use the --output option to specify a filename."
<< std::endl;
} }
} }
} }
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,12 +4,12 @@
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved. * Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <vector>
#include <fstream> #include <fstream>
#include <sstream> #include <iostream>
#include <ixwebsocket/IXHttpServer.h> #include <ixwebsocket/IXHttpServer.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <sstream>
#include <vector>
namespace ix namespace ix
{ {
@ -31,4 +31,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -5,9 +5,9 @@
*/ */
#include <iostream> #include <iostream>
#include <sstream>
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket/IXSocket.h> #include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXWebSocket.h>
#include <sstream>
namespace ix namespace ix
{ {
@ -30,8 +30,8 @@ namespace ix
void log(const std::string& msg); void log(const std::string& msg);
}; };
WebSocketPingPong::WebSocketPingPong(const std::string& url) : WebSocketPingPong::WebSocketPingPong(const std::string& url)
_url(url) : _url(url)
{ {
; ;
} }
@ -53,9 +53,7 @@ namespace ix
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + _url); log(std::string("Connecting to url: ") + _url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) {
[this](const ix::WebSocketMessagePtr& msg)
{
std::cerr << "Received " << msg->wireSize << " bytes" << std::endl; std::cerr << "Received " << msg->wireSize << " bytes" << std::endl;
std::stringstream ss; std::stringstream ss;
@ -73,27 +71,23 @@ namespace ix
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
ss << "ping_pong: disconnected:" ss << "ping_pong: disconnected:"
<< " code " << msg->closeInfo.code << " code " << msg->closeInfo.code << " reason " << msg->closeInfo.reason
<< " reason " << msg->closeInfo.reason
<< msg->str; << msg->str;
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Message) else if (msg->type == ix::WebSocketMessageType::Message)
{ {
ss << "ping_pong: received message: " ss << "ping_pong: received message: " << msg->str;
<< msg->str;
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Ping) else if (msg->type == ix::WebSocketMessageType::Ping)
{ {
ss << "ping_pong: received ping message: " ss << "ping_pong: received ping message: " << msg->str;
<< msg->str;
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Pong) else if (msg->type == ix::WebSocketMessageType::Pong)
{ {
ss << "ping_pong: received pong message: " ss << "ping_pong: received pong message: " << msg->str;
<< msg->str;
log(ss.str()); log(ss.str());
} }
else if (msg->type == ix::WebSocketMessageType::Error) else if (msg->type == ix::WebSocketMessageType::Error)
@ -118,7 +112,8 @@ namespace ix
{ {
if (!_webSocket.ping(text).success) if (!_webSocket.ping(text).success)
{ {
std::cerr << "Failed to send ping message. Message too long (> 125 bytes) or endpoint is disconnected" std::cerr << "Failed to send ping message. Message too long (> 125 bytes) or endpoint "
"is disconnected"
<< std::endl; << std::endl;
} }
} }
@ -160,4 +155,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,19 +4,19 @@
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <condition_variable>
#include <mutex>
#include <chrono> #include <chrono>
#include <ixwebsocket/IXWebSocket.h> #include <condition_variable>
#include <ixwebsocket/IXSocket.h> #include <fstream>
#include <ixcrypto/IXUuid.h> #include <iostream>
#include <ixcrypto/IXBase64.h> #include <ixcrypto/IXBase64.h>
#include <ixcrypto/IXHash.h> #include <ixcrypto/IXHash.h>
#include <ixcrypto/IXUuid.h>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXWebSocket.h>
#include <msgpack11/msgpack11.hpp> #include <msgpack11/msgpack11.hpp>
#include <mutex>
#include <sstream>
#include <vector>
using msgpack11::MsgPack; using msgpack11::MsgPack;
@ -25,9 +25,7 @@ namespace ix
class WebSocketReceiver class WebSocketReceiver
{ {
public: public:
WebSocketReceiver(const std::string& _url, WebSocketReceiver(const std::string& _url, bool enablePerMessageDeflate, int delayMs);
bool enablePerMessageDeflate,
int delayMs);
void subscribe(const std::string& channel); void subscribe(const std::string& channel);
void start(); void start();
@ -55,11 +53,11 @@ namespace ix
WebSocketReceiver::WebSocketReceiver(const std::string& url, WebSocketReceiver::WebSocketReceiver(const std::string& url,
bool enablePerMessageDeflate, bool enablePerMessageDeflate,
int delayMs) : int delayMs)
_url(url), : _url(url)
_enablePerMessageDeflate(enablePerMessageDeflate), , _enablePerMessageDeflate(enablePerMessageDeflate)
_delayMs(delayMs), , _delayMs(delayMs)
_receivedFragmentCounter(0) , _receivedFragmentCounter(0)
{ {
; ;
} }
@ -107,8 +105,7 @@ namespace ix
} }
} }
void WebSocketReceiver::handleError(const std::string& errMsg, void WebSocketReceiver::handleError(const std::string& errMsg, const std::string& id)
const std::string& id)
{ {
std::map<MsgPack, MsgPack> pdu; std::map<MsgPack, MsgPack> pdu;
pdu["kind"] = "error"; pdu["kind"] = "error";
@ -182,9 +179,7 @@ namespace ix
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + _url); log(std::string("Connecting to url: ") + _url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) {
[this](const ix::WebSocketMessagePtr& msg)
{
std::stringstream ss; std::stringstream ss;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
@ -243,9 +238,7 @@ namespace ix
_webSocket.start(); _webSocket.start();
} }
void wsReceive(const std::string& url, void wsReceive(const std::string& url, bool enablePerMessageDeflate, int delayMs)
bool enablePerMessageDeflate,
int delayMs)
{ {
WebSocketReceiver webSocketReceiver(url, enablePerMessageDeflate, delayMs); WebSocketReceiver webSocketReceiver(url, enablePerMessageDeflate, delayMs);
webSocketReceiver.start(); webSocketReceiver.start();
@ -261,11 +254,9 @@ namespace ix
webSocketReceiver.stop(); webSocketReceiver.stop();
} }
int ws_receive_main(const std::string& url, int ws_receive_main(const std::string& url, bool enablePerMessageDeflate, int delayMs)
bool enablePerMessageDeflate,
int delayMs)
{ {
wsReceive(url, enablePerMessageDeflate, delayMs); wsReceive(url, enablePerMessageDeflate, delayMs);
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,9 +4,9 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include "IXRedisClient.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include "IXRedisClient.h"
namespace ix namespace ix
{ {
@ -41,8 +41,7 @@ namespace ix
{ {
if (!redisClient.publish(channel, message, errMsg)) if (!redisClient.publish(channel, message, errMsg))
{ {
std::cerr << "Error publishing to channel " << channel std::cerr << "Error publishing to channel " << channel << "error: " << errMsg
<< "error: " << errMsg
<< std::endl; << std::endl;
return 1; return 1;
} }
@ -50,4 +49,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,12 +4,12 @@
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved. * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/ */
#include "IXRedisClient.h"
#include <atomic>
#include <chrono>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <chrono>
#include <thread> #include <thread>
#include <atomic>
#include "IXRedisClient.h"
namespace ix namespace ix
{ {
@ -41,9 +41,7 @@ namespace ix
std::atomic<int> msgPerSeconds(0); std::atomic<int> msgPerSeconds(0);
std::atomic<int> msgCount(0); std::atomic<int> msgCount(0);
auto callback = [&msgPerSeconds, &msgCount, verbose] auto callback = [&msgPerSeconds, &msgCount, verbose](const std::string& message) {
(const std::string& message)
{
if (verbose) if (verbose)
{ {
std::cout << "received: " << message << std::endl; std::cout << "received: " << message << std::endl;
@ -53,18 +51,15 @@ namespace ix
msgCount++; msgCount++;
}; };
auto responseCallback = [](const std::string& redisResponse) auto responseCallback = [](const std::string& redisResponse) {
{
std::cout << "Redis subscribe response: " << redisResponse << std::endl; std::cout << "Redis subscribe response: " << redisResponse << std::endl;
}; };
auto timer = [&msgPerSeconds, &msgCount] auto timer = [&msgPerSeconds, &msgCount] {
{
while (true) while (true)
{ {
std::cout << "#messages " << msgCount << " " std::cout << "#messages " << msgCount << " "
<< "msg/s " << msgPerSeconds << "msg/s " << msgPerSeconds << std::endl;
<< std::endl;
msgPerSeconds = 0; msgPerSeconds = 0;
auto duration = std::chrono::seconds(1); auto duration = std::chrono::seconds(1);
@ -83,4 +78,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix

View File

@ -4,19 +4,19 @@
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
*/ */
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <condition_variable>
#include <mutex>
#include <chrono> #include <chrono>
#include <ixwebsocket/IXWebSocket.h> #include <condition_variable>
#include <ixwebsocket/IXSocket.h> #include <fstream>
#include <ixcrypto/IXUuid.h> #include <iostream>
#include <ixcrypto/IXBase64.h> #include <ixcrypto/IXBase64.h>
#include <ixcrypto/IXHash.h> #include <ixcrypto/IXHash.h>
#include <ixcrypto/IXUuid.h>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXWebSocket.h>
#include <msgpack11/msgpack11.hpp> #include <msgpack11/msgpack11.hpp>
#include <mutex>
#include <sstream>
#include <vector>
using msgpack11::MsgPack; using msgpack11::MsgPack;
@ -25,8 +25,7 @@ namespace ix
class WebSocketSender class WebSocketSender
{ {
public: public:
WebSocketSender(const std::string& _url, WebSocketSender(const std::string& _url, bool enablePerMessageDeflate);
bool enablePerMessageDeflate);
void subscribe(const std::string& channel); void subscribe(const std::string& channel);
void start(); void start();
@ -49,10 +48,9 @@ namespace ix
void log(const std::string& msg); void log(const std::string& msg);
}; };
WebSocketSender::WebSocketSender(const std::string& url, WebSocketSender::WebSocketSender(const std::string& url, bool enablePerMessageDeflate)
bool enablePerMessageDeflate) : : _url(url)
_url(url), , _enablePerMessageDeflate(enablePerMessageDeflate)
_enablePerMessageDeflate(enablePerMessageDeflate)
{ {
; ;
} }
@ -111,9 +109,7 @@ namespace ix
std::stringstream ss; std::stringstream ss;
log(std::string("Connecting to url: ") + _url); log(std::string("Connecting to url: ") + _url);
_webSocket.setOnMessageCallback( _webSocket.setOnMessageCallback([this](const WebSocketMessagePtr& msg) {
[this](const WebSocketMessagePtr& msg)
{
std::stringstream ss; std::stringstream ss;
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
@ -177,10 +173,10 @@ namespace ix
class Bench class Bench
{ {
public: public:
Bench(const std::string& description) : Bench(const std::string& description)
_description(description), : _description(description)
_start(std::chrono::system_clock::now()), , _start(std::chrono::system_clock::now())
_reported(false) , _reported(false)
{ {
; ;
} }
@ -199,8 +195,7 @@ namespace ix
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start); auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start);
_ms = milliseconds.count(); _ms = milliseconds.count();
std::cout << _description << " completed in " std::cout << _description << " completed in " << _ms << "ms" << std::endl;
<< _ms << "ms" << std::endl;
_reported = true; _reported = true;
} }
@ -217,8 +212,7 @@ namespace ix
bool _reported; bool _reported;
}; };
void WebSocketSender::sendMessage(const std::string& filename, void WebSocketSender::sendMessage(const std::string& filename, bool throttle)
bool throttle)
{ {
std::vector<uint8_t> content; std::vector<uint8_t> content;
{ {
@ -239,9 +233,7 @@ namespace ix
MsgPack msg(pdu); MsgPack msg(pdu);
Bench bench("Sending file through websocket"); Bench bench("Sending file through websocket");
_webSocket.sendBinary(msg.dump(), _webSocket.sendBinary(msg.dump(), [throttle](int current, int total) -> bool {
[throttle](int current, int total) -> bool
{
std::cout << "ws_send: Step " << current << " out of " << total << std::endl; std::cout << "ws_send: Step " << current << " out of " << total << std::endl;
if (throttle) if (throttle)
@ -256,8 +248,7 @@ namespace ix
do do
{ {
size_t bufferedAmount = _webSocket.bufferedAmount(); size_t bufferedAmount = _webSocket.bufferedAmount();
std::cout << "ws_send: " << bufferedAmount std::cout << "ws_send: " << bufferedAmount << " bytes left to be sent" << std::endl;
<< " bytes left to be sent" << std::endl;
std::chrono::duration<double, std::milli> duration(10); std::chrono::duration<double, std::milli> duration(10);
std::this_thread::sleep_for(duration); std::this_thread::sleep_for(duration);
@ -289,8 +280,7 @@ namespace ix
webSocketSender.stop(); webSocketSender.stop();
} }
int ws_send_main(const std::string& url, int ws_send_main(const std::string& url, const std::string& path)
const std::string& path)
{ {
bool throttle = false; bool throttle = false;
bool enablePerMessageDeflate = false; bool enablePerMessageDeflate = false;
@ -298,4 +288,4 @@ namespace ix
wsSend(url, path, enablePerMessageDeflate, throttle); wsSend(url, path, enablePerMessageDeflate, throttle);
return 0; return 0;
} }
} } // namespace ix

View File

@ -5,10 +5,9 @@
*/ */
#include "IXSnakeServer.h" #include "IXSnakeServer.h"
#include <fstream>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <fstream>
namespace namespace
{ {
@ -34,7 +33,7 @@ namespace
auto vec = load(path); auto vec = load(path);
return std::string(vec.begin(), vec.end()); return std::string(vec.begin(), vec.end());
} }
} } // namespace
namespace ix namespace ix
{ {
@ -80,4 +79,4 @@ namespace ix
return 0; // should never reach this return 0; // should never reach this
} }
} } // namespace ix

View File

@ -5,8 +5,8 @@
*/ */
#include <iostream> #include <iostream>
#include <sstream>
#include <ixwebsocket/IXWebSocketServer.h> #include <ixwebsocket/IXWebSocketServer.h>
#include <sstream>
namespace ix namespace ix
{ {
@ -16,13 +16,10 @@ namespace ix
ix::WebSocketServer server(port, hostname); ix::WebSocketServer server(port, hostname);
server.setOnConnectionCallback( server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket,
[&server](std::shared_ptr<ix::WebSocket> webSocket, std::shared_ptr<ConnectionState> connectionState) {
std::shared_ptr<ConnectionState> connectionState) webSocket->setOnMessageCallback([webSocket, connectionState, &server](
{ const WebSocketMessagePtr& msg) {
webSocket->setOnMessageCallback(
[webSocket, connectionState, &server](const WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Open) if (msg->type == ix::WebSocketMessageType::Open)
{ {
std::cerr << "New connection" << std::endl; std::cerr << "New connection" << std::endl;
@ -37,8 +34,8 @@ namespace ix
else if (msg->type == ix::WebSocketMessageType::Close) else if (msg->type == ix::WebSocketMessageType::Close)
{ {
std::cerr << "Closed connection" std::cerr << "Closed connection"
<< " code " << msg->closeInfo.code << " code " << msg->closeInfo.code << " reason "
<< " reason " << msg->closeInfo.reason << std::endl; << msg->closeInfo.reason << std::endl;
} }
else if (msg->type == ix::WebSocketMessageType::Error) else if (msg->type == ix::WebSocketMessageType::Error)
{ {
@ -51,8 +48,7 @@ namespace ix
} }
else if (msg->type == ix::WebSocketMessageType::Fragment) else if (msg->type == ix::WebSocketMessageType::Fragment)
{ {
std::cerr << "Received message fragment " std::cerr << "Received message fragment " << std::endl;
<< std::endl;
} }
else if (msg->type == ix::WebSocketMessageType::Message) else if (msg->type == ix::WebSocketMessageType::Message)
{ {
@ -61,12 +57,9 @@ namespace ix
{ {
if (client != webSocket) if (client != webSocket)
{ {
client->send(msg->str, client->send(msg->str, msg->binary, [](int current, int total) -> bool {
msg->binary, std::cerr << "ws_transfer: Step " << current << " out of " << total
[](int current, int total) -> bool << std::endl;
{
std::cerr << "ws_transfer: Step " << current
<< " out of " << total << std::endl;
return true; return true;
}); });
@ -82,10 +75,8 @@ namespace ix
} }
} }
} }
} });
); });
}
);
auto res = server.listen(); auto res = server.listen();
if (!res.first) if (!res.first)
@ -99,4 +90,4 @@ namespace ix
return 0; return 0;
} }
} } // namespace ix