add simple test + set default http handler
This commit is contained in:
parent
22b8fc831c
commit
cfc1b8f1c2
@ -97,7 +97,6 @@ namespace ix
|
|||||||
return std::make_tuple(true, "", httpRequest);
|
return std::make_tuple(true, "", httpRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Write a mime type
|
|
||||||
bool Http::sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket)
|
bool Http::sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket)
|
||||||
{
|
{
|
||||||
// Write the response to the socket
|
// Write the response to the socket
|
||||||
@ -127,6 +126,8 @@ namespace ix
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return socket->writeBytes(response->payload, nullptr);
|
return response->payload.empty()
|
||||||
|
? true
|
||||||
|
: socket->writeBytes(response->payload, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,22 +11,45 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <future>
|
#include <fstream>
|
||||||
#include <string.h>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::pair<bool, std::vector<uint8_t>> load(const std::string& path)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> memblock;
|
||||||
|
|
||||||
|
std::ifstream file(path);
|
||||||
|
if (!file.is_open()) return std::make_pair(false, memblock);
|
||||||
|
|
||||||
|
file.seekg(0, file.end);
|
||||||
|
std::streamoff size = file.tellg();
|
||||||
|
file.seekg(0, file.beg);
|
||||||
|
|
||||||
|
memblock.resize((size_t) size);
|
||||||
|
file.read((char*)&memblock.front(), static_cast<std::streamsize>(size));
|
||||||
|
|
||||||
|
return std::make_pair(true, memblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, std::string> readAsString(const std::string& path)
|
||||||
|
{
|
||||||
|
auto res = load(path);
|
||||||
|
auto vec = res.second;
|
||||||
|
return std::make_pair(res.first, std::string(vec.begin(), vec.end()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
const int HttpServer::kDefaultHandShakeTimeoutSecs(3); // 3 seconds
|
|
||||||
|
|
||||||
HttpServer::HttpServer(int port,
|
HttpServer::HttpServer(int port,
|
||||||
const std::string& host,
|
const std::string& host,
|
||||||
int backlog,
|
int backlog,
|
||||||
size_t maxConnections,
|
size_t maxConnections) : SocketServer(port, host, backlog, maxConnections),
|
||||||
int handshakeTimeoutSecs) : SocketServer(port, host, backlog, maxConnections),
|
|
||||||
_handshakeTimeoutSecs(handshakeTimeoutSecs),
|
|
||||||
_connectedClientsCount(0)
|
_connectedClientsCount(0)
|
||||||
{
|
{
|
||||||
|
setDefaultConnectionCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpServer::~HttpServer()
|
HttpServer::~HttpServer()
|
||||||
@ -56,16 +79,21 @@ namespace ix
|
|||||||
|
|
||||||
std::string errorMsg;
|
std::string errorMsg;
|
||||||
auto socket = createSocket(fd, errorMsg);
|
auto socket = createSocket(fd, errorMsg);
|
||||||
|
|
||||||
// Set the socket to non blocking mode + other tweaks
|
// Set the socket to non blocking mode + other tweaks
|
||||||
SocketConnect::configure(fd);
|
SocketConnect::configure(fd);
|
||||||
|
|
||||||
auto ret = Http::parseRequest(socket);
|
auto ret = Http::parseRequest(socket);
|
||||||
// FIXME: handle errors in parseRequest
|
// FIXME: handle errors in parseRequest
|
||||||
|
|
||||||
auto response = _onConnectionCallback(std::get<2>(ret), connectionState);
|
if (std::get<0>(ret))
|
||||||
Http::sendResponse(response, socket);
|
{
|
||||||
|
auto response = _onConnectionCallback(std::get<2>(ret), connectionState);
|
||||||
logInfo("HttpServer::handleConnection() done");
|
if (!Http::sendResponse(response, socket))
|
||||||
|
{
|
||||||
|
logError("Cannot send response");
|
||||||
|
}
|
||||||
|
}
|
||||||
connectionState->setTerminated();
|
connectionState->setTerminated();
|
||||||
|
|
||||||
_connectedClientsCount--;
|
_connectedClientsCount--;
|
||||||
@ -75,4 +103,49 @@ namespace ix
|
|||||||
{
|
{
|
||||||
return _connectedClientsCount;
|
return _connectedClientsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpServer::setDefaultConnectionCallback()
|
||||||
|
{
|
||||||
|
setOnConnectionCallback(
|
||||||
|
[this](HttpRequestPtr request,
|
||||||
|
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr
|
||||||
|
{
|
||||||
|
std::string path("." + request->uri);
|
||||||
|
auto res = readAsString(path);
|
||||||
|
bool found = res.first;
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
return std::make_shared<HttpResponse>(404, "Not Found",
|
||||||
|
HttpErrorCode::Ok,
|
||||||
|
WebSocketHttpHeaders(),
|
||||||
|
std::string());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string content = res.second;
|
||||||
|
|
||||||
|
// Log request
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << request->method
|
||||||
|
<< " "
|
||||||
|
<< request->uri
|
||||||
|
<< " "
|
||||||
|
<< content.size();
|
||||||
|
logInfo(ss.str());
|
||||||
|
|
||||||
|
WebSocketHttpHeaders headers;
|
||||||
|
headers["Content-Type"] = "application/octet-stream";
|
||||||
|
headers["Accept-Ranges"] = "none";
|
||||||
|
|
||||||
|
for (auto&& it : request->headers)
|
||||||
|
{
|
||||||
|
headers[it.first] = it.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_shared<HttpResponse>(200, "OK",
|
||||||
|
HttpErrorCode::Ok,
|
||||||
|
WebSocketHttpHeaders(),
|
||||||
|
content);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,17 +19,16 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
using OnConnectionCallback =
|
|
||||||
std::function<HttpResponsePtr(HttpRequestPtr, std::shared_ptr<ConnectionState>)>;
|
|
||||||
|
|
||||||
class HttpServer final : public SocketServer
|
class HttpServer final : public SocketServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using OnConnectionCallback =
|
||||||
|
std::function<HttpResponsePtr(HttpRequestPtr, std::shared_ptr<ConnectionState>)>;
|
||||||
|
|
||||||
HttpServer(int port = SocketServer::kDefaultPort,
|
HttpServer(int port = SocketServer::kDefaultPort,
|
||||||
const std::string& host = SocketServer::kDefaultHost,
|
const std::string& host = SocketServer::kDefaultHost,
|
||||||
int backlog = SocketServer::kDefaultTcpBacklog,
|
int backlog = SocketServer::kDefaultTcpBacklog,
|
||||||
size_t maxConnections = SocketServer::kDefaultMaxConnections,
|
size_t maxConnections = SocketServer::kDefaultMaxConnections);
|
||||||
int handshakeTimeoutSecs = HttpServer::kDefaultHandShakeTimeoutSecs);
|
|
||||||
virtual ~HttpServer();
|
virtual ~HttpServer();
|
||||||
virtual void stop() final;
|
virtual void stop() final;
|
||||||
|
|
||||||
@ -37,15 +36,15 @@ namespace ix
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Member variables
|
// Member variables
|
||||||
int _handshakeTimeoutSecs;
|
|
||||||
OnConnectionCallback _onConnectionCallback;
|
OnConnectionCallback _onConnectionCallback;
|
||||||
const static int kDefaultHandShakeTimeoutSecs;
|
|
||||||
std::atomic<int> _connectedClientsCount;
|
std::atomic<int> _connectedClientsCount;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
virtual void handleConnection(int fd,
|
virtual void handleConnection(int fd,
|
||||||
std::shared_ptr<ConnectionState> connectionState) final;
|
std::shared_ptr<ConnectionState> connectionState) final;
|
||||||
virtual size_t getConnectedClientsCount() final;
|
virtual size_t getConnectedClientsCount() final;
|
||||||
|
|
||||||
|
void setDefaultConnectionCallback();
|
||||||
};
|
};
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
|
||||||
|
@ -232,19 +232,28 @@ namespace ix
|
|||||||
bool Socket::writeBytes(const std::string& str,
|
bool Socket::writeBytes(const std::string& str,
|
||||||
const CancellationRequest& isCancellationRequested)
|
const CancellationRequest& isCancellationRequested)
|
||||||
{
|
{
|
||||||
|
char* buffer = const_cast<char*>(str.c_str());
|
||||||
|
int len = (int) str.size();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (isCancellationRequested && isCancellationRequested()) return false;
|
if (isCancellationRequested && isCancellationRequested()) return false;
|
||||||
|
|
||||||
char* buffer = const_cast<char*>(str.c_str());
|
|
||||||
int len = (int) str.size();
|
|
||||||
|
|
||||||
ssize_t ret = send(buffer, len);
|
ssize_t ret = send(buffer, len);
|
||||||
|
|
||||||
// We wrote some bytes, as needed, all good.
|
// We wrote some bytes, as needed, all good.
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
return ret == len;
|
if (ret == len)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer += ret;
|
||||||
|
len -= ret;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// There is possibly something to be writen, try again
|
// There is possibly something to be writen, try again
|
||||||
else if (ret < 0 && Socket::isWaitNeeded())
|
else if (ret < 0 && Socket::isWaitNeeded())
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <future>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
using OnConnectionCallback =
|
|
||||||
std::function<void(std::shared_ptr<WebSocket>, std::shared_ptr<ConnectionState>)>;
|
|
||||||
|
|
||||||
class WebSocketServer final : public SocketServer
|
class WebSocketServer final : public SocketServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using OnConnectionCallback =
|
||||||
|
std::function<void(std::shared_ptr<WebSocket>, std::shared_ptr<ConnectionState>)>;
|
||||||
|
|
||||||
WebSocketServer(int port = SocketServer::kDefaultPort,
|
WebSocketServer(int port = SocketServer::kDefaultPort,
|
||||||
const std::string& host = SocketServer::kDefaultHost,
|
const std::string& host = SocketServer::kDefaultHost,
|
||||||
int backlog = SocketServer::kDefaultTcpBacklog,
|
int backlog = SocketServer::kDefaultTcpBacklog,
|
||||||
|
@ -28,6 +28,7 @@ include_directories(
|
|||||||
set (SOURCES
|
set (SOURCES
|
||||||
test_runner.cpp
|
test_runner.cpp
|
||||||
IXTest.cpp
|
IXTest.cpp
|
||||||
|
IXGetFreePort.cpp
|
||||||
../third_party/msgpack11/msgpack11.cpp
|
../third_party/msgpack11/msgpack11.cpp
|
||||||
../ws/ixcore/utils/IXCoreLogger.cpp
|
../ws/ixcore/utils/IXCoreLogger.cpp
|
||||||
|
|
||||||
@ -38,6 +39,8 @@ set (SOURCES
|
|||||||
IXUrlParserTest.cpp
|
IXUrlParserTest.cpp
|
||||||
IXWebSocketServerTest.cpp
|
IXWebSocketServerTest.cpp
|
||||||
IXHttpClientTest.cpp
|
IXHttpClientTest.cpp
|
||||||
|
IXHttpServerTest.cpp
|
||||||
|
IXUnityBuildsTest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Some unittest don't work on windows yet
|
# Some unittest don't work on windows yet
|
||||||
|
93
test/IXGetFreePort.cpp
Normal file
93
test/IXGetFreePort.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* IXGetFreePort.cpp
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IXGetFreePort.h"
|
||||||
|
#include <ixwebsocket/IXNetSystem.h>
|
||||||
|
#include <ixwebsocket/IXSocket.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
int getAnyFreePortRandom()
|
||||||
|
{
|
||||||
|
std::random_device rd;
|
||||||
|
std::uniform_int_distribution<int> dist(1024 + 1, 65535);
|
||||||
|
|
||||||
|
return dist(rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getAnyFreePort()
|
||||||
|
{
|
||||||
|
int defaultPort = 8090;
|
||||||
|
int sockfd;
|
||||||
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
|
{
|
||||||
|
return getAnyFreePortRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
int enable = 1;
|
||||||
|
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(char*) &enable, sizeof(enable)) < 0)
|
||||||
|
{
|
||||||
|
return getAnyFreePortRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to port 0. This is the standard way to get a free port.
|
||||||
|
struct sockaddr_in server; // server address information
|
||||||
|
server.sin_family = AF_INET;
|
||||||
|
server.sin_port = htons(0);
|
||||||
|
server.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||||
|
|
||||||
|
if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
|
||||||
|
{
|
||||||
|
Socket::closeSocket(sockfd);
|
||||||
|
return getAnyFreePortRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in sa; // server address information
|
||||||
|
socklen_t len = sizeof(sa);
|
||||||
|
if (getsockname(sockfd, (struct sockaddr *) &sa, &len) < 0)
|
||||||
|
{
|
||||||
|
Socket::closeSocket(sockfd);
|
||||||
|
return getAnyFreePortRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = ntohs(sa.sin_port);
|
||||||
|
Socket::closeSocket(sockfd);
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getFreePort()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
#if defined(__has_feature)
|
||||||
|
# if __has_feature(address_sanitizer)
|
||||||
|
int port = getAnyFreePortRandom();
|
||||||
|
# else
|
||||||
|
int port = getAnyFreePort();
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
int port = getAnyFreePort();
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
// Only port above 1024 can be used by non root users, but for some
|
||||||
|
// reason I got port 7 returned with macOS when binding on port 0...
|
||||||
|
//
|
||||||
|
if (port > 1024)
|
||||||
|
{
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} // namespace ix
|
||||||
|
|
||||||
|
|
12
test/IXGetFreePort.h
Normal file
12
test/IXGetFreePort.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* IXGetFreePort.h
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
int getFreePort();
|
||||||
|
} // namespace ix
|
70
test/IXHttpServerTest.cpp
Normal file
70
test/IXHttpServerTest.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* IXSocketTest.cpp
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <ixwebsocket/IXHttpClient.h>
|
||||||
|
#include <ixwebsocket/IXHttpServer.h>
|
||||||
|
#include "IXGetFreePort.h"
|
||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
using namespace ix;
|
||||||
|
|
||||||
|
TEST_CASE("http server", "[httpd]")
|
||||||
|
{
|
||||||
|
SECTION("Connect to a local HTTP server")
|
||||||
|
{
|
||||||
|
int port = getFreePort();
|
||||||
|
ix::HttpServer server(port, "127.0.0.1");
|
||||||
|
|
||||||
|
auto res = server.listen();
|
||||||
|
REQUIRE(res.first);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
HttpClient httpClient;
|
||||||
|
WebSocketHttpHeaders headers;
|
||||||
|
|
||||||
|
std::string url("http://127.0.0.1:");
|
||||||
|
url += std::to_string(port);
|
||||||
|
url += "/data/foo.txt";
|
||||||
|
auto args = httpClient.createRequest(url);
|
||||||
|
|
||||||
|
args->extraHeaders = headers;
|
||||||
|
args->connectTimeout = 60;
|
||||||
|
args->transferTimeout = 60;
|
||||||
|
args->followRedirects = true;
|
||||||
|
args->maxRedirects = 10;
|
||||||
|
args->verbose = true;
|
||||||
|
args->compress = true;
|
||||||
|
args->logger = [](const std::string& msg)
|
||||||
|
{
|
||||||
|
std::cout << msg;
|
||||||
|
};
|
||||||
|
args->onProgressCallback = [](int current, int total) -> bool
|
||||||
|
{
|
||||||
|
std::cerr << "\r" << "Downloaded "
|
||||||
|
<< current << " bytes out of " << total;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto response = httpClient.get(url, args);
|
||||||
|
|
||||||
|
for (auto it : response->headers)
|
||||||
|
{
|
||||||
|
std::cerr << it.first << ": " << it.second << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "Upload size: " << response->uploadSize << std::endl;
|
||||||
|
std::cerr << "Download size: " << response->downloadSize << std::endl;
|
||||||
|
std::cerr << "Status: " << response->statusCode << std::endl;
|
||||||
|
std::cerr << "Error message: " << response->errorMsg << std::endl;
|
||||||
|
|
||||||
|
REQUIRE(response->errorCode == HttpErrorCode::Ok);
|
||||||
|
REQUIRE(response->statusCode == 200);
|
||||||
|
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
}
|
@ -72,88 +72,6 @@ namespace ix
|
|||||||
Logger() << msg;
|
Logger() << msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getAnyFreePortRandom()
|
|
||||||
{
|
|
||||||
std::random_device rd;
|
|
||||||
std::uniform_int_distribution<int> dist(1024 + 1, 65535);
|
|
||||||
|
|
||||||
return dist(rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAnyFreePort()
|
|
||||||
{
|
|
||||||
int defaultPort = 8090;
|
|
||||||
int sockfd;
|
|
||||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
|
||||||
{
|
|
||||||
log("Cannot compute a free port. socket error.");
|
|
||||||
return getAnyFreePortRandom();
|
|
||||||
}
|
|
||||||
|
|
||||||
int enable = 1;
|
|
||||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
|
||||||
(char*) &enable, sizeof(enable)) < 0)
|
|
||||||
{
|
|
||||||
log("Cannot compute a free port. setsockopt error.");
|
|
||||||
return getAnyFreePortRandom();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind to port 0. This is the standard way to get a free port.
|
|
||||||
struct sockaddr_in server; // server address information
|
|
||||||
server.sin_family = AF_INET;
|
|
||||||
server.sin_port = htons(0);
|
|
||||||
server.sin_addr.s_addr = inet_addr("127.0.0.1");
|
|
||||||
|
|
||||||
if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
|
|
||||||
{
|
|
||||||
log("Cannot compute a free port. bind error.");
|
|
||||||
|
|
||||||
Socket::closeSocket(sockfd);
|
|
||||||
return getAnyFreePortRandom();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in sa; // server address information
|
|
||||||
socklen_t len = sizeof(sa);
|
|
||||||
if (getsockname(sockfd, (struct sockaddr *) &sa, &len) < 0)
|
|
||||||
{
|
|
||||||
log("Cannot compute a free port. getsockname error.");
|
|
||||||
|
|
||||||
Socket::closeSocket(sockfd);
|
|
||||||
return getAnyFreePortRandom();
|
|
||||||
}
|
|
||||||
|
|
||||||
int port = ntohs(sa.sin_port);
|
|
||||||
Socket::closeSocket(sockfd);
|
|
||||||
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getFreePort()
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
#if defined(__has_feature)
|
|
||||||
# if __has_feature(address_sanitizer)
|
|
||||||
int port = getAnyFreePortRandom();
|
|
||||||
# else
|
|
||||||
int port = getAnyFreePort();
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
int port = getAnyFreePort();
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
// Only port above 1024 can be used by non root users, but for some
|
|
||||||
// reason I got port 7 returned with macOS when binding on port 0...
|
|
||||||
//
|
|
||||||
if (port > 1024)
|
|
||||||
{
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hexDump(const std::string& prefix,
|
void hexDump(const std::string& prefix,
|
||||||
const std::string& s)
|
const std::string& s)
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <ixwebsocket/IXWebSocketServer.h>
|
#include <ixwebsocket/IXWebSocketServer.h>
|
||||||
|
#include "IXGetFreePort.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -46,7 +47,5 @@ namespace ix
|
|||||||
|
|
||||||
void log(const std::string& msg);
|
void log(const std::string& msg);
|
||||||
|
|
||||||
int getFreePort();
|
|
||||||
|
|
||||||
bool startWebSocketEchoServer(ix::WebSocketServer& server);
|
bool startWebSocketEchoServer(ix::WebSocketServer& server);
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
52
test/IXUnityBuildsTest.cpp
Normal file
52
test/IXUnityBuildsTest.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* IXUnityBuildsTest.cpp
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ixwebsocket/IXCancellationRequest.h>
|
||||||
|
#include <ixwebsocket/IXConnectionState.h>
|
||||||
|
#include <ixwebsocket/IXDNSLookup.h>
|
||||||
|
#include <ixwebsocket/IXHttp.h>
|
||||||
|
#include <ixwebsocket/IXHttpClient.h>
|
||||||
|
#include <ixwebsocket/IXHttpServer.h>
|
||||||
|
#include <ixwebsocket/IXNetSystem.h>
|
||||||
|
#include <ixwebsocket/IXProgressCallback.h>
|
||||||
|
#include <ixwebsocket/IXSelectInterrupt.h>
|
||||||
|
#include <ixwebsocket/IXSelectInterruptFactory.h>
|
||||||
|
#include <ixwebsocket/IXSetThreadName.h>
|
||||||
|
#include <ixwebsocket/IXSocket.h>
|
||||||
|
#include <ixwebsocket/IXSocketConnect.h>
|
||||||
|
#include <ixwebsocket/IXSocketFactory.h>
|
||||||
|
#include <ixwebsocket/IXSocketServer.h>
|
||||||
|
#include <ixwebsocket/IXUrlParser.h>
|
||||||
|
#include <ixwebsocket/IXWebSocket.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketCloseConstants.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketCloseInfo.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketErrorInfo.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketHandshake.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketMessage.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketMessageQueue.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketMessageType.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketOpenInfo.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketPerMessageDeflate.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketPerMessageDeflateCodec.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketPerMessageDeflateOptions.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketSendInfo.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketServer.h>
|
||||||
|
#include <ixwebsocket/IXWebSocketTransport.h>
|
||||||
|
#include <ixwebsocket/LUrlParser.h>
|
||||||
|
#include <ixwebsocket/libwshandshake.hpp>
|
||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
using namespace ix;
|
||||||
|
|
||||||
|
TEST_CASE("unity build", "[unity_build]")
|
||||||
|
{
|
||||||
|
SECTION("dummy test")
|
||||||
|
{
|
||||||
|
REQUIRE(true);
|
||||||
|
}
|
||||||
|
}
|
1
test/data/foo.txt
Normal file
1
test/data/foo.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hello world
|
Loading…
x
Reference in New Issue
Block a user