select interrupt cleanup

This commit is contained in:
Benjamin Sergeant 2019-03-14 18:37:38 -07:00
parent b462b5a5c8
commit b91dc77d6f
22 changed files with 411 additions and 150 deletions

View File

@ -16,7 +16,6 @@ if (NOT WIN32)
endif() endif()
set( IXWEBSOCKET_SOURCES set( IXWEBSOCKET_SOURCES
ixwebsocket/IXEventFd.cpp
ixwebsocket/IXSocket.cpp ixwebsocket/IXSocket.cpp
ixwebsocket/IXSocketServer.cpp ixwebsocket/IXSocketServer.cpp
ixwebsocket/IXSocketConnect.cpp ixwebsocket/IXSocketConnect.cpp
@ -33,10 +32,11 @@ set( IXWEBSOCKET_SOURCES
ixwebsocket/IXWebSocketHttpHeaders.cpp ixwebsocket/IXWebSocketHttpHeaders.cpp
ixwebsocket/IXHttpClient.cpp ixwebsocket/IXHttpClient.cpp
ixwebsocket/IXUrlParser.cpp ixwebsocket/IXUrlParser.cpp
ixwebsocket/IXSelectInterrupt.cpp
ixwebsocket/IXSelectInterruptFactory.cpp
) )
set( IXWEBSOCKET_HEADERS set( IXWEBSOCKET_HEADERS
ixwebsocket/IXEventFd.h
ixwebsocket/IXSocket.h ixwebsocket/IXSocket.h
ixwebsocket/IXSocketServer.h ixwebsocket/IXSocketServer.h
ixwebsocket/IXSocketConnect.h ixwebsocket/IXSocketConnect.h
@ -58,15 +58,21 @@ set( IXWEBSOCKET_HEADERS
ixwebsocket/libwshandshake.hpp ixwebsocket/libwshandshake.hpp
ixwebsocket/IXHttpClient.h ixwebsocket/IXHttpClient.h
ixwebsocket/IXUrlParser.h ixwebsocket/IXUrlParser.h
ixwebsocket/IXSelectInterrupt.h
ixwebsocket/IXSelectInterruptFactory.h
) )
# Platform specific code # Platform specific code
if (APPLE) if (APPLE)
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/apple/IXSetThreadName_apple.cpp) list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/apple/IXSetThreadName_apple.cpp)
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSelectInterruptPipe.cpp)
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSelectInterruptPipe.h)
elseif (WIN32) elseif (WIN32)
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/windows/IXSetThreadName_windows.cpp) list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/windows/IXSetThreadName_windows.cpp)
else() else()
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/linux/IXSetThreadName_linux.cpp) list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/linux/IXSetThreadName_linux.cpp)
list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSelectInterruptEventFd.cpp)
list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSelectInterruptEventFd.h)
endif() endif()
if (USE_TLS) if (USE_TLS)

View File

@ -0,0 +1,46 @@
/*
* IXSelectInterrupt.cpp
* Author: Benjamin Sergeant
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/
#include "IXSelectInterrupt.h"
namespace ix
{
SelectInterrupt::SelectInterrupt()
{
;
}
SelectInterrupt::~SelectInterrupt()
{
;
}
bool SelectInterrupt::init(std::string& /*errorMsg*/)
{
return true;
}
bool SelectInterrupt::notify(uint64_t /*value*/)
{
return true;
}
uint64_t SelectInterrupt::read()
{
return 0;
}
bool SelectInterrupt::clear()
{
return true;
}
int SelectInterrupt::getFd()
{
return -1;
}
}

View File

