Compare commits

..

18 Commits

Author SHA1 Message Date
c192c9ec96 (snake) add an option to disable answering pongs as response to pings, to test cobra client behavior with hanged connections 2020-01-31 16:55:54 -08:00
86f6fca703 (IXCobraConnection) set a ping timeout of 90 seconds. If no pong messages are received as responses to ping for a while, give up and close the connection 2020-01-31 16:25:45 -08:00
bbe744a323 (cobra to sentry) remove noisy logging 2020-01-31 16:07:36 -08:00
3d401fbc8d (ixcobra) check if we are authenticated in publishNext before trying to publish a message 2020-01-30 20:52:11 -08:00
a0c9d31389 version 8.0.2: add severity level for log sentry events (#152)
* script to update version

* version 8.0.2: add severity level for log sentry events
2020-01-28 14:04:18 -08:00
48ea80bb8f bump version and update changelog 2020-01-28 10:50:03 -08:00
44a813caae quit checkConnection after sleeping if requested to stop (iterate on #151) 2020-01-28 10:46:04 -08:00
78af792f23 wait with a condition variable instead of a this_thread::sleep_for so that waiting can be cancelled when we stop/shutdown the data thread (see #151) 2020-01-28 10:04:32 -08:00
1ee8e31483 bump version 2020-01-27 17:41:27 -08:00
e927dcca3a Fix #148 2020-01-27 17:29:44 -08:00
86c2ab450e bind returns zero on success (#149) 2020-01-27 17:15:44 -08:00
f3d562ff02 add -6 option to ws echo_server / cf #148 2020-01-26 16:44:44 -08:00
3c27228585 (SocketServer) add ability to bind on an ipv6 address 2020-01-26 16:21:56 -08:00
9d7807b25c (ws) add a dnslookup sub-command, to get the ip address of a remote host 2020-01-26 16:21:56 -08:00
6256264d78 Remove 'handleConnect() done' info message (#147) 2020-01-26 10:03:17 -08:00
04c9985030 Doc update for Conan (#146)
* Doc update for Conan

* Migration notice
2020-01-17 07:15:41 -08:00
99fe6ea493 fix #144 - get rid of stubbed windows ssl schannel backend 2020-01-14 13:39:48 -08:00
acab19fe9f install gdb in the alpine dockerfile 2020-01-14 13:37:28 -08:00
31 changed files with 288 additions and 194 deletions

View File

@ -129,9 +129,6 @@ if (USE_TLS)
elseif (APPLE AND NOT USE_OPEN_SSL)
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketAppleSSL.h)
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketAppleSSL.cpp)
elseif (WIN32 AND NOT USE_OPEN_SSL)
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketSChannel.h)
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketSChannel.cpp)
else()
set(USE_OPEN_SSL ON)
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketOpenSSL.h)

View File

@ -21,6 +21,7 @@ FROM alpine:3.11 as runtime
RUN apk add --no-cache libstdc++
RUN apk add --no-cache strace
RUN apk add --no-cache gdb
RUN addgroup -S app && adduser -S -G app app
COPY --chown=app:app --from=build /usr/local/bin/ws /usr/local/bin/ws
@ -36,4 +37,3 @@ WORKDIR /home/app
ENTRYPOINT ["ws"]
EXPOSE 8008
C

View File

@ -1,6 +1,42 @@
# Changelog
All changes to this project will be documented in this file.
## [8.0.6] - 2020-01-31
(snake) add an option to disable answering pongs as response to pings, to test cobra client behavior with hanged connections
## [8.0.5] - 2020-01-31
(IXCobraConnection) set a ping timeout of 90 seconds. If no pong messages are received as responses to ping for a while, give up and close the connection
## [8.0.4] - 2020-01-31
(cobra to sentry) remove noisy logging
## [8.0.3] - 2020-01-30
(ixcobra) check if we are authenticated in publishNext before trying to publish a message
## [8.0.2] - 2020-01-28
Extract severity level when emitting messages to sentry
## [8.0.1] - 2020-01-28
Fix bug #151 - If a socket connection is interrupted, calling stop() on the IXWebSocket object blocks until the next retry
## [8.0.0] - 2020-01-26
(SocketServer) add ability to bind on an ipv6 address
## [7.9.6] - 2020-01-22
(ws) add a dnslookup sub-command, to get the ip address of a remote host
## [7.9.5] - 2020-01-14
(windows) fix #144, get rid of stubbed/un-implemented windows schannel ssl backend
## [7.9.4] - 2020-01-12
(openssl + mbedssl) fix #140, can send large files with ws send over ssl / still broken with apple ssl

View File

@ -33,11 +33,16 @@ vcpkg install ixwebsocket
### Conan
Support for building with conan was contributed by Olivia Zoe (thanks!). The package name to reference is `IXWebSocket/5.0.0@LunarWatcher/stable`, and a list of the uploaded versions is available on [Bintray](https://bintray.com/oliviazoe0/conan-packages/IXWebSocket%3ALunarWatcher). The package is in the process to be published to the official conan package repo, but in the meantime, it can be accessed by adding a new remote
[ ![Download](https://api.bintray.com/packages/conan/conan-center/ixwebsocket%3A_/images/download.svg) ](https://bintray.com/conan/conan-center/ixwebsocket%3A_/_latestVersion)
```
conan remote add remote_name_here https://api.bintray.com/conan/oliviazoe0/conan-packages
```
Conan is currently supported through a recipe in [Conan Center](https://github.com/conan-io/conan-center-index/tree/master/recipes/ixwebsocket) ([Bintray entry](https://bintray.com/conan/conan-center/ixwebsocket%3A_)).
Package reference
* Conan 1.21.0 and up: `ixwebsocket/7.9.2`
* Earlier versions: `ixwebsocket/7.9.2@_/_`
Note that the version listed here might not be the latest one. See Bintray or the recipe itself for the latest version. If you're migrating from the previous, custom Bintray remote, note that the package reference _has_ to be lower-case.
### Docker

View File

@ -265,7 +265,15 @@ namespace ix
_webSocket->setUrl(url);
_webSocket->setPerMessageDeflateOptions(webSocketPerMessageDeflateOptions);
_webSocket->setTLSOptions(socketTLSOptions);
// Send a websocket ping every N seconds (N = 30) now
// This should keep the connection open and prevent some load balancers such as
// the Amazon one from shutting it down
_webSocket->setPingInterval(kPingIntervalSecs);
// If we don't receive a pong back, declare loss after 3 * N seconds
// (will be 90s now), and close and restart the connection
_webSocket->setPingTimeout(3 * kPingIntervalSecs);
}
//
@ -506,7 +514,7 @@ namespace ix
if (_messageQueue.empty()) return true;
auto&& msg = _messageQueue.back();
if (!publishMessage(msg))
if (!_authenticated || !publishMessage(msg))
{
return false;
}

View File

@ -166,6 +166,17 @@ namespace ix
tags.append(tag);
}
}
if (msg["data"]["info"].isMember("level_str"))
{
// https://docs.sentry.io/enriching-error-data/context/?platform=python#setting-the-level
std::string level = msg["data"]["info"]["level_str"].asString();
if (level == "critical")
{
level = "fatal";
}
payload["level"] = level;
}
}
else
{

View File

@ -32,6 +32,7 @@ namespace snake
// Misc
bool verbose;
bool disablePong;
};
bool isAppKeyValid(const AppConfig& appConfig, std::string appkey);

View File

@ -17,8 +17,8 @@
namespace ix
{
RedisServer::RedisServer(int port, const std::string& host, int backlog, size_t maxConnections)
: SocketServer(port, host, backlog, maxConnections)
RedisServer::RedisServer(int port, const std::string& host, int backlog, size_t maxConnections, int addressFamily)
: SocketServer(port, host, backlog, maxConnections, addressFamily)
, _connectedClientsCount(0)
, _stopHandlingConnections(false)
{

View File

@ -25,7 +25,8 @@ namespace ix
RedisServer(int port = SocketServer::kDefaultPort,
const std::string& host = SocketServer::kDefaultHost,
int backlog = SocketServer::kDefaultTcpBacklog,
size_t maxConnections = SocketServer::kDefaultMaxConnections);
size_t maxConnections = SocketServer::kDefaultMaxConnections,
int addressFamily = SocketServer::kDefaultAddressFamily);
virtual ~RedisServer();
virtual void stop() final;

View File

@ -21,6 +21,15 @@ namespace snake
, _server(appConfig.port, appConfig.hostname)
{
_server.setTLSOptions(appConfig.socketTLSOptions);
if (appConfig.disablePong)
{
_server.disablePong();
}
std::stringstream ss;
ss << "Listening on " << appConfig.hostname << ":" << appConfig.port;
ix::IXCoreLogger::Log(ss.str().c_str());
}
//

View File

@ -42,8 +42,8 @@ namespace
namespace ix
{
HttpServer::HttpServer(int port, const std::string& host, int backlog, size_t maxConnections)
: SocketServer(port, host, backlog, maxConnections)
HttpServer::HttpServer(int port, const std::string& host, int backlog, size_t maxConnections, int addressFamily)
: SocketServer(port, host, backlog, maxConnections, addressFamily)
, _connectedClientsCount(0)
{
setDefaultConnectionCallback();

View File

@ -28,7 +28,8 @@ namespace ix
HttpServer(int port = SocketServer::kDefaultPort,
const std::string& host = SocketServer::kDefaultHost,
int backlog = SocketServer::kDefaultTcpBacklog,
size_t maxConnections = SocketServer::kDefaultMaxConnections);
size_t maxConnections = SocketServer::kDefaultMaxConnections,
int addressFamily = SocketServer::kDefaultAddressFamily);
virtual ~HttpServer();
virtual void stop() final;

View File

@ -14,8 +14,6 @@
#include "IXSocketOpenSSL.h"
#elif __APPLE__
#include "IXSocketAppleSSL.h"
#elif defined(_WIN32)
#include "IXSocketSChannel.h"
#endif
#else
@ -46,8 +44,6 @@ namespace ix
socket = std::make_shared<SocketMbedTLS>(tlsOptions, fd);
#elif defined(IXWEBSOCKET_USE_OPEN_SSL)
socket = std::make_shared<SocketOpenSSL>(tlsOptions, fd);
#elif defined(_WIN32)
socket = std::make_shared<SocketSChannel>(tlsOptions, fd);
#elif defined(__APPLE__)
socket = std::make_shared<SocketAppleSSL>(tlsOptions, fd);
#endif

View File

@ -1,103 +0,0 @@
/*
* IXSocketSChannel.cpp
* Author: Benjamin Sergeant
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
*
* See https://docs.microsoft.com/en-us/windows/desktop/WinSock/using-secure-socket-extensions
*
* https://github.com/pauldotknopf/WindowsSDK7-Samples/blob/master/netds/winsock/securesocket/stcpclient/tcpclient.c
*
* This is the right example to look at:
* https://www.codeproject.com/Articles/1000189/A-Working-TCP-Client-and-Server-With-SSL
*
* Similar code is available from this git repo
* https://github.com/david-maw/StreamSSL
*/
#include "IXSocketSChannel.h"
#ifdef _WIN32
#include <WS2tcpip.h>
#include <WinSock2.h>
#include <basetsd.h>
#include <io.h>
#include <schannel.h>
#include <ws2def.h>
#define WIN32_LEAN_AND_MEAN
#ifndef UNICODE
#define UNICODE
#endif
#include <mstcpip.h>
#include <ntdsapi.h>
#include <rpc.h>
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#define RECV_DATA_BUF_SIZE 256
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
// link with fwpuclnt.lib for Winsock secure socket extensions
#pragma comment(lib, "fwpuclnt.lib")
// link with ntdsapi.lib for DsMakeSpn function
#pragma comment(lib, "ntdsapi.lib")
// The following function assumes that Winsock
// has already been initialized
#else
#error("This file should only be built on Windows")
#endif
namespace ix
{
SocketSChannel::SocketSChannel()
{
;
}
SocketSChannel::~SocketSChannel()
{
}
bool SocketSChannel::connect(const std::string& host, int port, std::string& errMsg)
{
return Socket::connect(host, port, errMsg, nullptr);
}
void SocketSChannel::secureSocket()
{
// there will be a lot to do here ...
}
void SocketSChannel::close()
{
Socket::close();
}
ssize_t SocketSChannel::send(char* buf, size_t nbyte)
{
return Socket::send(buf, nbyte);
}
ssize_t SocketSChannel::send(const std::string& buffer)
{
return Socket::send(buffer);
}
ssize_t SocketSChannel::recv(void* buf, size_t nbyte)
{
return Socket::recv(buf, nbyte);
}
} // namespace ix

View File

@ -1,32 +0,0 @@
/*
* IXSocketSChannel.h
* Author: Benjamin Sergeant
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
*/
#pragma once
#include "IXSocket.h"
namespace ix
{
class SocketSChannel final : public Socket
{
public:
SocketSChannel();
~SocketSChannel();
virtual bool connect(const std::string& host, int port, std::string& errMsg) final;
virtual void close() final;
// The important override
virtual void secureSocket() final;
virtual ssize_t send(char* buffer, size_t length) final;
virtual ssize_t send(const std::string& buffer) final;
virtual ssize_t recv(void* buffer, size_t length) final;
private:
};
} // namespace ix

View File

@ -21,15 +21,18 @@ namespace ix
const std::string SocketServer::kDefaultHost("127.0.0.1");
const int SocketServer::kDefaultTcpBacklog(5);
const size_t SocketServer::kDefaultMaxConnections(32);
const int SocketServer::kDefaultAddressFamily(AF_INET);
SocketServer::SocketServer(int port,
const std::string& host,
int backlog,
size_t maxConnections)
size_t maxConnections,
int addressFamily)
: _port(port)
, _host(host)
, _backlog(backlog)
, _maxConnections(maxConnections)
, _addressFamily(addressFamily)
, _serverFd(-1)
, _stop(false)
, _stopGc(false)
@ -56,10 +59,15 @@ namespace ix
std::pair<bool, std::string> SocketServer::listen()
{
struct sockaddr_in server; // server address information
if (_addressFamily != AF_INET && _addressFamily != AF_INET6)
{
std::string errMsg("SocketServer::listen() AF_INET and AF_INET6 are currently "
"the only supported address families");
return std::make_pair(false, errMsg);
}
// Get a socket for accepting connections.
if ((_serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
if ((_serverFd = socket(_addressFamily, SOCK_STREAM, 0)) < 0)
{
std::stringstream ss;
ss << "SocketServer::listen() error creating socket): " << strerror(Socket::getErrno());
@ -79,27 +87,59 @@ namespace ix
return std::make_pair(false, ss.str());
}
// Bind the socket to the server address.
server.sin_family = AF_INET;
server.sin_port = htons(_port);
// Using INADDR_ANY trigger a pop-up box as binding to any address is detected
// by the osx firewall. We need to codesign the binary with a self-signed cert
// to allow that, but this is a bit of a pain. (this is what node or python would do).
//
// Using INADDR_LOOPBACK also does not work ... while it should.
// We default to 127.0.0.1 (localhost)
//
server.sin_addr.s_addr = inet_addr(_host.c_str());
if (bind(_serverFd, (struct sockaddr*) &server, sizeof(server)) < 0)
if (_addressFamily == AF_INET)
{
std::stringstream ss;
ss << "SocketServer::listen() error calling bind "
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
struct sockaddr_in server;
server.sin_family = _addressFamily;
server.sin_port = htons(_port);
Socket::closeSocket(_serverFd);
return std::make_pair(false, ss.str());
if (inet_pton(_addressFamily, _host.c_str(), &server.sin_addr.s_addr) <= 0)
{
std::stringstream ss;
ss << "SocketServer::listen() error calling inet_pton "
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
Socket::closeSocket(_serverFd);
return std::make_pair(false, ss.str());
}
// Bind the socket to the server address.
if (bind(_serverFd, (struct sockaddr*) &server, sizeof(server)) < 0)
{
std::stringstream ss;
ss << "SocketServer::listen() error calling bind "
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
Socket::closeSocket(_serverFd);
return std::make_pair(false, ss.str());
}
}
else // AF_INET6
{
struct sockaddr_in6 server;
server.sin6_family = _addressFamily;
server.sin6_port = htons(_port);
if (inet_pton(_addressFamily, _host.c_str(), &server.sin6_addr) <= 0)
{
std::stringstream ss;
ss << "SocketServer::listen() error calling inet_pton "
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
Socket::closeSocket(_serverFd);
return std::make_pair(false, ss.str());
}
// Bind the socket to the server address.
if (bind(_serverFd, (struct sockaddr*) &server, sizeof(server)) < 0)
{
std::stringstream ss;
ss << "SocketServer::listen() error calling bind "
<< "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno());
Socket::closeSocket(_serverFd);
return std::make_pair(false, ss.str());
}
}
//

View File

@ -36,7 +36,8 @@ namespace ix
SocketServer(int port = SocketServer::kDefaultPort,
const std::string& host = SocketServer::kDefaultHost,
int backlog = SocketServer::kDefaultTcpBacklog,
size_t maxConnections = SocketServer::kDefaultMaxConnections);
size_t maxConnections = SocketServer::kDefaultMaxConnections,
int addressFamily = SocketServer::kDefaultAddressFamily);
virtual ~SocketServer();
virtual void stop();
@ -49,6 +50,7 @@ namespace ix
const static std::string kDefaultHost;
const static int kDefaultTcpBacklog;
const static size_t kDefaultMaxConnections;
const static int kDefaultAddressFamily;
void start();
std::pair<bool, std::string> listen();
@ -69,6 +71,7 @@ namespace ix
std::string _host;
int _backlog;
size_t _maxConnections;
int _addressFamily;
// socket for accepting connections
int _serverFd;

View File

@ -169,6 +169,7 @@ namespace ix
// wait until working thread will exit
// it will exit after close operation is finished
_stop = true;
_sleepCondition.notify_one();
_thread.join();
_stop = false;
}
@ -282,8 +283,13 @@ namespace ix
// Only sleep if we are retrying
if (duration.count() > 0)
{
// to do: make sleeping conditional
std::this_thread::sleep_for(duration);
std::unique_lock<std::mutex> lock(_sleepMutex);
_sleepCondition.wait_for(lock, duration);
}
if (_stop)
{
break;
}
// Try to connect synchronously

View File

@ -22,6 +22,7 @@
#include <mutex>
#include <string>
#include <thread>
#include <condition_variable>
namespace ix
{
@ -140,6 +141,10 @@ namespace ix
static const uint32_t kDefaultMaxWaitBetweenReconnectionRetries;
uint32_t _maxWaitBetweenReconnectionRetries;
// Make the sleeping in the automatic reconnection cancellable
std::mutex _sleepMutex;
std::condition_variable _sleepCondition;
std::atomic<int> _handshakeTimeoutSecs;
static const int kDefaultHandShakeTimeoutSecs;

View File

@ -23,8 +23,9 @@ namespace ix
const std::string& host,
int backlog,
size_t maxConnections,
int handshakeTimeoutSecs)
: SocketServer(port, host, backlog, maxConnections)
int handshakeTimeoutSecs,
int addressFamily)
: SocketServer(port, host, backlog, maxConnections, addressFamily)
, _handshakeTimeoutSecs(handshakeTimeoutSecs)
, _enablePong(kDefaultEnablePong)
{
@ -106,7 +107,6 @@ namespace ix
}
}
logInfo("WebSocketServer::handleConnection() done");
connectionState->setTerminated();
}

