Compare commits

..

4 Commits

Author SHA1 Message Date
753fc845ac Fix for windows (#50) 2019-05-06 09:13:42 -07:00
5dbc00bbfe doc: add reference to the conan file built at https://github.com/Zinnion/conan-IXWebSocket 2019-05-01 21:31:32 -07:00
14ec8522ef remove un-needed _backgroundThreadRunning variable 2019-05-01 11:09:25 -07:00
0c2d1c22bc Make AutomaticReconnection optional (#47)
* unittest pass + commands behave as expected

* cleanup
2019-04-29 21:12:34 -07:00
10 changed files with 35 additions and 25 deletions

View File

@ -199,6 +199,8 @@ make install # will install to /usr/local on Unix, on macOS it is a good idea to
Headers and a static library will be installed to the target dir. Headers and a static library will be installed to the target dir.
A [conan](https://conan.io/) file is available at [conan-IXWebSocket](https://github.com/Zinnion/conan-IXWebSocket).
There is a unittest which can be executed by typing `make test`. There is a unittest which can be executed by typing `make test`.
There is a Dockerfile for running some code on Linux. To use docker-compose you must make a docker container first. There is a Dockerfile for running some code on Linux. To use docker-compose you must make a docker container first.

View File

@ -35,7 +35,6 @@ namespace ix
_activeJobs.erase(_id); _activeJobs.erase(_id);
} }
// we want hostname to be copied, not passed as a const reference
struct addrinfo* DNSLookup::getAddrInfo(const std::string& hostname, struct addrinfo* DNSLookup::getAddrInfo(const std::string& hostname,
int port, int port,
std::string& errMsg) std::string& errMsg)

View File

@ -196,6 +196,25 @@ namespace ix
#endif #endif
} }
bool Socket::isWaitNeeded()
{
int err = getErrno();
if (err == EWOULDBLOCK || err == EAGAIN)
{
return true;
}
#ifdef _WIN32
if (err == WSAEWOULDBLOCK || err == WSATRY_AGAIN)
{
return true;
}
#endif
return false;
}
void Socket::closeSocket(int fd) void Socket::closeSocket(int fd)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -228,8 +247,7 @@ namespace ix
return ret == len; return ret == len;
} }
// There is possibly something to be writen, try again // There is possibly something to be writen, try again
else if (ret < 0 && (getErrno() == EWOULDBLOCK || else if (ret < 0 && Socket::isWaitNeeded())
getErrno() == EAGAIN))
{ {
continue; continue;
} }
@ -257,8 +275,7 @@ namespace ix
return true; return true;
} }
// There is possibly something to be read, try again // There is possibly something to be read, try again
else if (ret < 0 && (getErrno() == EWOULDBLOCK || else if (ret < 0 && Socket::isWaitNeeded())
getErrno() == EAGAIN))
{ {
// Wait with a 1ms timeout until the socket is ready to read. // Wait with a 1ms timeout until the socket is ready to read.
// This way we are not busy looping // This way we are not busy looping
@ -317,13 +334,12 @@ namespace ix
size_t size = std::min(kChunkSize, length - output.size()); size_t size = std::min(kChunkSize, length - output.size());
ssize_t ret = recv((char*)&_readBuffer[0], size); ssize_t ret = recv((char*)&_readBuffer[0], size);
if (ret <= 0 && (getErrno() != EWOULDBLOCK && if (ret <= 0 && !Socket::isWaitNeeded())
getErrno() != EAGAIN))
{ {
// Error // Error
return std::make_pair(false, std::string()); return std::make_pair(false, std::string());
} }
else if (ret > 0) else
{ {
output.insert(output.end(), output.insert(output.end(),
_readBuffer.begin(), _readBuffer.begin(),

View File

@ -41,8 +41,6 @@ namespace ix
virtual ~Socket(); virtual ~Socket();
bool init(std::string& errorMsg); bool init(std::string& errorMsg);
void configure();
// Functions to check whether there is activity on the socket // Functions to check whether there is activity on the socket
PollResultType poll(int timeoutSecs = kDefaultPollTimeout); PollResultType poll(int timeoutSecs = kDefaultPollTimeout);
bool wakeUpFromPoll(uint8_t wakeUpCode); bool wakeUpFromPoll(uint8_t wakeUpCode);
@ -76,6 +74,7 @@ namespace ix
const CancellationRequest& isCancellationRequested); const CancellationRequest& isCancellationRequested);
static int getErrno(); static int getErrno();
static bool isWaitNeeded();
// Used as special codes for pipe communication // Used as special codes for pipe communication
static const uint64_t kSendRequest; static const uint64_t kSendRequest;

View File

@ -247,7 +247,7 @@ namespace ix
if ((clientFd = accept(_serverFd, (struct sockaddr *)&client, &addressLen)) < 0) if ((clientFd = accept(_serverFd, (struct sockaddr *)&client, &addressLen)) < 0)
{ {
if (Socket::getErrno() != EWOULDBLOCK) if (!Socket::isWaitNeeded())
{ {
// FIXME: that error should be propagated // FIXME: that error should be propagated
std::stringstream ss; std::stringstream ss;

View File

@ -270,7 +270,7 @@ namespace ix
_onMessageCallback(WebSocket_MessageType_Error, "", 0, _onMessageCallback(WebSocket_MessageType_Error, "", 0,
connectErr, WebSocketOpenInfo(), connectErr, WebSocketOpenInfo(),
WebSocketCloseInfo()); WebSocketCloseInfo());
// Only sleep if we aren't in the middle of stopping // Only sleep if we aren't in the middle of stopping
if (!_stop) if (!_stop)
{ {
@ -340,9 +340,7 @@ namespace ix
WebSocket::invokeTrafficTrackerCallback(msg.size(), true); WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
}); });
// 4. In blocking mode, getting out of this function is triggered by // If we aren't trying to reconnect automatically, exit if we aren't connected
// an explicit disconnection from the callback, or by the remote end
// closing the connection, ie isConnected() == false.
if (!isConnected() && !_automaticReconnection) return; if (!isConnected() && !_automaticReconnection) return;
} }
} }

View File

@ -154,7 +154,6 @@ namespace ix
static OnTrafficTrackerCallback _onTrafficTrackerCallback; static OnTrafficTrackerCallback _onTrafficTrackerCallback;
std::atomic<bool> _stop; std::atomic<bool> _stop;
std::atomic<bool> _backgroundThreadRunning;
std::atomic<bool> _automaticReconnection; std::atomic<bool> _automaticReconnection;
std::thread _thread; std::thread _thread;
std::mutex _writeMutex; std::mutex _writeMutex;

View File

@ -296,8 +296,7 @@ namespace ix
{ {
ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size()); ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size());
if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK || if (ret < 0 && Socket::isWaitNeeded())
_socket->getErrno() == EAGAIN))
{ {
break; break;
} }
@ -553,7 +552,7 @@ namespace ix
// Get the reason. // Get the reason.
std::string reason(_rxbuf.begin()+ws.header_size + 2, std::string reason(_rxbuf.begin()+ws.header_size + 2,
_rxbuf.begin()+ws.header_size + (size_t) ws.N); _rxbuf.begin()+ws.header_size + (size_t) ws.N);
bool remote = true; bool remote = true;
close(code, reason, _rxbuf.size(), remote); close(code, reason, _rxbuf.size(), remote);
@ -844,8 +843,7 @@ namespace ix
{ {
ssize_t ret = _socket->send((char*)&_txbuf[0], _txbuf.size()); ssize_t ret = _socket->send((char*)&_txbuf[0], _txbuf.size());
if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK || if (ret < 0 && Socket::isWaitNeeded())
_socket->getErrno() == EAGAIN))
{ {
break; break;
} }

View File

@ -8,12 +8,11 @@ project (ixwebsocket_unittest)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../third_party/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH}) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../third_party/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH})
find_package(Sanitizers) find_package(Sanitizers)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
set(CMAKE_LD_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
set (CMAKE_CXX_STANDARD 14) set (CMAKE_CXX_STANDARD 14)
if (NOT WIN32) if (NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
set(CMAKE_LD_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
option(USE_TLS "Add TLS support" ON) option(USE_TLS "Add TLS support" ON)
endif() endif()

View File

@ -41,7 +41,7 @@ namespace ix
{ {
if (!redisClient.publish(channel, message, errMsg)) if (!redisClient.publish(channel, message, errMsg))
{ {
std::cerr << "Error publishing to channel " << channel std::cerr << "Error publishing to channel " << channel
<< "error: " << errMsg << "error: " << errMsg
<< std::endl; << std::endl;
return 1; return 1;