@ -0,0 +1,28 @@
/*
* IXSelectInterrupt.h
* Author: Benjamin Sergeant
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/
#pragma once
#include <stdint.h>
#include <string>
namespace ix
{
class SelectInterrupt {
public:
SelectInterrupt();
virtual ~SelectInterrupt();
virtual bool init(std::string& errorMsg);
virtual bool notify(uint64_t value);
virtual bool clear();
virtual uint64_t read();
virtual int getFd();
};
}

View File

@ -1,9 +1,13 @@
/* /*
* IXEventFd.cpp * IXSelectInterruptEventFd.cpp
* Author: Benjamin Sergeant * Author: Benjamin Sergeant
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved. * Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved.
*/ */
//
// On Linux we use eventd to wake up select.
//
// //
// Linux/Android has a special type of virtual files. select(2) will react // Linux/Android has a special type of virtual files. select(2) will react
// when reading/writing to those files, unlike closing sockets. // when reading/writing to those files, unlike closing sockets.
@ -22,57 +26,59 @@
#include "IXEventFd.h" #include "IXEventFd.h"
#ifdef __linux__ #include <sys/eventfd.h>
# include <sys/eventfd.h>
#endif
#include <unistd.h> // for write #include <unistd.h> // for write
#include <string.h> // for strerror
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
#include <sstream>
namespace ix namespace ix
{ {
// File descriptor at index 0 in _fildes is the read end of the pipe SelectInterruptEventFd::SelectInterruptEventFd()
// File descriptor at index 1 in _fildes is the write end of the pipe
const int EventFd::kPipeReadIndex = 0;
const int EventFd::kPipeWriteIndex = 1;
EventFd::EventFd()
{ {
#ifdef __linux__ ;
_eventfd = -1;
_eventfd = eventfd(0, 0);
fcntl(_eventfd, F_SETFL, O_NONBLOCK);
#else
_fildes[kPipeReadIndex] = -1;
_fildes[kPipeWriteIndex] = -1;
pipe(_fildes);
fcntl(_fildes[kPipeReadIndex], F_SETFL, O_NONBLOCK);
fcntl(_fildes[kPipeWriteIndex], F_SETFL, O_NONBLOCK);
#endif
} }
EventFd::~EventFd() SelectInterruptEventFd::~SelectInterruptEventFd()
{ {
#ifdef __linux__
::close(_eventfd); ::close(_eventfd);
#else
::close(_fildes[kPipeReadIndex]);
::close(_fildes[kPipeWriteIndex]);
_fildes[kPipeReadIndex] = -1;
_fildes[kPipeWriteIndex] = -1;
#endif
} }
bool EventFd::notify(uint64_t value) bool SelectInterruptEventFd::init(std::string& errorMsg)
{ {
int fd; _eventfd = -1;
#if defined(__linux__) _eventfd = eventfd(0, 0);
fd = _eventfd; if (_eventfd < 0)
#else {
fd = _fildes[kPipeWriteIndex]; std::stringstream ss;
#endif ss << "SelectInterruptEventFd::init() failed in eventfd()"
<< " : " << strerror(errno);
errorMsg = ss.str();
_eventfd = -1;
return false;
}
if (fcntl(_eventfd, F_SETFL, O_NONBLOCK) == -1)
{
std::stringstream ss;
ss << "SelectInterruptEventFd::init() failed in fcntl() call"
<< " : " << strerror(errno);
errorMsg = ss.str();
_eventfd = -1;
return false;
}
return true;
}
bool SelectInterruptEventFd::notify(uint64_t value)
{
int fd = _eventfd;
if (fd == -1) return false; if (fd == -1) return false;
@ -81,23 +87,17 @@ namespace ix
} }
// TODO: return max uint64_t for errors ? // TODO: return max uint64_t for errors ?
uint64_t EventFd::read() uint64_t SelectInterruptEventFd::read()
{ {
int fd; int fd = _eventfd;
#if defined(__linux__)
fd = _eventfd;
#else
fd = _fildes[kPipeReadIndex];
#endif
uint64_t value = 0; uint64_t value = 0;
::read(fd, &value, sizeof(value)); ::read(fd, &value, sizeof(value));
return value; return value;
} }
bool EventFd::clear() bool SelectInterruptEventFd::clear()
{ {
#if defined(__linux__)
if (_eventfd == -1) return false; if (_eventfd == -1) return false;
// 0 is a special value ; select will not wake up // 0 is a special value ; select will not wake up
@ -105,17 +105,10 @@ namespace ix
// we should write 8 bytes for an uint64_t // we should write 8 bytes for an uint64_t
return write(_eventfd, &value, sizeof(value)) == 8; return write(_eventfd, &value, sizeof(value)) == 8;
#else
return true;
#endif
} }
int EventFd::getFd() int SelectInterruptEventFd::getFd()
{ {
#if defined(__linux__)
return _eventfd; return _eventfd;
#else
return _fildes[kPipeReadIndex];
#endif
} }
} }

