select interrupt cleanup
This commit is contained in:
		@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										46
									
								
								ixwebsocket/IXSelectInterrupt.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								ixwebsocket/IXSelectInterrupt.cpp
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										28
									
								
								ixwebsocket/IXSelectInterrupt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								ixwebsocket/IXSelectInterrupt.h
									
									
									
									
									
										Normal 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();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								ixwebsocket/IXSelectInterruptEventFd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								ixwebsocket/IXSelectInterruptEventFd.h
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										25
									
								
								ixwebsocket/IXSelectInterruptFactory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								ixwebsocket/IXSelectInterruptFactory.cpp
									
									
									
									
									
										Normal 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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								ixwebsocket/IXSelectInterruptFactory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								ixwebsocket/IXSelectInterruptFactory.h
									
									
									
									
									
										Normal 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();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										108
									
								
								ixwebsocket/IXSelectInterruptPipe.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								ixwebsocket/IXSelectInterruptPipe.cpp
									
									
									
									
									
										Normal 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];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user