View File

@ -29,7 +29,8 @@ namespace ix
const std::string& host = SocketServer::kDefaultHost,
int backlog = SocketServer::kDefaultTcpBacklog,
size_t maxConnections = SocketServer::kDefaultMaxConnections,
int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs);
int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs,
int addressFamily = SocketServer::kDefaultAddressFamily);
virtual ~WebSocketServer();
virtual void stop() final;
@ -41,6 +42,8 @@ namespace ix
// Get all the connected clients
std::set<std::shared_ptr<WebSocket>> getClients();
const static int kDefaultHandShakeTimeoutSecs;
private:
// Member variables
int _handshakeTimeoutSecs;
@ -51,7 +54,6 @@ namespace ix
std::mutex _clientsMutex;
std::set<std::shared_ptr<WebSocket>> _clients;
const static int kDefaultHandShakeTimeoutSecs;
const static bool kDefaultEnablePong;
// Methods

View File

@ -6,4 +6,4 @@
#pragma once
#define IX_WEBSOCKET_VERSION "7.9.4"
#define IX_WEBSOCKET_VERSION "8.0.5"

View File

@ -49,6 +49,9 @@ BUILD := ${NAME}:build
print_version:
@echo 'IXWebSocket version =>' ${TAG}
set_version:
sh tools/update_version.sh ${VERSION}
docker_test:
docker build -f docker/Dockerfile.debian -t bsergean/ixwebsocket_test:build .