View File

@ -0,0 +1,32 @@
/*
* IXSelectInterruptEventFd.h
* Author: Benjamin Sergeant
* Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved.
*/
#pragma once
#include "IXSelectInterrupt.h"
#include <stdint.h>
#include <string>
namespace ix
{
class SelectInterruptEventFd : public SelectInterrupt {
public:
SelectInterruptEventFd();
virtual ~SelectInterruptEventFd();
bool init(std::string& errorMsg) final;
bool notify(uint64_t value) final;
bool clear() final;
uint64_t read() final;
int getFd() final;
private:
int _eventfd;
};
}

View File

@ -0,0 +1,25 @@
/*
* IXSelectInterruptFactory.cpp
* Author: Benjamin Sergeant
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/
#include "IXSelectInterruptFactory.h"
#if defined(__linux__)
# include <ixwebsocket/IXSelectInterruptEventFd.h>
#else
# include <ixwebsocket/IXSelectInterruptPipe.h>
#endif
namespace ix
{
std::shared_ptr<SelectInterrupt> createSelectInterrupt()
{
#if defined(__linux__)
return std::make_shared<SelectInterruptEventFd>();
#else
return std::make_shared<SelectInterruptPipe>();
#endif
}
}

View File

@ -0,0 +1,15 @@
/*
* IXSelectInterruptFactory.h
* Author: Benjamin Sergeant
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/
#pragma once
#include <memory>
namespace ix
{
class SelectInterrupt;
std::shared_ptr<SelectInterrupt> createSelectInterrupt();
}

View File

@ -0,0 +1,108 @@
/*
* IXEventFd.cpp
* Author: Benjamin Sergeant
* Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved.
*/
//
// On macOS we use UNIX pipes to wake up select.
//
#include "IXSelectInterruptPipe.h"
#include <unistd.h> // for write
#include <string.h> // for strerror
#include <fcntl.h>
#include <errno.h>
#include <sstream>
namespace ix
{
// File descriptor at index 0 in _fildes is the read end of the pipe
// File descriptor at index 1 in _fildes is the write end of the pipe
const int SelectInterruptPipe::kPipeReadIndex = 0;
const int SelectInterruptPipe::kPipeWriteIndex = 1;
SelectInterruptPipe::SelectInterruptPipe()
{
;
}
SelectInterruptPipe::~SelectInterruptPipe()
{
::close(_fildes[kPipeReadIndex]);
::close(_fildes[kPipeWriteIndex]);
_fildes[kPipeReadIndex] = -1;
_fildes[kPipeWriteIndex] = -1;
}
bool SelectInterruptPipe::init(std::string& errorMsg)
{
_fildes[kPipeReadIndex] = -1;
_fildes[kPipeWriteIndex] = -1;
if (pipe(_fildes) < 0)
{
std::stringstream ss;
ss << "SelectInterruptPipe::init() failed in pipe() call"
<< " : " << strerror(errno);
errorMsg = ss.str();
return false;
}
if (fcntl(_fildes[kPipeReadIndex], F_SETFL, O_NONBLOCK) == -1)
{
std::stringstream ss;
ss << "SelectInterruptPipe::init() failed in fcntl() call"
<< " : " << strerror(errno);
errorMsg = ss.str();
_fildes[kPipeReadIndex] = -1;
_fildes[kPipeWriteIndex] = -1;
return false;
}
if (fcntl(_fildes[kPipeWriteIndex], F_SETFL, O_NONBLOCK) == -1)
{
std::stringstream ss;
ss << "SelectInterruptPipe::init() failed in fcntl() call"
<< " : " << strerror(errno);
errorMsg = ss.str();
_fildes[kPipeReadIndex] = -1;
_fildes[kPipeWriteIndex] = -1;
return false;
}
return true;
}
bool SelectInterruptPipe::notify(uint64_t value)
{
int fd = _fildes[kPipeWriteIndex];
if (fd == -1) return false;
// we should write 8 bytes for an uint64_t
return write(fd, &value, sizeof(value)) == 8;
}
// TODO: return max uint64_t for errors ?
uint64_t SelectInterruptPipe::read()
{
int fd = _fildes[kPipeReadIndex];
uint64_t value = 0;
::read(fd, &value, sizeof(value));
return value;
}
bool SelectInterruptPipe::clear()
{
return true;
}
int SelectInterruptPipe::getFd()
{
return _fildes[kPipeReadIndex];
}
}

