unique_ptr for sockets

This commit is contained in:
Benjamin Sergeant 2020-03-24 12:40:58 -07:00
parent 9f818c7acf
commit 179e17895d
25 changed files with 54 additions and 51 deletions

View File

@ -1,6 +1,10 @@
# Changelog # Changelog
All changes to this project will be documented in this file. All changes to this project will be documented in this file.
## [9.0.2] - 2020-03-24
(socket) works with unique_ptr<Socket> instead of shared_ptr<Socket> in many places
## [9.0.1] - 2020-03-24 ## [9.0.1] - 2020-03-24
(socket) selectInterrupt member is an unique_ptr instead of being a shared_ptr (socket) selectInterrupt member is an unique_ptr instead of being a shared_ptr

View File

@ -9,7 +9,6 @@
#include <cstring> #include <cstring>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXSocketFactory.h> #include <ixwebsocket/IXSocketFactory.h>
#include <ixwebsocket/IXSocketTLSOptions.h> #include <ixwebsocket/IXSocketTLSOptions.h>
#include <sstream> #include <sstream>

View File

@ -11,10 +11,10 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <ixwebsocket/IXSocket.h>
namespace ix namespace ix
{ {
class Socket;
class RedisClient class RedisClient
{ {
public: public:
@ -57,7 +57,7 @@ namespace ix
private: private:
std::string writeString(const std::string& str); std::string writeString(const std::string& str);
std::shared_ptr<Socket> _socket; std::unique_ptr<Socket> _socket;
std::atomic<bool> _stop; std::atomic<bool> _stop;
}; };
} // namespace ix } // namespace ix

View File

@ -43,7 +43,7 @@ namespace ix
SocketServer::stop(); SocketServer::stop();
} }
void RedisServer::handleConnection(std::shared_ptr<Socket> socket, void RedisServer::handleConnection(std::unique_ptr<Socket> socket,
std::shared_ptr<ConnectionState> connectionState) std::shared_ptr<ConnectionState> connectionState)
{ {
_connectedClientsCount++; _connectedClientsCount++;
@ -102,13 +102,13 @@ namespace ix
_connectedClientsCount--; _connectedClientsCount--;
} }
void RedisServer::cleanupSubscribers(std::shared_ptr<Socket> socket) void RedisServer::cleanupSubscribers(std::unique_ptr<Socket>& socket)
{ {
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
for (auto&& it : _subscribers) for (auto&& it : _subscribers)
{ {
it.second.erase(socket); it.second.erase(socket.get());
} }
for (auto it : _subscribers) for (auto it : _subscribers)
@ -145,7 +145,7 @@ namespace ix
} }
bool RedisServer::parseRequest( bool RedisServer::parseRequest(
std::shared_ptr<Socket> socket, std::unique_ptr<Socket>& socket,
std::vector<std::string>& tokens) std::vector<std::string>& tokens)
{ {
// Parse first line // Parse first line
@ -191,7 +191,7 @@ namespace ix
} }
bool RedisServer::handleCommand( bool RedisServer::handleCommand(
std::shared_ptr<Socket> socket, std::unique_ptr<Socket>& socket,
const std::vector<std::string>& tokens) const std::vector<std::string>& tokens)
{ {
if (tokens.size() != 1) return false; if (tokens.size() != 1) return false;
@ -230,7 +230,7 @@ namespace ix
} }
bool RedisServer::handleSubscribe( bool RedisServer::handleSubscribe(
std::shared_ptr<Socket> socket, std::unique_ptr<Socket>& socket,
const std::vector<std::string>& tokens) const std::vector<std::string>& tokens)
{ {
if (tokens.size() != 2) return false; if (tokens.size() != 2) return false;
@ -245,13 +245,13 @@ namespace ix
socket->writeBytes(":1\r\n", cb); socket->writeBytes(":1\r\n", cb);
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
_subscribers[channel].insert(socket); _subscribers[channel].insert(socket.get());
return true; return true;
} }
bool RedisServer::handlePublish( bool RedisServer::handlePublish(
std::shared_ptr<Socket> socket, std::unique_ptr<Socket>& socket,
const std::vector<std::string>& tokens) const std::vector<std::string>& tokens)
{ {
if (tokens.size() != 3) return false; if (tokens.size() != 3) return false;

View File

@ -37,13 +37,13 @@ namespace ix
// Subscribers // Subscribers
// We could store connection states in there, to add better debugging // We could store connection states in there, to add better debugging
// since a connection state has a readable ID // since a connection state has a readable ID
std::map<std::string, std::set<std::shared_ptr<Socket>>> _subscribers; std::map<std::string, std::set<Socket*>> _subscribers;
std::mutex _mutex; std::mutex _mutex;
std::atomic<bool> _stopHandlingConnections; std::atomic<bool> _stopHandlingConnections;
// Methods // Methods
virtual void handleConnection(std::shared_ptr<Socket>, virtual void handleConnection(std::unique_ptr<Socket>,
std::shared_ptr<ConnectionState> connectionState) final; std::shared_ptr<ConnectionState> connectionState) final;
virtual size_t getConnectedClientsCount() final; virtual size_t getConnectedClientsCount() final;
@ -51,18 +51,18 @@ namespace ix
std::string writeString(const std::string& str); std::string writeString(const std::string& str);
bool parseRequest( bool parseRequest(
std::shared_ptr<Socket> socket, std::unique_ptr<Socket>& socket,
std::vector<std::string>& tokens); std::vector<std::string>& tokens);
bool handlePublish(std::shared_ptr<Socket> socket, bool handlePublish(std::unique_ptr<Socket>& socket,
const std::vector<std::string>& tokens); const std::vector<std::string>& tokens);
bool handleSubscribe(std::shared_ptr<Socket> socket, bool handleSubscribe(std::unique_ptr<Socket>& socket,
const std::vector<std::string>& tokens); const std::vector<std::string>& tokens);
bool handleCommand(std::shared_ptr<Socket> socket, bool handleCommand(std::unique_ptr<Socket>& socket,
const std::vector<std::string>& tokens); const std::vector<std::string>& tokens);
void cleanupSubscribers(std::shared_ptr<Socket> socket); void cleanupSubscribers(std::unique_ptr<Socket>& socket);
}; };
} // namespace ix } // namespace ix