45
tools/update_version.sh Executable file
View File

@ -0,0 +1,45 @@
#/bin/sh
ver_gt() {
[ "$1" != "$2" ] && [ "$2" == "$(echo "$1\n$2" | sort -V | head -n1)" ]
}
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname ${SCRIPT_DIR})"
CUR_VSN=$(bash $SCRIPT_DIR/extract_version.sh)
NEW_VSN="$1"
check_ver() {
if [[ $NEW_VSN =~ ^[0-9.]+$ ]]; then
:
else
echo "Invalid version '$NEW_VSN'"
exit 1
fi
}
check_ver_increase() {
if ! ver_gt $NEW_VSN $CUR_VSN; then
echo "Invalid version '$NEW_VSN'. Must be greater than current version $CUR_VSN"
exit 1
fi
}
check_changelog() {
if ! egrep "\b$NEW_VSN\b" $PROJECT_ROOT/docs/CHANGELOG.md >/dev/null; then
echo "Invalid version '$NEW_VSN'. Missing entry in CHANGELOG.md"
exit 1
fi
}
set_version() {
sed -i '' "s/$CUR_VSN/$NEW_VSN/g" $PROJECT_ROOT/ixwebsocket/IXWebSocketVersion.h
echo "Set version to '$NEW_VSN'"
exit 0
}
check_ver
check_ver_increase
check_changelog
set_version