View File

@ -1,37 +1,39 @@
/* /*
* IXEventFd.h * IXSelectInterruptPipe.h
* Author: Benjamin Sergeant * Author: Benjamin Sergeant
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved. * Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved.
*/ */
#pragma once #pragma once
#include "IXSelectInterrupt.h"
#include <stdint.h> #include <stdint.h>
#include <string>
namespace ix namespace ix
{ {
class EventFd { class SelectInterruptPipe : public SelectInterrupt {
public: public:
EventFd(); SelectInterruptPipe();
virtual ~EventFd(); virtual ~SelectInterruptPipe();
bool notify(uint64_t value); bool init(std::string& errorMsg) final;
bool clear();
uint64_t read(); bool notify(uint64_t value) final;
int getFd(); bool clear() final;
uint64_t read() final;
int getFd() final;
private: private:
#if defined(__linux__)
int _eventfd;
#else
// Store file descriptors used by the communication pipe. Communication // Store file descriptors used by the communication pipe. Communication
// happens between a control thread and a background thread, which is // happens between a control thread and a background thread, which is
// blocked on select. // blocked on select.
int _fildes[2]; int _fildes[2];
#endif
// Used to identify the read/write idx // Used to identify the read/write idx
static const int kPipeReadIndex; static const int kPipeReadIndex;
static const int kPipeWriteIndex; static const int kPipeWriteIndex;
}; };
} }

View File