View File

@ -92,7 +92,7 @@ namespace ix
return std::make_tuple(method, requestUri, httpVersion); return std::make_tuple(method, requestUri, httpVersion);
} }
std::tuple<bool, std::string, HttpRequestPtr> Http::parseRequest(std::shared_ptr<Socket> socket) std::tuple<bool, std::string, HttpRequestPtr> Http::parseRequest(std::unique_ptr<Socket>& socket)
{ {
HttpRequestPtr httpRequest; HttpRequestPtr httpRequest;
@ -133,7 +133,7 @@ namespace ix
return std::make_tuple(true, "", httpRequest); return std::make_tuple(true, "", httpRequest);
} }
bool Http::sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket) bool Http::sendResponse(HttpResponsePtr response, std::unique_ptr<Socket>& socket)
{ {
// Write the response to the socket // Write the response to the socket
std::stringstream ss; std::stringstream ss;

View File

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

View File

@ -95,7 +95,7 @@ namespace ix
std::atomic<bool> _stop; std::atomic<bool> _stop;
std::thread _thread; std::thread _thread;
std::shared_ptr<Socket> _socket; std::unique_ptr<Socket> _socket;
std::mutex _mutex; // to protect accessing the _socket (only one socket per client) std::mutex _mutex; // to protect accessing the _socket (only one socket per client)
SocketTLSOptions _tlsOptions; SocketTLSOptions _tlsOptions;

View File

@ -69,7 +69,7 @@ namespace ix
_onConnectionCallback = callback; _onConnectionCallback = callback;
} }
void HttpServer::handleConnection(std::shared_ptr<Socket> socket, void HttpServer::handleConnection(std::unique_ptr<Socket> socket,
std::shared_ptr<ConnectionState> connectionState) std::shared_ptr<ConnectionState> connectionState)
{ {
_connectedClientsCount++; _connectedClientsCount++;

View File

@ -43,7 +43,7 @@ namespace ix
std::atomic<int> _connectedClientsCount; std::atomic<int> _connectedClientsCount;
// Methods // Methods
virtual void handleConnection(std::shared_ptr<Socket>, virtual void handleConnection(std::unique_ptr<Socket>,
std::shared_ptr<ConnectionState> connectionState) final; std::shared_ptr<ConnectionState> connectionState) final;
virtual size_t getConnectedClientsCount() final; virtual size_t getConnectedClientsCount() final;

View File

@ -24,28 +24,28 @@
namespace ix namespace ix
{ {
std::shared_ptr<Socket> createSocket(bool tls, std::unique_ptr<Socket> createSocket(bool tls,
int fd, int fd,
std::string& errorMsg, std::string& errorMsg,
const SocketTLSOptions& tlsOptions) const SocketTLSOptions& tlsOptions)
{ {
(void) tlsOptions; (void) tlsOptions;
errorMsg.clear(); errorMsg.clear();
std::shared_ptr<Socket> socket; std::unique_ptr<Socket> socket;
if (!tls) if (!tls)
{ {
socket = std::make_shared<Socket>(fd); socket = std::make_unique<Socket>(fd);
} }
else else
{ {
#ifdef IXWEBSOCKET_USE_TLS #ifdef IXWEBSOCKET_USE_TLS
#if defined(IXWEBSOCKET_USE_MBED_TLS) #if defined(IXWEBSOCKET_USE_MBED_TLS)
socket = std::make_shared<SocketMbedTLS>(tlsOptions, fd); socket = std::make_unique<SocketMbedTLS>(tlsOptions, fd);
#elif defined(IXWEBSOCKET_USE_OPEN_SSL) #elif defined(IXWEBSOCKET_USE_OPEN_SSL)
socket = std::make_shared<SocketOpenSSL>(tlsOptions, fd); socket = std::make_unique<SocketOpenSSL>(tlsOptions, fd);
#elif defined(__APPLE__) #elif defined(__APPLE__)
socket = std::make_shared<SocketAppleSSL>(tlsOptions, fd); socket = std::make_unique<SocketAppleSSL>(tlsOptions, fd);
#endif #endif
#else #else
errorMsg = "TLS support is not enabled on this platform."; errorMsg = "TLS support is not enabled on this platform.";

View File

@ -14,7 +14,7 @@
namespace ix namespace ix
{ {
class Socket; class Socket;
std::shared_ptr<Socket> createSocket(bool tls, std::unique_ptr<Socket> createSocket(bool tls,
int fd, int fd,
std::string& errorMsg, std::string& errorMsg,
const SocketTLSOptions& tlsOptions); const SocketTLSOptions& tlsOptions);

View File

@ -340,7 +340,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, this, socket, connectionState))); std::thread(&SocketServer::handleConnection, this, std::move(socket), connectionState)));
} }
} }

View File

@ -101,7 +101,7 @@ namespace ix
// the factory to create ConnectionState objects // the factory to create ConnectionState objects
ConnectionStateFactory _connectionStateFactory; ConnectionStateFactory _connectionStateFactory;
virtual void handleConnection(std::shared_ptr<Socket>, virtual void handleConnection(std::unique_ptr<Socket>,
std::shared_ptr<ConnectionState> connectionState) = 0; std::shared_ptr<ConnectionState> connectionState) = 0;
virtual size_t getConnectedClientsCount() = 0; virtual size_t getConnectedClientsCount() = 0;

View File

@ -210,7 +210,7 @@ namespace ix
return status; return status;
} }
WebSocketInitResult WebSocket::connectToSocket(std::shared_ptr<Socket> socket, int timeoutSecs) WebSocketInitResult WebSocket::connectToSocket(std::unique_ptr<Socket> socket, int timeoutSecs)
{ {
{ {
std::lock_guard<std::mutex> lock(_configMutex); std::lock_guard<std::mutex> lock(_configMutex);
@ -218,7 +218,7 @@ namespace ix
_perMessageDeflateOptions, _socketTLSOptions, _enablePong, _pingIntervalSecs); _perMessageDeflateOptions, _socketTLSOptions, _enablePong, _pingIntervalSecs);
} }
WebSocketInitResult status = _ws.connectToSocket(socket, timeoutSecs); WebSocketInitResult status = _ws.connectToSocket(std::move(socket), timeoutSecs);
if (!status.success) if (!status.success)
{ {
return status; return status;

View File

@ -113,7 +113,7 @@ namespace ix
static void invokeTrafficTrackerCallback(size_t size, bool incoming); static void invokeTrafficTrackerCallback(size_t size, bool incoming);
// Server // Server
WebSocketInitResult connectToSocket(std::shared_ptr<Socket>, int timeoutSecs); WebSocketInitResult connectToSocket(std::unique_ptr<Socket>, int timeoutSecs);
WebSocketTransport _ws; WebSocketTransport _ws;

View File

@ -21,7 +21,7 @@ namespace ix
{ {
WebSocketHandshake::WebSocketHandshake( WebSocketHandshake::WebSocketHandshake(
std::atomic<bool>& requestInitCancellation, std::atomic<bool>& requestInitCancellation,
std::shared_ptr<Socket> socket, std::unique_ptr<Socket>& socket,
WebSocketPerMessageDeflatePtr& perMessageDeflate, WebSocketPerMessageDeflatePtr& perMessageDeflate,
WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
std::atomic<bool>& enablePerMessageDeflate) std::atomic<bool>& enablePerMessageDeflate)

View File

@ -23,7 +23,7 @@ namespace ix
{ {
public: public:
WebSocketHandshake(std::atomic<bool>& requestInitCancellation, WebSocketHandshake(std::atomic<bool>& requestInitCancellation,
std::shared_ptr<Socket> _socket, std::unique_ptr<Socket>& _socket,
WebSocketPerMessageDeflatePtr& perMessageDeflate, WebSocketPerMessageDeflatePtr& perMessageDeflate,
WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
std::atomic<bool>& enablePerMessageDeflate); std::atomic<bool>& enablePerMessageDeflate);
@ -46,7 +46,7 @@ namespace ix
bool insensitiveStringCompare(const std::string& a, const std::string& b); bool insensitiveStringCompare(const std::string& a, const std::string& b);
std::atomic<bool>& _requestInitCancellation; std::atomic<bool>& _requestInitCancellation;
std::shared_ptr<Socket> _socket; std::unique_ptr<Socket>& _socket;
WebSocketPerMessageDeflatePtr& _perMessageDeflate; WebSocketPerMessageDeflatePtr& _perMessageDeflate;
WebSocketPerMessageDeflateOptions& _perMessageDeflateOptions; WebSocketPerMessageDeflateOptions& _perMessageDeflateOptions;
std::atomic<bool>& _enablePerMessageDeflate; std::atomic<bool>& _enablePerMessageDeflate;

View File

@ -32,7 +32,7 @@ namespace ix
} }
std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders( std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders(
std::shared_ptr<Socket> socket, const CancellationRequest& isCancellationRequested) std::unique_ptr<Socket>& socket, const CancellationRequest& isCancellationRequested)
{ {
WebSocketHttpHeaders headers; WebSocketHttpHeaders headers;

View File

@ -29,5 +29,5 @@ namespace ix
using WebSocketHttpHeaders = std::map<std::string, std::string, CaseInsensitiveLess>; using WebSocketHttpHeaders = std::map<std::string, std::string, CaseInsensitiveLess>;
std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders( std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders(
std::shared_ptr<Socket> socket, const CancellationRequest& isCancellationRequested); std::unique_ptr<Socket>& socket, const CancellationRequest& isCancellationRequested);
} // namespace ix } // namespace ix

View File

@ -71,7 +71,7 @@ namespace ix
_onConnectionCallback = callback; _onConnectionCallback = callback;
} }
void WebSocketServer::handleConnection(std::shared_ptr<Socket> socket, void WebSocketServer::handleConnection(std::unique_ptr<Socket> socket,
std::shared_ptr<ConnectionState> connectionState) std::shared_ptr<ConnectionState> connectionState)
{ {
setThreadName("WebSocketServer::" + connectionState->getId()); setThreadName("WebSocketServer::" + connectionState->getId());
@ -96,7 +96,7 @@ namespace ix
_clients.insert(webSocket); _clients.insert(webSocket);
} }
auto status = webSocket->connectToSocket(socket, _handshakeTimeoutSecs); auto status = webSocket->connectToSocket(std::move(socket), _handshakeTimeoutSecs);
if (status.success) if (status.success)
{ {
// Process incoming messages and execute callbacks // Process incoming messages and execute callbacks

View File

@ -59,7 +59,7 @@ namespace ix
const static bool kDefaultEnablePong; const static bool kDefaultEnablePong;
// Methods // Methods
virtual void handleConnection(std::shared_ptr<Socket> socket, virtual void handleConnection(std::unique_ptr<Socket> socket,
std::shared_ptr<ConnectionState> connectionState) final; std::shared_ptr<ConnectionState> connectionState) final;
virtual size_t getConnectedClientsCount() final; virtual size_t getConnectedClientsCount() final;
}; };

View File

@ -140,7 +140,7 @@ namespace ix
} }
// Server // Server
WebSocketInitResult WebSocketTransport::connectToSocket(std::shared_ptr<Socket> socket, WebSocketInitResult WebSocketTransport::connectToSocket(std::unique_ptr<Socket> socket,
int timeoutSecs) int timeoutSecs)
{ {
std::lock_guard<std::mutex> lock(_socketMutex); std::lock_guard<std::mutex> lock(_socketMutex);
@ -149,7 +149,7 @@ namespace ix
_useMask = false; _useMask = false;
_blockingSend = true; _blockingSend = true;
_socket = socket; _socket = std::move(socket);
_perMessageDeflate = std::make_unique<WebSocketPerMessageDeflate>(); _perMessageDeflate = std::make_unique<WebSocketPerMessageDeflate>();
WebSocketHandshake webSocketHandshake(_requestInitCancellation, WebSocketHandshake webSocketHandshake(_requestInitCancellation,

View File

@ -83,7 +83,7 @@ namespace ix
int timeoutSecs); int timeoutSecs);
// Server // Server
WebSocketInitResult connectToSocket(std::shared_ptr<Socket> socket, int timeoutSecs); WebSocketInitResult connectToSocket(std::unique_ptr<Socket> socket, int timeoutSecs);
PollResult poll(); PollResult poll();
WebSocketSendInfo sendBinary(const std::string& message, WebSocketSendInfo sendBinary(const std::string& message,
@ -171,7 +171,7 @@ namespace ix
static constexpr size_t kChunkSize = 1 << 15; static constexpr size_t kChunkSize = 1 << 15;
// Underlying TCP socket // Underlying TCP socket
std::shared_ptr<Socket> _socket; std::unique_ptr<Socket> _socket;
std::mutex _socketMutex; std::mutex _socketMutex;
// Hold the state of the connection (OPEN, CLOSED, etc...) // Hold the state of the connection (OPEN, CLOSED, etc...)

View File

@ -6,4 +6,4 @@
#pragma once #pragma once
#define IX_WEBSOCKET_VERSION "9.0.1" #define IX_WEBSOCKET_VERSION "9.0.2"