View File

@ -65,6 +65,7 @@ add_executable(ws
ws_autobahn.cpp
ws_proxy_server.cpp
ws_sentry_minidump_upload.cpp
ws_dns_lookup.cpp
ws.cpp)
target_link_libraries(ws ixsnake)

View File

@ -94,10 +94,12 @@ int main(int argc, char** argv)
bool disableAutomaticReconnection = false;
bool disablePerMessageDeflate = false;
bool greetings = false;
bool ipv6 = false;
bool binaryMode = false;
bool redirect = false;
bool version = false;
bool verifyNone = false;
bool disablePong = false;
int port = 8008;
int redisPort = 6379;
int statsdPort = 8125;
@ -171,6 +173,7 @@ int main(int argc, char** argv)
echoServerApp->add_option("--port", port, "Port");
echoServerApp->add_option("--host", hostname, "Hostname");
echoServerApp->add_flag("-g", greetings, "Verbose");
echoServerApp->add_flag("-6", ipv6, "IpV6");
addTLSOptions(echoServerApp);
CLI::App* broadcastServerApp = app.add_subcommand("broadcast_server", "Broadcasting server");
@ -307,6 +310,7 @@ int main(int argc, char** argv)
snakeApp->add_option("--apps_config_path", appsConfigPath, "Path to auth data")
->check(CLI::ExistingPath);
snakeApp->add_flag("-v", verbose, "Verbose");
snakeApp->add_flag("-d", disablePong, "Disable Pongs");
addTLSOptions(snakeApp);
CLI::App* httpServerApp = app.add_subcommand("httpd", "HTTP server");
@ -338,6 +342,9 @@ int main(int argc, char** argv)
minidumpApp->add_option("--key", key, "Sentry Key")->required();
minidumpApp->add_flag("-v", verbose, "Verbose");
CLI::App* dnsLookupApp = app.add_subcommand("dnslookup", "DNS lookup");
dnsLookupApp->add_option("host", hostname, "Hostname")->required();
CLI11_PARSE(app, argc, argv);
// pid file handling
@ -387,7 +394,7 @@ int main(int argc, char** argv)
}
else if (app.got_subcommand("echo_server"))
{
ret = ix::ws_echo_server_main(port, greetings, hostname, tlsOptions);
ret = ix::ws_echo_server_main(port, greetings, hostname, tlsOptions, ipv6);
}
else if (app.got_subcommand("broadcast_server"))
{
@ -487,7 +494,8 @@ int main(int argc, char** argv)
redisPassword,
verbose,
appsConfigPath,
tlsOptions);
tlsOptions,
disablePong);
}
else if (app.got_subcommand("httpd"))
{
@ -509,6 +517,10 @@ int main(int argc, char** argv)
{
ret = ix::ws_sentry_minidump_upload(metadata, minidump, project, key, verbose);
}
else if (app.got_subcommand("dnslookup"))
{
ret = ix::ws_dns_lookup(hostname);
}
else if (version)
{
spdlog::info("ws {}", ix::userAgent());

View File

@ -29,7 +29,9 @@ namespace ix
int ws_echo_server_main(int port,
bool greetings,
const std::string& hostname,
const ix::SocketTLSOptions& tlsOptions);
const ix::SocketTLSOptions& tlsOptions,
bool ipv6);
int ws_broadcast_server_main(int port,
const std::string& hostname,
const ix::SocketTLSOptions& tlsOptions);
@ -140,7 +142,8 @@ namespace ix
const std::string& redisPassword,
bool verbose,
const std::string& appsConfigPath,
const ix::SocketTLSOptions& tlsOptions);
const ix::SocketTLSOptions& tlsOptions,
bool disablePong);
int ws_httpd_main(int port,
const std::string& hostname,
@ -163,4 +166,6 @@ namespace ix
const std::string& project,
const std::string& key,
bool verbose);
int ws_dns_lookup(const std::string& hostname);
} // namespace ix