@ -7,6 +7,8 @@
#include "IXSocket.h" #include "IXSocket.h"
#include "IXSocketConnect.h" #include "IXSocketConnect.h"
#include "IXNetSystem.h" #include "IXNetSystem.h"
#include "IXSelectInterrupt.h"
#include "IXSelectInterruptFactory.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -28,7 +30,8 @@ namespace ix
constexpr size_t Socket::kChunkSize; constexpr size_t Socket::kChunkSize;
Socket::Socket(int fd) : Socket::Socket(int fd) :
_sockfd(fd) _sockfd(fd),
_selectInterrupt(createSelectInterrupt())
{ {
; ;
} }
@ -57,11 +60,11 @@ namespace ix
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(_sockfd, &rfds); FD_SET(_sockfd, &rfds);
// File descriptor at index 0 in _fildes is the read end of the pipe // File descriptor used to interrupt select when needed
int eventfd = _eventfd.getFd(); int interruptFd = _selectInterrupt->getFd();
if (eventfd != -1) if (interruptFd != -1)
{ {
FD_SET(eventfd, &rfds); FD_SET(interruptFd, &rfds);
} }
struct timeval timeout; struct timeval timeout;
@ -70,7 +73,7 @@ namespace ix
// Compute the highest fd. // Compute the highest fd.
int sockfd = _sockfd; int sockfd = _sockfd;
int nfds = (std::max)(sockfd, eventfd); int nfds = (std::max)(sockfd, interruptFd);
int ret = ::select(nfds + 1, &rfds, nullptr, nullptr, int ret = ::select(nfds + 1, &rfds, nullptr, nullptr,
(timeoutSecs < 0) ? nullptr : &timeout); (timeoutSecs < 0) ? nullptr : &timeout);
@ -84,9 +87,9 @@ namespace ix
{ {
pollResult = PollResultType_Timeout; pollResult = PollResultType_Timeout;
} }
else if (eventfd != -1 && FD_ISSET(eventfd, &rfds)) else if (interruptFd != -1 && FD_ISSET(interruptFd, &rfds))
{ {
uint64_t value = _eventfd.read(); uint64_t value = _selectInterrupt->read();
if (value == kSendRequest) if (value == kSendRequest)
{ {
@ -104,7 +107,7 @@ namespace ix
// Wake up from poll/select by writing to the pipe which is watched by select // Wake up from poll/select by writing to the pipe which is watched by select
bool Socket::wakeUpFromPoll(uint8_t wakeUpCode) bool Socket::wakeUpFromPoll(uint8_t wakeUpCode)
{ {
return _eventfd.notify(wakeUpCode); return _selectInterrupt->notify(wakeUpCode);
} }
bool Socket::connect(const std::string& host, bool Socket::connect(const std::string& host,
@ -114,7 +117,7 @@ namespace ix
{ {
std::lock_guard<std::mutex> lock(_socketMutex); std::lock_guard<std::mutex> lock(_socketMutex);
if (!_eventfd.clear()) return false; if (!_selectInterrupt->clear()) return false;
_sockfd = SocketConnect::connect(host, port, errMsg, isCancellationRequested); _sockfd = SocketConnect::connect(host, port, errMsg, isCancellationRequested);
return _sockfd != -1; return _sockfd != -1;
@ -173,24 +176,9 @@ namespace ix
#endif #endif
} }
bool Socket::init() bool Socket::init(std::string& errorMsg)
{ {
#ifdef _WIN32 return _selectInterrupt->init(errorMsg);
INT rc;
WSADATA wsaData;
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
return rc != 0;
#else
return true;
#endif
}
void Socket::cleanup()
{
#ifdef _WIN32
WSACleanup();
#endif
} }
bool Socket::writeBytes(const std::string& str, bool Socket::writeBytes(const std::string& str,

View File

@ -23,6 +23,8 @@ typedef SSIZE_T ssize_t;
namespace ix namespace ix
{ {
class SelectInterrupt;
enum PollResultType enum PollResultType
{ {
PollResultType_ReadyForRead = 0, PollResultType_ReadyForRead = 0,
@ -38,6 +40,7 @@ namespace ix
Socket(int fd = -1); Socket(int fd = -1);
virtual ~Socket(); virtual ~Socket();
bool init(std::string& errorMsg);
void configure(); void configure();
@ -72,8 +75,6 @@ namespace ix
const CancellationRequest& isCancellationRequested); const CancellationRequest& isCancellationRequested);
static int getErrno(); static int getErrno();
static bool init(); // Required on Windows to initialize WinSocket
static void cleanup(); // Required on Windows to cleanup WinSocket
// Used as special codes for pipe communication // Used as special codes for pipe communication
static const uint64_t kSendRequest; static const uint64_t kSendRequest;
@ -93,6 +94,6 @@ namespace ix
std::vector<uint8_t> _readBuffer; std::vector<uint8_t> _readBuffer;
static constexpr size_t kChunkSize = 1 << 15; static constexpr size_t kChunkSize = 1 << 15;
EventFd _eventfd; std::shared_ptr<SelectInterrupt> _selectInterrupt;
}; };
} }

View File

@ -20,23 +20,45 @@ namespace ix
std::string& errorMsg) std::string& errorMsg)
{ {
errorMsg.clear(); errorMsg.clear();
std::shared_ptr<Socket> socket;
if (!tls) if (!tls)
{ {
return std::make_shared<Socket>(); socket = std::make_shared<Socket>();
} }
else else
{ {
#ifdef IXWEBSOCKET_USE_TLS #ifdef IXWEBSOCKET_USE_TLS
# ifdef __APPLE__ # ifdef __APPLE__
return std::make_shared<SocketAppleSSL>(); socket = std::make_shared<SocketAppleSSL>();
# else # else
return std::make_shared<SocketOpenSSL>(); socket = std::make_shared<SocketOpenSSL>();
# endif # endif
#else #else
errorMsg = "TLS support is not enabled on this platform."; errorMsg = "TLS support is not enabled on this platform.";
return nullptr; return nullptr;
#endif #endif
} }
if (!socket->init(errorMsg))
{
socket.reset();
}
return socket;
}
std::shared_ptr<Socket> createSocket(int fd,
std::string& errorMsg)
{
errorMsg.clear();
std::shared_ptr<Socket> socket = std::make_shared<Socket>(fd);
if (!socket->init(errorMsg))
{
socket.reset();
}
return socket;
} }
} }

View File

@ -14,4 +14,7 @@ namespace ix
class Socket; class Socket;
std::shared_ptr<Socket> createSocket(bool tls, std::shared_ptr<Socket> createSocket(bool tls,
std::string& errorMsg); std::string& errorMsg);
std::shared_ptr<Socket> createSocket(int fd,
std::string& errorMsg);
} }