View File

@ -58,8 +58,6 @@ namespace ix
std::random_shuffle(games.begin(), games.end());
std::string game = games[0];
spdlog::info("Sending event for game '{}'", game);
_condition.wait(lock, [this] { return !_stop; });
if (_queues[game].empty())

34
ws/ws_dns_lookup.cpp Normal file
View File

@ -0,0 +1,34 @@
/*
* ws_dns_lookup.cpp
* Author: Benjamin Sergeant
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
*/
#include <atomic>
#include <spdlog/spdlog.h>
#include <sstream>
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXDNSLookup.h>
namespace ix
{
int ws_dns_lookup(const std::string& hostname)
{
auto dnsLookup = std::make_shared<DNSLookup>(hostname, 80);
std::string errMsg;
struct addrinfo* res;
res = dnsLookup->resolve(errMsg, [] { return false; });
auto addr = res->ai_addr;
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &addr, str, INET_ADDRSTRLEN);
spdlog::info("host: {} ip: {}", hostname, str);
return 0;
}
} // namespace ix

View File

@ -5,6 +5,7 @@
*/
#include <ixwebsocket/IXWebSocketServer.h>
#include <ixwebsocket/IXNetSystem.h>
#include <spdlog/spdlog.h>
#include <sstream>
@ -13,11 +14,18 @@ namespace ix
int ws_echo_server_main(int port,
bool greetings,
const std::string& hostname,
const ix::SocketTLSOptions& tlsOptions)
const ix::SocketTLSOptions& tlsOptions,
bool ipv6)
{
spdlog::info("Listening on {}:{}", hostname, port);
ix::WebSocketServer server(port, hostname);
ix::WebSocketServer server(port,
hostname,
SocketServer::kDefaultTcpBacklog,
SocketServer::kDefaultMaxConnections,
WebSocketServer::kDefaultHandShakeTimeoutSecs,
(ipv6) ? AF_INET6 : AF_INET);
server.setTLSOptions(tlsOptions);
server.setOnConnectionCallback(

View File

@ -44,7 +44,8 @@ namespace ix
const std::string& redisPassword,
bool verbose,
const std::string& appsConfigPath,
const SocketTLSOptions& socketTLSOptions)
const SocketTLSOptions& socketTLSOptions,
bool disablePong)
{
snake::AppConfig appConfig;
appConfig.port = port;
@ -53,6 +54,7 @@ namespace ix
appConfig.redisPort = redisPort;
appConfig.redisPassword = redisPassword;
appConfig.socketTLSOptions = socketTLSOptions;
appConfig.disablePong = disablePong;
// Parse config file
auto str = readAsString(appsConfigPath);