View File

@ -123,8 +123,13 @@ namespace ix
// Server // Server
WebSocketInitResult WebSocketTransport::connectToSocket(int fd, int timeoutSecs) WebSocketInitResult WebSocketTransport::connectToSocket(int fd, int timeoutSecs)
{ {
_socket.reset(); std::string errorMsg;
_socket = std::make_shared<Socket>(fd); _socket = createSocket(fd, errorMsg);
if (!_socket)
{
return WebSocketInitResult(false, 0, errorMsg);
}
WebSocketHandshake webSocketHandshake(_requestInitCancellation, WebSocketHandshake webSocketHandshake(_requestInitCancellation,
_socket, _socket,

View File

@ -5,17 +5,10 @@
*/ */
#include <iostream> #include <iostream>
#include <ixwebsocket/IXSocketFactory.h>
#include <ixwebsocket/IXSocket.h> #include <ixwebsocket/IXSocket.h>
#include <ixwebsocket/IXCancellationRequest.h> #include <ixwebsocket/IXCancellationRequest.h>
#if defined(__APPLE__) or defined(__linux__)
# ifdef __APPLE__
# include <ixwebsocket/IXSocketAppleSSL.h>
# else
# include <ixwebsocket/IXSocketOpenSSL.h>
# endif
#endif
#include "IXTest.h" #include "IXTest.h"
#include "catch.hpp" #include "catch.hpp"
#include <string.h> #include <string.h>
@ -63,7 +56,9 @@ TEST_CASE("socket", "[socket]")
{ {
SECTION("Connect to google HTTP server. Send GET request without header. Should return 200") SECTION("Connect to google HTTP server. Send GET request without header. Should return 200")
{ {
std::shared_ptr<Socket> socket(new Socket); std::string errMsg;
bool tls = false;
std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
std::string host("www.google.com"); std::string host("www.google.com");
int port = 80; int port = 80;
@ -82,11 +77,9 @@ TEST_CASE("socket", "[socket]")
#if defined(__APPLE__) or defined(__linux__) #if defined(__APPLE__) or defined(__linux__)
SECTION("Connect to google HTTPS server. Send GET request without header. Should return 200") SECTION("Connect to google HTTPS server. Send GET request without header. Should return 200")
{ {
# ifdef __APPLE__ std::string errMsg;
std::shared_ptr<Socket> socket = std::make_shared<SocketAppleSSL>(); bool tls = true;
# else std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
std::shared_ptr<Socket> socket = std::make_shared<SocketOpenSSL>();
# endif
std::string host("www.google.com"); std::string host("www.google.com");
int port = 443; int port = 443;
std::string request("GET / HTTP/1.1\r\n\r\n"); std::string request("GET / HTTP/1.1\r\n\r\n");

View File

@ -8,6 +8,7 @@
#include <ixwebsocket/IXSocket.h> #include <ixwebsocket/IXSocket.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 "IXTest.h"
@ -79,17 +80,18 @@ TEST_CASE("Websocket_server", "[websocket_server]")
ix::WebSocketServer server(port); ix::WebSocketServer server(port);
REQUIRE(startServer(server)); REQUIRE(startServer(server));
Socket socket;
std::string host("localhost");
std::string errMsg; std::string errMsg;
bool tls = false;
std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
std::string host("localhost");
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);
auto lineResult = socket.readLine(isCancellationRequested); auto lineResult = socket->readLine(isCancellationRequested);
auto lineValid = lineResult.first; auto lineValid = lineResult.first;
auto line = lineResult.second; auto line = lineResult.second;
@ -111,20 +113,21 @@ TEST_CASE("Websocket_server", "[websocket_server]")
ix::WebSocketServer server(port); ix::WebSocketServer server(port);
REQUIRE(startServer(server)); REQUIRE(startServer(server));
Socket socket;
std::string host("localhost");
std::string errMsg; std::string errMsg;
bool tls = false;
std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
std::string host("localhost");
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);
Logger() << "writeBytes"; Logger() << "writeBytes";
socket.writeBytes("GET /\r\n", isCancellationRequested); socket->writeBytes("GET /\r\n", isCancellationRequested);
auto lineResult = socket.readLine(isCancellationRequested); auto lineResult = socket->readLine(isCancellationRequested);
auto lineValid = lineResult.first; auto lineValid = lineResult.first;
auto line = lineResult.second; auto line = lineResult.second;
@ -146,24 +149,25 @@ TEST_CASE("Websocket_server", "[websocket_server]")
ix::WebSocketServer server(port); ix::WebSocketServer server(port);
REQUIRE(startServer(server)); REQUIRE(startServer(server));
Socket socket;
std::string host("localhost");
std::string errMsg; std::string errMsg;
bool tls = false;
std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
std::string host("localhost");
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);
socket.writeBytes("GET / HTTP/1.1\r\n" socket->writeBytes("GET / HTTP/1.1\r\n"
"Upgrade: websocket\r\n" "Upgrade: websocket\r\n"
"Sec-WebSocket-Version: 13\r\n" "Sec-WebSocket-Version: 13\r\n"
"Sec-WebSocket-Key: foobar\r\n" "Sec-WebSocket-Key: foobar\r\n"
"\r\n", "\r\n",
isCancellationRequested); isCancellationRequested);
auto lineResult = socket.readLine(isCancellationRequested); auto lineResult = socket->readLine(isCancellationRequested);
auto lineValid = lineResult.first; auto lineValid = lineResult.first;
auto line = lineResult.second; auto line = lineResult.second;

View File

@ -78,7 +78,7 @@ shutil.copy(os.path.join(
'bin', 'bin',
'zlib.dll'), '.') 'zlib.dll'), '.')
lldb = "lldb --batch -o 'run' -k 'thread backtrace all' -k 'quit 1'" # lldb = "lldb --batch -o 'run' -k 'thread backtrace all' -k 'quit 1'"
lldb = "" # Disabled for now lldb = "" # Disabled for now
testCommand = '{} {} {}'.format(lldb, testBinary, os.getenv('TEST', '')) testCommand = '{} {} {}'.format(lldb, testBinary, os.getenv('TEST', ''))
ret = os.system(testCommand) ret = os.system(testCommand)

View File

@ -11,10 +11,6 @@
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
ix::Socket::init(); // for Windows
int result = Catch::Session().run(argc, argv); int result = Catch::Session().run(argc, argv);
ix::Socket::cleanup(); // for Windows
return result; return result;
} }

View File

@ -92,12 +92,9 @@ int main(int argc, char** argv)
CLI11_PARSE(app, argc, argv); CLI11_PARSE(app, argc, argv);
ix::Socket::init();
// pid file handling
if (app.got_subcommand("transfer")) if (app.got_subcommand("transfer"))
{ {
// pid file handling
if (!pidfile.empty()) if (!pidfile.empty())
{ {
unlink(pidfile.c_str()); unlink(pidfile.c_str());

View File

@ -153,7 +153,6 @@ namespace ix
int ws_connect_main(const std::string& url) int ws_connect_main(const std::string& url)
{ {
Socket::init();
interactiveMain(url); interactiveMain(url);
return 0; return 0;
} }

View File

@ -254,7 +254,6 @@ namespace ix
int ws_receive_main(const std::string& url, int ws_receive_main(const std::string& url,
bool enablePerMessageDeflate) bool enablePerMessageDeflate)
{ {
Socket::init();
wsReceive(url, enablePerMessageDeflate); wsReceive(url, enablePerMessageDeflate);
return 0; return 0;
} }

View File

@ -298,7 +298,6 @@ namespace ix
bool throttle = false; bool throttle = false;
bool enablePerMessageDeflate = false; bool enablePerMessageDeflate = false;
Socket::init();
wsSend(url, path, enablePerMessageDeflate, throttle); wsSend(url, path, enablePerMessageDeflate, throttle);
return 0; return 0;
} }