Compare commits
	
		
			34 Commits
		
	
	
		
			v1.2.0
			...
			feature/ht
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					73f4ba7ee7 | ||
| 
						 | 
					6f39592c7b | ||
| 
						 | 
					38200fc5d7 | ||
| 
						 | 
					285c12775a | ||
| 
						 | 
					6d56f7223a | ||
| 
						 | 
					1db3568375 | ||
| 
						 | 
					0a752e7d18 | ||
| 
						 | 
					7c2bc2cf7e | ||
| 
						 | 
					79f601ac65 | ||
| 
						 | 
					069eccf415 | ||
| 
						 | 
					b563541b14 | ||
| 
						 | 
					3bcd6f97a6 | ||
| 
						 | 
					c04bc3cdfc | ||
| 
						 | 
					846f0c680a | ||
| 
						 | 
					c552a03ef0 | ||
| 
						 | 
					0f175143c9 | ||
| 
						 | 
					85569cb401 | ||
| 
						 | 
					bd854553d4 | ||
| 
						 | 
					38c57e1ed2 | ||
| 
						 | 
					26cc5025fb | ||
| 
						 | 
					806cf39efc | ||
| 
						 | 
					daaa7ec704 | ||
| 
						 | 
					3cffc6f9a5 | ||
| 
						 | 
					f8b1a03ee6 | ||
| 
						 | 
					a7ff3c41a1 | ||
| 
						 | 
					78dbba5521 | ||
| 
						 | 
					b211bdbe38 | ||
| 
						 | 
					a0a53ab986 | ||
| 
						 | 
					8d819053ff | ||
| 
						 | 
					e20ddc2a08 | ||
| 
						 | 
					c415ba9427 | ||
| 
						 | 
					0b7c3ec235 | ||
| 
						 | 
					29c96f287f | ||
| 
						 | 
					2a17cad1bf | 
							
								
								
									
										31
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -1,31 +0,0 @@
 | 
				
			|||||||
FROM debian:stretch
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ENV DEBIAN_FRONTEND noninteractive
 | 
					 | 
				
			||||||
RUN apt-get update 
 | 
					 | 
				
			||||||
RUN apt-get -y install g++ 
 | 
					 | 
				
			||||||
RUN apt-get -y install libssl-dev
 | 
					 | 
				
			||||||
RUN apt-get -y install gdb
 | 
					 | 
				
			||||||
RUN apt-get -y install screen
 | 
					 | 
				
			||||||
RUN apt-get -y install procps
 | 
					 | 
				
			||||||
RUN apt-get -y install lsof
 | 
					 | 
				
			||||||
RUN apt-get -y install libz-dev
 | 
					 | 
				
			||||||
RUN apt-get -y install vim
 | 
					 | 
				
			||||||
RUN apt-get -y install make
 | 
					 | 
				
			||||||
RUN apt-get -y install cmake
 | 
					 | 
				
			||||||
RUN apt-get -y install curl
 | 
					 | 
				
			||||||
RUN apt-get -y install python
 | 
					 | 
				
			||||||
RUN apt-get -y install netcat
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# debian strech cmake is too old for building with Docker
 | 
					 | 
				
			||||||
COPY makefile .
 | 
					 | 
				
			||||||
RUN ["make", "install_cmake_for_linux"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
COPY . .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ARG CMAKE_BIN_PATH=/tmp/cmake/cmake-3.14.0-rc4-Linux-x86_64/bin
 | 
					 | 
				
			||||||
ENV PATH="${CMAKE_BIN_PATH}:${PATH}"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# RUN ["make"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXPOSE 8765
 | 
					 | 
				
			||||||
CMD ["/ws/ws", "transfer", "--port", "8765", "--host", "0.0.0.0"]
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								Dockerfile
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								Dockerfile
									
									
									
									
									
										Symbolic link
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					docker/Dockerfile.debian
 | 
				
			||||||
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							@@ -11,6 +11,7 @@ communication channels over a single TCP connection. *IXWebSocket* is a C++ libr
 | 
				
			|||||||
* iOS
 | 
					* iOS
 | 
				
			||||||
* Linux
 | 
					* Linux
 | 
				
			||||||
* Android 
 | 
					* Android 
 | 
				
			||||||
 | 
					* Windows (no TLS support yet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Examples
 | 
					## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,10 +77,7 @@ server.setOnConnectionCallback(
 | 
				
			|||||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
					                if (messageType == ix::WebSocket_MessageType_Open)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    std::cerr << "New connection" << std::endl;
 | 
					                    std::cerr << "New connection" << std::endl;
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    // The uri the client did connect to.
 | 
					 | 
				
			||||||
                    std::cerr << "Uri: " << openInfo.uri << std::endl;
 | 
					                    std::cerr << "Uri: " << openInfo.uri << std::endl;
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    std::cerr << "Headers:" << std::endl;
 | 
					                    std::cerr << "Headers:" << std::endl;
 | 
				
			||||||
                    for (auto it : openInfo.headers)
 | 
					                    for (auto it : openInfo.headers)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@@ -180,13 +178,6 @@ CMakefiles for the library and the examples are available. This library has few
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
There is a Dockerfile for running some code on Linux, and a unittest which can be executed by typing `make test`.
 | 
					There is a Dockerfile for running some code on Linux, and a unittest which can be executed by typing `make test`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can build and install the ws command line tool with Homebrew.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
brew create --cmake https://github.com/machinezone/IXWebSocket/archive/v1.1.0.tar.gz
 | 
					 | 
				
			||||||
brew install IXWebSocket
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Implementation details
 | 
					## Implementation details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Per Message Deflate compression.
 | 
					### Per Message Deflate compression.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								docker/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								docker/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					FROM debian:stretch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# RUN yum install -y gcc-c++ make cmake openssl-devel gdb
 | 
				
			||||||
 | 
					ENV DEBIAN_FRONTEND noninteractive
 | 
				
			||||||
 | 
					RUN apt-get update 
 | 
				
			||||||
 | 
					RUN apt-get -y install g++ 
 | 
				
			||||||
 | 
					RUN apt-get -y install libssl-dev
 | 
				
			||||||
 | 
					RUN apt-get -y install gdb
 | 
				
			||||||
 | 
					RUN apt-get -y install screen
 | 
				
			||||||
 | 
					RUN apt-get -y install procps
 | 
				
			||||||
 | 
					RUN apt-get -y install lsof
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR examples/ws_connect
 | 
				
			||||||
 | 
					RUN ["sh", "build_linux.sh"]
 | 
				
			||||||
							
								
								
									
										11
									
								
								docker/Dockerfile.alpine
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								docker/Dockerfile.alpine
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					FROM alpine:3.8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN apk add --no-cache g++ musl-dev make cmake openssl-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR examples/ws_connect
 | 
				
			||||||
 | 
					RUN ["sh", "build_linux.sh"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXPOSE 8765
 | 
				
			||||||
 | 
					CMD ["ws_connect"]
 | 
				
			||||||
							
								
								
									
										11
									
								
								docker/Dockerfile.centos
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								docker/Dockerfile.centos
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					FROM alpine:3.8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN apk add --no-cache g++ musl-dev make cmake openssl-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR examples/ws_connect
 | 
				
			||||||
 | 
					RUN ["sh", "build_linux.sh"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXPOSE 8765
 | 
				
			||||||
 | 
					CMD ["ws_connect"]
 | 
				
			||||||
							
								
								
									
										22
									
								
								docker/Dockerfile.debian
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								docker/Dockerfile.debian
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					FROM debian:stretch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENV DEBIAN_FRONTEND noninteractive
 | 
				
			||||||
 | 
					RUN apt-get update 
 | 
				
			||||||
 | 
					RUN apt-get -y install g++ 
 | 
				
			||||||
 | 
					RUN apt-get -y install libssl-dev
 | 
				
			||||||
 | 
					RUN apt-get -y install gdb
 | 
				
			||||||
 | 
					RUN apt-get -y install screen
 | 
				
			||||||
 | 
					RUN apt-get -y install procps
 | 
				
			||||||
 | 
					RUN apt-get -y install lsof
 | 
				
			||||||
 | 
					RUN apt-get -y install libz-dev
 | 
				
			||||||
 | 
					RUN apt-get -y install vim
 | 
				
			||||||
 | 
					RUN apt-get -y install make
 | 
				
			||||||
 | 
					RUN apt-get -y install cmake
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR ws
 | 
				
			||||||
 | 
					RUN ["sh", "docker_build.sh"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXPOSE 8765
 | 
				
			||||||
 | 
					CMD ["/ws/ws", "transfer", "8765"]
 | 
				
			||||||
							
								
								
									
										8
									
								
								docker/Dockerfile.gcc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docker/Dockerfile.gcc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					FROM gcc:8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# RUN yum install -y gcc-c++ make cmake openssl-devel gdb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY . .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR examples/ws_connect
 | 
				
			||||||
 | 
					RUN ["sh", "build_linux.sh"]
 | 
				
			||||||
@@ -17,8 +17,6 @@
 | 
				
			|||||||
// cf Android/Kernel table here
 | 
					// cf Android/Kernel table here
 | 
				
			||||||
// https://android.stackexchange.com/questions/51651/which-android-runs-which-linux-kernel
 | 
					// https://android.stackexchange.com/questions/51651/which-android-runs-which-linux-kernel
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// On macOS we use UNIX pipes to wake up select.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXEventFd.h"
 | 
					#include "IXEventFd.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,29 +24,17 @@
 | 
				
			|||||||
# include <sys/eventfd.h>
 | 
					# include <sys/eventfd.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _WIN32
 | 
				
			||||||
#include <unistd.h> // for write
 | 
					#include <unistd.h> // for write
 | 
				
			||||||
#include <fcntl.h>
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // File descriptor at index 0 in _fildes is the read end of the pipe
 | 
					    EventFd::EventFd() :
 | 
				
			||||||
    // File descriptor at index 1 in _fildes is the write end of the pipe
 | 
					        _eventfd(-1)
 | 
				
			||||||
    const int EventFd::kPipeReadIndex = 0;
 | 
					 | 
				
			||||||
    const int EventFd::kPipeWriteIndex = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    EventFd::EventFd()
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
#ifdef __linux__
 | 
					#ifdef __linux__
 | 
				
			||||||
        _eventfd = -1;
 | 
					 | 
				
			||||||
        _eventfd = eventfd(0, 0);
 | 
					        _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
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -56,43 +42,22 @@ namespace ix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
#ifdef __linux__
 | 
					#ifdef __linux__
 | 
				
			||||||
        ::close(_eventfd);
 | 
					        ::close(_eventfd);
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
        ::close(_fildes[kPipeReadIndex]);
 | 
					 | 
				
			||||||
        ::close(_fildes[kPipeWriteIndex]);
 | 
					 | 
				
			||||||
        _fildes[kPipeReadIndex] = -1;
 | 
					 | 
				
			||||||
        _fildes[kPipeWriteIndex] = -1;
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool EventFd::notify(uint64_t value)
 | 
					    bool EventFd::notify()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        int fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(__linux__)
 | 
					#if defined(__linux__)
 | 
				
			||||||
        fd = _eventfd;
 | 
					        if (_eventfd == -1) return false;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
        fd = _fildes[kPipeWriteIndex];
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (fd == -1) return false;
 | 
					        // select will wake up when a non-zero value is written to our eventfd
 | 
				
			||||||
 | 
					        uint64_t value = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // we should write 8 bytes for an uint64_t
 | 
					        // we should write 8 bytes for an uint64_t
 | 
				
			||||||
        return write(fd, &value, sizeof(value)) == 8;
 | 
					        return write(_eventfd, &value, sizeof(value)) == 8;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO: return max uint64_t for errors ?
 | 
					 | 
				
			||||||
    uint64_t EventFd::read()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        int fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(__linux__)
 | 
					 | 
				
			||||||
        fd = _eventfd;
 | 
					 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
        fd = _fildes[kPipeReadIndex];
 | 
					        return true;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        uint64_t value = 0;
 | 
					 | 
				
			||||||
        ::read(fd, &value, sizeof(value));
 | 
					 | 
				
			||||||
        return value;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool EventFd::clear()
 | 
					    bool EventFd::clear()
 | 
				
			||||||
@@ -112,10 +77,6 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    int EventFd::getFd()
 | 
					    int EventFd::getFd()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
#if defined(__linux__)
 | 
					 | 
				
			||||||
        return _eventfd;
 | 
					        return _eventfd;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
        return _fildes[kPipeReadIndex];
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    class EventFd {
 | 
					    class EventFd {
 | 
				
			||||||
@@ -15,23 +13,11 @@ namespace ix
 | 
				
			|||||||
        EventFd();
 | 
					        EventFd();
 | 
				
			||||||
        virtual ~EventFd();
 | 
					        virtual ~EventFd();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool notify(uint64_t value);
 | 
					        bool notify();
 | 
				
			||||||
        bool clear();
 | 
					        bool clear();
 | 
				
			||||||
        uint64_t read();
 | 
					 | 
				
			||||||
        int getFd();
 | 
					        int getFd();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
#if defined(__linux__)
 | 
					 | 
				
			||||||
        int _eventfd;
 | 
					        int _eventfd;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
        // Store file descriptors used by the communication pipe. Communication
 | 
					 | 
				
			||||||
        // happens between a control thread and a background thread, which is
 | 
					 | 
				
			||||||
        // blocked on select.
 | 
					 | 
				
			||||||
        int _fildes[2];
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Used to identify the read/write idx
 | 
					 | 
				
			||||||
        static const int kPipeReadIndex;
 | 
					 | 
				
			||||||
        static const int kPipeWriteIndex;
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -231,17 +231,19 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            payload.reserve(contentLength);
 | 
					            payload.reserve(contentLength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto chunkResult = _socket->readBytes(contentLength,
 | 
					            // FIXME: very inefficient way to read bytes, but it works...
 | 
				
			||||||
                                                  args.onProgressCallback,
 | 
					            for (int i = 0; i < contentLength; ++i)
 | 
				
			||||||
                                                  isCancellationRequested);
 | 
					 | 
				
			||||||
            if (!chunkResult.first)
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                errorMsg = "Cannot read chunk";
 | 
					                char c;
 | 
				
			||||||
                return std::make_tuple(code, HttpErrorCode_ChunkReadError,
 | 
					                if (!_socket->readByte(&c, isCancellationRequested))
 | 
				
			||||||
                                       headers, payload, errorMsg,
 | 
					                {
 | 
				
			||||||
 | 
					                    return std::make_tuple(code, HttpErrorCode_ReadError,
 | 
				
			||||||
 | 
					                                           headers, payload, "Cannot read byte",
 | 
				
			||||||
                                           uploadSize, downloadSize);
 | 
					                                           uploadSize, downloadSize);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            payload += chunkResult.second;
 | 
					
 | 
				
			||||||
 | 
					                payload += c;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (headers.find("Transfer-Encoding") != headers.end() &&
 | 
					        else if (headers.find("Transfer-Encoding") != headers.end() &&
 | 
				
			||||||
                 headers["Transfer-Encoding"] == "chunked")
 | 
					                 headers["Transfer-Encoding"] == "chunked")
 | 
				
			||||||
@@ -275,20 +277,22 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                payload.reserve(payload.size() + chunkSize);
 | 
					                payload.reserve(payload.size() + chunkSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Read a chunk
 | 
					                // Read another line
 | 
				
			||||||
                auto chunkResult = _socket->readBytes(chunkSize,
 | 
					
 | 
				
			||||||
                                                      args.onProgressCallback,
 | 
					                for (uint64_t i = 0; i < chunkSize; ++i)
 | 
				
			||||||
                                                      isCancellationRequested);
 | 
					 | 
				
			||||||
                if (!chunkResult.first)
 | 
					 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    errorMsg = "Cannot read chunk";
 | 
					                    char c;
 | 
				
			||||||
 | 
					                    if (!_socket->readByte(&c, isCancellationRequested))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        errorMsg = "Cannot read byte";
 | 
				
			||||||
                        return std::make_tuple(code, HttpErrorCode_ChunkReadError,
 | 
					                        return std::make_tuple(code, HttpErrorCode_ChunkReadError,
 | 
				
			||||||
                                               headers, payload, errorMsg,
 | 
					                                               headers, payload, errorMsg,
 | 
				
			||||||
                                               uploadSize, downloadSize);
 | 
					                                               uploadSize, downloadSize);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                payload += chunkResult.second;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Read the line that terminates the chunk (\r\n)
 | 
					                    payload += c;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                lineResult = _socket->readLine(isCancellationRequested);
 | 
					                lineResult = _socket->readLine(isCancellationRequested);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!lineResult.first)
 | 
					                if (!lineResult.first)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,7 +61,6 @@ namespace ix
 | 
				
			|||||||
        bool verbose;
 | 
					        bool verbose;
 | 
				
			||||||
        bool compress;
 | 
					        bool compress;
 | 
				
			||||||
        Logger logger;
 | 
					        Logger logger;
 | 
				
			||||||
        OnProgressCallback onProgressCallback;
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class HttpClient {
 | 
					    class HttpClient {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,14 +23,11 @@ namespace ix
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    const int Socket::kDefaultPollNoTimeout = -1; // No poll timeout by default
 | 
					    const int Socket::kDefaultPollNoTimeout = -1; // No poll timeout by default
 | 
				
			||||||
    const int Socket::kDefaultPollTimeout = kDefaultPollNoTimeout;
 | 
					    const int Socket::kDefaultPollTimeout = kDefaultPollNoTimeout;
 | 
				
			||||||
    const uint64_t Socket::kSendRequest = 1;
 | 
					 | 
				
			||||||
    const uint64_t Socket::kCloseRequest = 2;
 | 
					 | 
				
			||||||
    constexpr size_t Socket::kChunkSize;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Socket::Socket(int fd) :
 | 
					    Socket::Socket(int fd) :
 | 
				
			||||||
        _sockfd(fd)
 | 
					        _sockfd(fd)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ;
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Socket::~Socket()
 | 
					    Socket::~Socket()
 | 
				
			||||||
@@ -42,37 +39,25 @@ namespace ix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if (_sockfd == -1)
 | 
					        if (_sockfd == -1)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (onPollCallback) onPollCallback(PollResultType_Error);
 | 
					            onPollCallback(PollResultType_Error);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        PollResultType pollResult = select(timeoutSecs, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (onPollCallback) onPollCallback(pollResult);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PollResultType Socket::select(int timeoutSecs, int timeoutMs)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        fd_set rfds;
 | 
					        fd_set rfds;
 | 
				
			||||||
        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
 | 
					#ifdef __linux__
 | 
				
			||||||
        int eventfd = _eventfd.getFd();
 | 
					        FD_SET(_eventfd.getFd(), &rfds);
 | 
				
			||||||
        if (eventfd != -1)
 | 
					#endif
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            FD_SET(eventfd, &rfds);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct timeval timeout;
 | 
					        struct timeval timeout;
 | 
				
			||||||
        timeout.tv_sec = timeoutSecs;
 | 
					        timeout.tv_sec = timeoutSecs;
 | 
				
			||||||
        timeout.tv_usec = 1000 * timeoutMs;
 | 
					        timeout.tv_usec = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Compute the highest fd.
 | 
					 | 
				
			||||||
        int sockfd = _sockfd;
 | 
					        int sockfd = _sockfd;
 | 
				
			||||||
        int nfds = (std::max)(sockfd, eventfd);
 | 
					        int nfds = (std::max)(sockfd, _eventfd.getFd());
 | 
				
			||||||
 | 
					        int ret = select(nfds + 1, &rfds, nullptr, nullptr,
 | 
				
			||||||
        int ret = ::select(nfds + 1, &rfds, nullptr, nullptr,
 | 
					 | 
				
			||||||
                         (timeoutSecs < 0) ? nullptr : &timeout);
 | 
					                         (timeoutSecs < 0) ? nullptr : &timeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        PollResultType pollResult = PollResultType_ReadyForRead;
 | 
					        PollResultType pollResult = PollResultType_ReadyForRead;
 | 
				
			||||||
@@ -84,27 +69,14 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            pollResult = PollResultType_Timeout;
 | 
					            pollResult = PollResultType_Timeout;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (eventfd != -1 && FD_ISSET(eventfd, &rfds))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            uint64_t value = _eventfd.read();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (value == kSendRequest)
 | 
					        onPollCallback(pollResult);
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                pollResult = PollResultType_SendRequest;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (value == kCloseRequest)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                pollResult = PollResultType_CloseRequest;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return pollResult;
 | 
					    void Socket::wakeUpFromPoll()
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Wake up from poll/select by writing to the pipe which is watched by select
 | 
					 | 
				
			||||||
    bool Socket::wakeUpFromPoll(uint8_t wakeUpCode)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return _eventfd.notify(wakeUpCode);
 | 
					        // this will wake up the thread blocked on select, only needed on Linux
 | 
				
			||||||
 | 
					        _eventfd.notify();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool Socket::connect(const std::string& host,
 | 
					    bool Socket::connect(const std::string& host,
 | 
				
			||||||
@@ -193,6 +165,51 @@ namespace ix
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Socket::readByte(void* buffer,
 | 
				
			||||||
 | 
					                          const CancellationRequest& isCancellationRequested)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        while (true)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (isCancellationRequested()) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ssize_t ret;
 | 
				
			||||||
 | 
					            ret = recv(buffer, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // We read one byte, as needed, all good.
 | 
				
			||||||
 | 
					            if (ret == 1)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // There is possibly something to be read, try again
 | 
				
			||||||
 | 
					            else if (ret < 0 && (getErrno() == EWOULDBLOCK ||
 | 
				
			||||||
 | 
					                                 getErrno() == EAGAIN))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // Wait with a timeout until something is written.
 | 
				
			||||||
 | 
					                // This way we are not busy looping
 | 
				
			||||||
 | 
					                fd_set rfds;
 | 
				
			||||||
 | 
					                struct timeval timeout;
 | 
				
			||||||
 | 
					                timeout.tv_sec = 0;
 | 
				
			||||||
 | 
					                timeout.tv_usec = 1 * 1000; // 1ms timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                FD_ZERO(&rfds);
 | 
				
			||||||
 | 
					                FD_SET(_sockfd, &rfds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (select(_sockfd + 1, &rfds, nullptr, nullptr, &timeout) < 0 &&
 | 
				
			||||||
 | 
					                    (errno == EBADF || errno == EINVAL))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // There was an error during the read, abort
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool Socket::writeBytes(const std::string& str,
 | 
					    bool Socket::writeBytes(const std::string& str,
 | 
				
			||||||
                            const CancellationRequest& isCancellationRequested)
 | 
					                            const CancellationRequest& isCancellationRequested)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -224,43 +241,7 @@ namespace ix
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool Socket::readByte(void* buffer,
 | 
					    std::pair<bool, std::string> Socket::readLine(const CancellationRequest& isCancellationRequested)
 | 
				
			||||||
                          const CancellationRequest& isCancellationRequested)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        while (true)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (isCancellationRequested()) return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            ssize_t ret;
 | 
					 | 
				
			||||||
            ret = recv(buffer, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // We read one byte, as needed, all good.
 | 
					 | 
				
			||||||
            if (ret == 1)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return true;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // There is possibly something to be read, try again
 | 
					 | 
				
			||||||
            else if (ret < 0 && (getErrno() == EWOULDBLOCK ||
 | 
					 | 
				
			||||||
                                 getErrno() == EAGAIN))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // Wait with a timeout until something is ready to read.
 | 
					 | 
				
			||||||
                // This way we are not busy looping
 | 
					 | 
				
			||||||
                int res = select(0, 1);
 | 
					 | 
				
			||||||
                if (res < 0 && (errno == EBADF || errno == EINVAL))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // There was an error during the read, abort
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::pair<bool, std::string> Socket::readLine(
 | 
					 | 
				
			||||||
        const CancellationRequest& isCancellationRequested)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        char c;
 | 
					        char c;
 | 
				
			||||||
        std::string line;
 | 
					        std::string line;
 | 
				
			||||||
@@ -270,8 +251,7 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!readByte(&c, isCancellationRequested))
 | 
					            if (!readByte(&c, isCancellationRequested))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Return what we were able to read
 | 
					                return std::make_pair(false, std::string());
 | 
				
			||||||
                return std::make_pair(false, line);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            line += c;
 | 
					            line += c;
 | 
				
			||||||
@@ -279,46 +259,4 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return std::make_pair(true, line);
 | 
					        return std::make_pair(true, line);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::pair<bool, std::string> Socket::readBytes(
 | 
					 | 
				
			||||||
        size_t length,
 | 
					 | 
				
			||||||
        const OnProgressCallback& onProgressCallback,
 | 
					 | 
				
			||||||
        const CancellationRequest& isCancellationRequested)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (_readBuffer.empty())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            _readBuffer.resize(kChunkSize);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::vector<uint8_t> output;
 | 
					 | 
				
			||||||
        while (output.size() != length)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (isCancellationRequested()) return std::make_pair(false, std::string());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            int size = std::min(kChunkSize, length - output.size());
 | 
					 | 
				
			||||||
            ssize_t ret = recv((char*)&_readBuffer[0], size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (ret <= 0 && (getErrno() != EWOULDBLOCK &&
 | 
					 | 
				
			||||||
                             getErrno() != EAGAIN))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // Error
 | 
					 | 
				
			||||||
                return std::make_pair(false, std::string());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (ret > 0)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                output.insert(output.end(),
 | 
					 | 
				
			||||||
                              _readBuffer.begin(),
 | 
					 | 
				
			||||||
                              _readBuffer.begin() + ret);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (onProgressCallback) onProgressCallback((int) output.size(), (int) length);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Wait with a timeout until something is ready to read.
 | 
					 | 
				
			||||||
            // This way we are not busy looping
 | 
					 | 
				
			||||||
            select(0, 1);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return std::make_pair(true, std::string(output.begin(),
 | 
					 | 
				
			||||||
                                                output.end()));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,16 +10,14 @@
 | 
				
			|||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <vector>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
#include <BaseTsd.h>
 | 
					#include <BaseTsd.h>
 | 
				
			||||||
typedef SSIZE_T ssize_t;
 | 
					typedef SSIZE_T ssize_t;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXCancellationRequest.h"
 | 
					 | 
				
			||||||
#include "IXProgressCallback.h"
 | 
					 | 
				
			||||||
#include "IXEventFd.h"
 | 
					#include "IXEventFd.h"
 | 
				
			||||||
 | 
					#include "IXCancellationRequest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -27,9 +25,7 @@ namespace ix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        PollResultType_ReadyForRead = 0,
 | 
					        PollResultType_ReadyForRead = 0,
 | 
				
			||||||
        PollResultType_Timeout = 1,
 | 
					        PollResultType_Timeout = 1,
 | 
				
			||||||
        PollResultType_Error = 2,
 | 
					        PollResultType_Error = 2
 | 
				
			||||||
        PollResultType_SendRequest = 3,
 | 
					 | 
				
			||||||
        PollResultType_CloseRequest = 4
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Socket {
 | 
					    class Socket {
 | 
				
			||||||
@@ -41,10 +37,9 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        void configure();
 | 
					        void configure();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        PollResultType select(int timeoutSecs, int timeoutMs);
 | 
					 | 
				
			||||||
        virtual void poll(const OnPollCallback& onPollCallback,
 | 
					        virtual void poll(const OnPollCallback& onPollCallback,
 | 
				
			||||||
                          int timeoutSecs = kDefaultPollTimeout);
 | 
					                          int timeoutSecs = kDefaultPollTimeout);
 | 
				
			||||||
        virtual bool wakeUpFromPoll(uint8_t wakeUpCode);
 | 
					        virtual void wakeUpFromPoll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Virtual methods
 | 
					        // Virtual methods
 | 
				
			||||||
        virtual bool connect(const std::string& url,
 | 
					        virtual bool connect(const std::string& url,
 | 
				
			||||||
@@ -63,36 +58,21 @@ namespace ix
 | 
				
			|||||||
                      const CancellationRequest& isCancellationRequested);
 | 
					                      const CancellationRequest& isCancellationRequested);
 | 
				
			||||||
        bool writeBytes(const std::string& str,
 | 
					        bool writeBytes(const std::string& str,
 | 
				
			||||||
                        const CancellationRequest& isCancellationRequested);
 | 
					                        const CancellationRequest& isCancellationRequested);
 | 
				
			||||||
 | 
					        std::pair<bool, std::string> readLine(const CancellationRequest& isCancellationRequested);
 | 
				
			||||||
        std::pair<bool, std::string> readLine(
 | 
					 | 
				
			||||||
            const CancellationRequest& isCancellationRequested);
 | 
					 | 
				
			||||||
        std::pair<bool, std::string> readBytes(
 | 
					 | 
				
			||||||
            size_t length,
 | 
					 | 
				
			||||||
            const OnProgressCallback& onProgressCallback,
 | 
					 | 
				
			||||||
            const CancellationRequest& isCancellationRequested);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static int getErrno();
 | 
					        static int getErrno();
 | 
				
			||||||
        static bool init(); // Required on Windows to initialize WinSocket
 | 
					        static bool init(); // Required on Windows to initialize WinSocket
 | 
				
			||||||
        static void cleanup(); // Required on Windows to cleanup WinSocket
 | 
					        static void cleanup(); // Required on Windows to cleanup WinSocket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Used as special codes for pipe communication
 | 
					 | 
				
			||||||
        static const uint64_t kSendRequest;
 | 
					 | 
				
			||||||
        static const uint64_t kCloseRequest;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
        void closeSocket(int fd);
 | 
					        void closeSocket(int fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::atomic<int> _sockfd;
 | 
					        std::atomic<int> _sockfd;
 | 
				
			||||||
        std::mutex _socketMutex;
 | 
					        std::mutex _socketMutex;
 | 
				
			||||||
 | 
					        EventFd _eventfd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        static const int kDefaultPollTimeout;
 | 
					        static const int kDefaultPollTimeout;
 | 
				
			||||||
        static const int kDefaultPollNoTimeout;
 | 
					        static const int kDefaultPollNoTimeout;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Buffer for reading from our socket. That buffer is never resized.
 | 
					 | 
				
			||||||
        std::vector<uint8_t> _readBuffer;
 | 
					 | 
				
			||||||
        static constexpr size_t kChunkSize = 1 << 15;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        EventFd _eventfd;
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -252,11 +252,6 @@ namespace ix
 | 
				
			|||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            webSocketMessageType = WebSocket_MessageType_Pong;
 | 
					                            webSocketMessageType = WebSocket_MessageType_Pong;
 | 
				
			||||||
                        } break;
 | 
					                        } break;
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        case WebSocketTransport::FRAGMENT:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            webSocketMessageType = WebSocket_MessageType_Fragment;
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    WebSocketErrorInfo webSocketErrorInfo;
 | 
					                    WebSocketErrorInfo webSocketErrorInfo;
 | 
				
			||||||
@@ -379,9 +374,4 @@ namespace ix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        _automaticReconnection = false;
 | 
					        _automaticReconnection = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    size_t WebSocket::bufferedAmount() const
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return _ws.bufferedAmount();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,8 +39,7 @@ namespace ix
 | 
				
			|||||||
        WebSocket_MessageType_Close = 2,
 | 
					        WebSocket_MessageType_Close = 2,
 | 
				
			||||||
        WebSocket_MessageType_Error = 3,
 | 
					        WebSocket_MessageType_Error = 3,
 | 
				
			||||||
        WebSocket_MessageType_Ping = 4,
 | 
					        WebSocket_MessageType_Ping = 4,
 | 
				
			||||||
        WebSocket_MessageType_Pong = 5,
 | 
					        WebSocket_MessageType_Pong = 5
 | 
				
			||||||
        WebSocket_MessageType_Fragment = 6
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct WebSocketOpenInfo
 | 
					    struct WebSocketOpenInfo
 | 
				
			||||||
@@ -112,7 +111,6 @@ namespace ix
 | 
				
			|||||||
        const std::string& getUrl() const;
 | 
					        const std::string& getUrl() const;
 | 
				
			||||||
        const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
 | 
					        const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
 | 
				
			||||||
        int getHeartBeatPeriod() const;
 | 
					        int getHeartBeatPeriod() const;
 | 
				
			||||||
        size_t bufferedAmount() const;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void enableAutomaticReconnection();
 | 
					        void enableAutomaticReconnection();
 | 
				
			||||||
        void disableAutomaticReconnection();
 | 
					        void disableAutomaticReconnection();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,31 +1,7 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * The MIT License (MIT)
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * Copyright (c) 2012, 2013 <dhbaird@gmail.com>
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					 | 
				
			||||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
					 | 
				
			||||||
 * in the Software without restriction, including without limitation the rights
 | 
					 | 
				
			||||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					 | 
				
			||||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
					 | 
				
			||||||
 * furnished to do so, subject to the following conditions:
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * The above copyright notice and this permission notice shall be included in
 | 
					 | 
				
			||||||
 * all copies or substantial portions of the Software.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					 | 
				
			||||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					 | 
				
			||||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					 | 
				
			||||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  IXWebSocketTransport.cpp
 | 
					 *  IXWebSocketTransport.cpp
 | 
				
			||||||
 *  Author: Benjamin Sergeant
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 *  Copyright (c) 2017-2019 Machine Zone, Inc. All rights reserved.
 | 
					 *  Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
@@ -38,6 +14,14 @@
 | 
				
			|||||||
#include "IXUrlParser.h"
 | 
					#include "IXUrlParser.h"
 | 
				
			||||||
#include "IXSocketFactory.h"
 | 
					#include "IXSocketFactory.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef IXWEBSOCKET_USE_TLS
 | 
				
			||||||
 | 
					# ifdef __APPLE__
 | 
				
			||||||
 | 
					#  include "IXSocketAppleSSL.h"
 | 
				
			||||||
 | 
					# else
 | 
				
			||||||
 | 
					#  include "IXSocketOpenSSL.h"
 | 
				
			||||||
 | 
					# endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,6 +80,16 @@ namespace ix
 | 
				
			|||||||
                                       std::string("Could not parse URL ") + url);
 | 
					                                       std::string("Could not parse URL ") + url);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (protocol != "ws" && protocol != "wss")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::stringstream ss;
 | 
				
			||||||
 | 
					            ss << "Invalid protocol: " << protocol
 | 
				
			||||||
 | 
					               << " for url " << url
 | 
				
			||||||
 | 
					               << " . Supported protocols are ws and wss";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return WebSocketInitResult(false, 0, ss.str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool tls = protocol == "wss";
 | 
					        bool tls = protocol == "wss";
 | 
				
			||||||
        std::string errorMsg;
 | 
					        std::string errorMsg;
 | 
				
			||||||
        _socket = createSocket(tls, errorMsg);
 | 
					        _socket = createSocket(tls, errorMsg);
 | 
				
			||||||
@@ -190,24 +184,9 @@ namespace ix
 | 
				
			|||||||
                    std::stringstream ss;
 | 
					                    std::stringstream ss;
 | 
				
			||||||
                    ss << kHeartBeatPingMessage << "::" << _heartBeatPeriod << "s";
 | 
					                    ss << kHeartBeatPingMessage << "::" << _heartBeatPeriod << "s";
 | 
				
			||||||
                    sendPing(ss.str());
 | 
					                    sendPing(ss.str());
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                // Make sure we send all the buffered data
 | 
					 | 
				
			||||||
                // there can be a lot of it for large messages.
 | 
					 | 
				
			||||||
                else if (pollResult == PollResultType_SendRequest)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    while (!isSendBufferEmpty() && !_requestInitCancellation)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        sendOnSocket();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // Sleep 10ms between each send so that we dont busy loop
 | 
					 | 
				
			||||||
                        // A better strategy would be to select on the socket to 
 | 
					 | 
				
			||||||
                        // check whether we can write to it without blocking
 | 
					 | 
				
			||||||
                        std::chrono::duration<double, std::micro> duration(10);
 | 
					 | 
				
			||||||
                        std::this_thread::sleep_for(duration);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else if (pollResult == PollResultType_ReadyForRead)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                while (true)
 | 
					                while (true)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size());
 | 
					                    ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size());
 | 
				
			||||||
@@ -231,16 +210,12 @@ namespace ix
 | 
				
			|||||||
                                      _readbuf.begin() + ret);
 | 
					                                      _readbuf.begin() + ret);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                }
 | 
					
 | 
				
			||||||
                else if (pollResult == PollResultType_Error)
 | 
					                if (isSendBufferEmpty() && _readyState == CLOSING)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    _socket->close();
 | 
					                    _socket->close();
 | 
				
			||||||
 | 
					                    setReadyState(CLOSED);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else if (pollResult == PollResultType_CloseRequest)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    ;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            _heartBeatPeriod);
 | 
					            _heartBeatPeriod);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -417,10 +392,6 @@ namespace ix
 | 
				
			|||||||
                        emitMessage(MSG, getMergedChunks(), ws, onMessageCallback);
 | 
					                        emitMessage(MSG, getMergedChunks(), ws, onMessageCallback);
 | 
				
			||||||
                        _chunks.clear();
 | 
					                        _chunks.clear();
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        emitMessage(FRAGMENT, std::string(), ws, onMessageCallback);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (ws.opcode == wsheader_type::PING)
 | 
					            else if (ws.opcode == wsheader_type::PING)
 | 
				
			||||||
@@ -504,7 +475,7 @@ namespace ix
 | 
				
			|||||||
        size_t wireSize = message.size();
 | 
					        size_t wireSize = message.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // When the RSV1 bit is 1 it means the message is compressed
 | 
					        // When the RSV1 bit is 1 it means the message is compressed
 | 
				
			||||||
        if (_enablePerMessageDeflate && ws.rsv1 && messageKind != FRAGMENT)
 | 
					        if (_enablePerMessageDeflate && ws.rsv1)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::string decompressedMessage;
 | 
					            std::string decompressedMessage;
 | 
				
			||||||
            bool success = _perMessageDeflate.decompress(message, decompressedMessage);
 | 
					            bool success = _perMessageDeflate.decompress(message, decompressedMessage);
 | 
				
			||||||
@@ -602,7 +573,7 @@ namespace ix
 | 
				
			|||||||
                // Send message
 | 
					                // Send message
 | 
				
			||||||
                sendFragment(opcodeType, fin, begin, end, compress);
 | 
					                sendFragment(opcodeType, fin, begin, end, compress);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (onProgressCallback && !onProgressCallback((int)i, (int) steps))
 | 
					                if (onProgressCallback && !onProgressCallback(i, steps))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -611,12 +582,6 @@ namespace ix
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Request to flush the send buffer on the background thread if it isn't empty
 | 
					 | 
				
			||||||
        if (!isSendBufferEmpty())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            _socket->wakeUpFromPoll(Socket::kSendRequest);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return WebSocketSendInfo(true, compressionError, payloadSize, wireSize);
 | 
					        return WebSocketSendInfo(true, compressionError, payloadSize, wireSize);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -762,18 +727,8 @@ namespace ix
 | 
				
			|||||||
        sendData(wsheader_type::CLOSE, normalClosure, compress);
 | 
					        sendData(wsheader_type::CLOSE, normalClosure, compress);
 | 
				
			||||||
        setReadyState(CLOSING);
 | 
					        setReadyState(CLOSING);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        _socket->wakeUpFromPoll(Socket::kCloseRequest);
 | 
					        _socket->wakeUpFromPoll();
 | 
				
			||||||
        _socket->close();
 | 
					        _socket->close();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        _closeCode = 1000;
 | 
					 | 
				
			||||||
        _closeReason = "Normal Closure";
 | 
					 | 
				
			||||||
        setReadyState(CLOSED);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    size_t WebSocketTransport::bufferedAmount() const
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_txbufMutex);
 | 
					 | 
				
			||||||
        return _txbuf.size();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace ix
 | 
					} // namespace ix
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,8 +45,7 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            MSG,
 | 
					            MSG,
 | 
				
			||||||
            PING,
 | 
					            PING,
 | 
				
			||||||
            PONG,
 | 
					            PONG
 | 
				
			||||||
            FRAGMENT
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        using OnMessageCallback = std::function<void(const std::string&,
 | 
					        using OnMessageCallback = std::function<void(const std::string&,
 | 
				
			||||||
@@ -77,7 +76,6 @@ namespace ix
 | 
				
			|||||||
        void setReadyState(ReadyStateValues readyStateValue);
 | 
					        void setReadyState(ReadyStateValues readyStateValue);
 | 
				
			||||||
        void setOnCloseCallback(const OnCloseCallback& onCloseCallback);
 | 
					        void setOnCloseCallback(const OnCloseCallback& onCloseCallback);
 | 
				
			||||||
        void dispatch(const OnMessageCallback& onMessageCallback);
 | 
					        void dispatch(const OnMessageCallback& onMessageCallback);
 | 
				
			||||||
        size_t bufferedAmount() const;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        std::string _url;
 | 
					        std::string _url;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								makefile
									
									
									
									
									
								
							@@ -8,10 +8,10 @@ brew:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.PHONY: docker
 | 
					.PHONY: docker
 | 
				
			||||||
docker:
 | 
					docker:
 | 
				
			||||||
	docker build -t ws:latest .
 | 
						docker build -t broadcast_server:latest .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
run:
 | 
					run:
 | 
				
			||||||
	docker run --cap-add sys_ptrace -it ws:latest
 | 
						docker run --cap-add sys_ptrace -it broadcast_server:latest bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# this is helpful to remove trailing whitespaces
 | 
					# this is helpful to remove trailing whitespaces
 | 
				
			||||||
trail:
 | 
					trail:
 | 
				
			||||||
@@ -36,9 +36,6 @@ test_server:
 | 
				
			|||||||
test:
 | 
					test:
 | 
				
			||||||
	python test/run.py
 | 
						python test/run.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ws_test:
 | 
					 | 
				
			||||||
	(cd ws ; sh test_ws.sh)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# For the fork that is configured with appveyor
 | 
					# For the fork that is configured with appveyor
 | 
				
			||||||
rebase_upstream:
 | 
					rebase_upstream:
 | 
				
			||||||
	git fetch upstream
 | 
						git fetch upstream
 | 
				
			||||||
@@ -46,9 +43,5 @@ rebase_upstream:
 | 
				
			|||||||
	git reset --hard upstream/master
 | 
						git reset --hard upstream/master
 | 
				
			||||||
	git push origin master --force
 | 
						git push origin master --force
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_cmake_for_linux:
 | 
					 | 
				
			||||||
	mkdir -p /tmp/cmake
 | 
					 | 
				
			||||||
	(cd /tmp/cmake ; curl -L -O https://github.com/Kitware/CMake/releases/download/v3.14.0-rc4/cmake-3.14.0-rc4-Linux-x86_64.tar.gz ; tar zxf cmake-3.14.0-rc4-Linux-x86_64.tar.gz)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.PHONY: test
 | 
					.PHONY: test
 | 
				
			||||||
.PHONY: build
 | 
					.PHONY: build
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "IXTest.h"
 | 
					#include "IXTest.h"
 | 
				
			||||||
#include "catch.hpp"
 | 
					#include "catch.hpp"
 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace ix;
 | 
					using namespace ix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,13 +65,7 @@ TEST_CASE("socket", "[socket]")
 | 
				
			|||||||
        std::shared_ptr<Socket> socket(new Socket);
 | 
					        std::shared_ptr<Socket> socket(new Socket);
 | 
				
			||||||
        std::string host("www.google.com");
 | 
					        std::string host("www.google.com");
 | 
				
			||||||
        int port = 80;
 | 
					        int port = 80;
 | 
				
			||||||
 | 
					        std::string request("GET / HTTP/1.1\r\n\r\n");
 | 
				
			||||||
        std::stringstream ss;
 | 
					 | 
				
			||||||
        ss << "GET / HTTP/1.1\r\n";
 | 
					 | 
				
			||||||
        ss << "Host: " << host << "\r\n";
 | 
					 | 
				
			||||||
        ss << "\r\n";
 | 
					 | 
				
			||||||
        std::string request(ss.str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int expectedStatus = 200;
 | 
					        int expectedStatus = 200;
 | 
				
			||||||
        int timeoutSecs = 3;
 | 
					        int timeoutSecs = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,15 +69,10 @@ namespace ix
 | 
				
			|||||||
        Logger() << msg;
 | 
					        Logger() << msg;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int getAnyFreePortSimple()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        static int defaultPort = 8090;
 | 
					 | 
				
			||||||
        return defaultPort++;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    int getAnyFreePort()
 | 
					    int getAnyFreePort()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        int defaultPort = 8090;
 | 
					        int defaultPort = 8090;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int sockfd;
 | 
					        int sockfd;
 | 
				
			||||||
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 | 
					        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -127,15 +122,8 @@ namespace ix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        while (true)
 | 
					        while (true)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
#if defined(__has_feature)
 | 
					 | 
				
			||||||
# if __has_feature(address_sanitizer)
 | 
					 | 
				
			||||||
            int port = getAnyFreePortSimple();
 | 
					 | 
				
			||||||
# else
 | 
					 | 
				
			||||||
            int port = getAnyFreePort();
 | 
					            int port = getAnyFreePort();
 | 
				
			||||||
# endif
 | 
					
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
            int port = getAnyFreePort();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
            //
 | 
					            //
 | 
				
			||||||
            // Only port above 1024 can be used by non root users, but for some
 | 
					            // Only port above 1024 can be used by non root users, but for some
 | 
				
			||||||
            // reason I got port 7 returned with macOS when binding on port 0...
 | 
					            // reason I got port 7 returned with macOS when binding on port 0...
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -164,21 +164,10 @@ namespace
 | 
				
			|||||||
                    ss << "cmd_websocket_chat: Error ! " << error.reason;
 | 
					                    ss << "cmd_websocket_chat: Error ! " << error.reason;
 | 
				
			||||||
                    log(ss.str());
 | 
					                    log(ss.str());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    log("cmd_websocket_chat: received ping message");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    log("cmd_websocket_chat: received pong message");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    log("cmd_websocket_chat: received message fragment");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    ss << "Unexpected ix::WebSocketMessageType";
 | 
					                    // FIXME: missing ping/pong messages
 | 
				
			||||||
 | 
					                    ss << "Invalid ix::WebSocketMessageType";
 | 
				
			||||||
                    log(ss.str());
 | 
					                    log(ss.str());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								test/run.py
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								test/run.py
									
									
									
									
									
								
							@@ -6,10 +6,10 @@ osName = platform.system()
 | 
				
			|||||||
print('os name = {}'.format(osName))
 | 
					print('os name = {}'.format(osName))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
root = os.path.dirname(os.path.realpath(__file__))
 | 
					root = os.path.dirname(os.path.realpath(__file__))
 | 
				
			||||||
buildDir = os.path.join(root, 'build', osName)
 | 
					buildDir = os.path.join(root, 'build')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if not os.path.exists(buildDir):
 | 
					if not os.path.exists(buildDir):
 | 
				
			||||||
    os.makedirs(buildDir)
 | 
					    os.mkdir(buildDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
os.chdir(buildDir)
 | 
					os.chdir(buildDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -38,7 +38,7 @@ sanitizerFlags = sanitizersFlags[sanitizer]
 | 
				
			|||||||
#     os.environ['CC'] = 'clang-cl'
 | 
					#     os.environ['CC'] = 'clang-cl'
 | 
				
			||||||
#     os.environ['CXX'] = 'clang-cl'
 | 
					#     os.environ['CXX'] = 'clang-cl'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cmakeCmd = 'cmake -DCMAKE_BUILD_TYPE=Debug {} {} ../..'.format(generator, sanitizerFlags)
 | 
					cmakeCmd = 'cmake -DCMAKE_BUILD_TYPE=Debug {} {} ..'.format(generator, sanitizerFlags)
 | 
				
			||||||
print(cmakeCmd)
 | 
					print(cmakeCmd)
 | 
				
			||||||
ret = os.system(cmakeCmd)
 | 
					ret = os.system(cmakeCmd)
 | 
				
			||||||
assert ret == 0, 'CMake failed, exiting'
 | 
					assert ret == 0, 'CMake failed, exiting'
 | 
				
			||||||
@@ -67,7 +67,6 @@ def findFiles(prefix):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# We need to copy the zlib DLL in the current work directory
 | 
					# We need to copy the zlib DLL in the current work directory
 | 
				
			||||||
shutil.copy(os.path.join(
 | 
					shutil.copy(os.path.join(
 | 
				
			||||||
    '..',
 | 
					 | 
				
			||||||
    '..',
 | 
					    '..',
 | 
				
			||||||
    '..',
 | 
					    '..',
 | 
				
			||||||
    'third_party',
 | 
					    'third_party',
 | 
				
			||||||
@@ -78,8 +77,6 @@ shutil.copy(os.path.join(
 | 
				
			|||||||
    'bin',
 | 
					    'bin',
 | 
				
			||||||
    'zlib.dll'), '.')
 | 
					    'zlib.dll'), '.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lldb = "lldb --batch -o 'run' -k 'thread backtrace all' -k 'quit 1'"
 | 
					testCommand = '{} {}'.format(testBinary, os.getenv('TEST', ''))
 | 
				
			||||||
lldb = ""  # Disabled for now
 | 
					 | 
				
			||||||
testCommand = '{} {} {}'.format(lldb, testBinary, os.getenv('TEST', ''))
 | 
					 | 
				
			||||||
ret = os.system(testCommand)
 | 
					ret = os.system(testCommand)
 | 
				
			||||||
assert ret == 0, 'Test command failed'
 | 
					assert ret == 0, 'Test command failed'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								third_party/homebrew_formula.rb
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								third_party/homebrew_formula.rb
									
									
									
									
										vendored
									
									
								
							@@ -1,20 +0,0 @@
 | 
				
			|||||||
class Ixwebsocket < Formula
 | 
					 | 
				
			||||||
  desc "WebSocket client and server, and HTTP client command-line tool"
 | 
					 | 
				
			||||||
  homepage "https://github.com/machinezone/IXWebSocket"
 | 
					 | 
				
			||||||
  url "https://github.com/machinezone/IXWebSocket/archive/v1.1.0.tar.gz"
 | 
					 | 
				
			||||||
  sha256 "52592ce3d0a67ad0f90ac9e8a458f61724175d95a01a38d1bad3fcdc5c7b6666"
 | 
					 | 
				
			||||||
  depends_on "cmake" => :build
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def install
 | 
					 | 
				
			||||||
    system "cmake", ".", *std_cmake_args
 | 
					 | 
				
			||||||
    system "make", "install"
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  test do
 | 
					 | 
				
			||||||
    system "#{bin}/ws", "--help"
 | 
					 | 
				
			||||||
    system "#{bin}/ws", "send", "--help"
 | 
					 | 
				
			||||||
    system "#{bin}/ws", "receive", "--help"
 | 
					 | 
				
			||||||
    system "#{bin}/ws", "transfer", "--help"
 | 
					 | 
				
			||||||
    system "#{bin}/ws", "curl", "--help"
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
							
								
								
									
										58
									
								
								ws/README.md
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								ws/README.md
									
									
									
									
									
								
							@@ -1,62 +1,10 @@
 | 
				
			|||||||
# General
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ws is a command line tool that should exercise most of the IXWebSocket code, and provide example code.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
$ ws --help
 | 
					 | 
				
			||||||
ws is a websocket tool
 | 
					 | 
				
			||||||
Usage: ws [OPTIONS] SUBCOMMAND
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Options:
 | 
					 | 
				
			||||||
  -h,--help                   Print this help message and exit
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Subcommands:
 | 
					 | 
				
			||||||
  send                        Send a file
 | 
					 | 
				
			||||||
  receive                     Receive a file
 | 
					 | 
				
			||||||
  transfer                    Broadcasting server
 | 
					 | 
				
			||||||
  connect                     Connect to a remote server
 | 
					 | 
				
			||||||
  chat                        Group chat
 | 
					 | 
				
			||||||
  echo_server                 Echo server
 | 
					 | 
				
			||||||
  broadcast_server            Broadcasting server
 | 
					 | 
				
			||||||
  ping                        Ping pong
 | 
					 | 
				
			||||||
  curl                        HTTP Client
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## file transfer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
# Start transfer server, which is just a broadcast server at this point
 | 
					# Start transfer server, which is just a broadcast server at this point
 | 
				
			||||||
ws transfer # running on port 8080.
 | 
					./ws transfer # running on port 8080.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Start receiver first
 | 
					# Start receiver first
 | 
				
			||||||
ws receive ws://localhost:8080 
 | 
					./ws receive ws://localhost:8080 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Then send a file. File will be received and written to disk by the receiver process
 | 
					# Then send a file. File will be received and written to disk by the receiver process
 | 
				
			||||||
ws send ws://localhost:8080 /file/to/path
 | 
					./ws send ws://localhost:8080 /file/to/path
 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## curl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
$ ws curl --help
 | 
					 | 
				
			||||||
HTTP Client
 | 
					 | 
				
			||||||
Usage: ws curl [OPTIONS] url
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Positionals:
 | 
					 | 
				
			||||||
  url TEXT REQUIRED           Connection url
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Options:
 | 
					 | 
				
			||||||
  -h,--help                   Print this help message and exit
 | 
					 | 
				
			||||||
  -d TEXT                     Form data
 | 
					 | 
				
			||||||
  -F TEXT                     Form data
 | 
					 | 
				
			||||||
  -H TEXT                     Header
 | 
					 | 
				
			||||||
  --output TEXT               Output file
 | 
					 | 
				
			||||||
  -I                          Send a HEAD request
 | 
					 | 
				
			||||||
  -L                          Follow redirects
 | 
					 | 
				
			||||||
  --max-redirects INT         Max Redirects
 | 
					 | 
				
			||||||
  -v                          Verbose
 | 
					 | 
				
			||||||
  -O                          Save output to disk
 | 
					 | 
				
			||||||
  --compress                  Enable gzip compression
 | 
					 | 
				
			||||||
  --connect-timeout INT       Connection timeout
 | 
					 | 
				
			||||||
  --transfer-timeout INT      Transfer timeout
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,6 @@ g++ --std=c++14 \
 | 
				
			|||||||
    ../ixwebsocket/IXSocket.cpp \
 | 
					    ../ixwebsocket/IXSocket.cpp \
 | 
				
			||||||
    ../ixwebsocket/IXSocketServer.cpp \
 | 
					    ../ixwebsocket/IXSocketServer.cpp \
 | 
				
			||||||
    ../ixwebsocket/IXSocketConnect.cpp \
 | 
					    ../ixwebsocket/IXSocketConnect.cpp \
 | 
				
			||||||
    ../ixwebsocket/IXSocketFactory.cpp \
 | 
					 | 
				
			||||||
    ../ixwebsocket/IXDNSLookup.cpp \
 | 
					    ../ixwebsocket/IXDNSLookup.cpp \
 | 
				
			||||||
    ../ixwebsocket/IXCancellationRequest.cpp \
 | 
					    ../ixwebsocket/IXCancellationRequest.cpp \
 | 
				
			||||||
    ../ixwebsocket/IXWebSocket.cpp \
 | 
					    ../ixwebsocket/IXWebSocket.cpp \
 | 
				
			||||||
@@ -23,16 +22,12 @@ g++ --std=c++14 \
 | 
				
			|||||||
    ../ixwebsocket/IXWebSocketPerMessageDeflate.cpp \
 | 
					    ../ixwebsocket/IXWebSocketPerMessageDeflate.cpp \
 | 
				
			||||||
    ../ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp \
 | 
					    ../ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp \
 | 
				
			||||||
    ../ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp \
 | 
					    ../ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp \
 | 
				
			||||||
    ../ixwebsocket/IXWebSocketHttpHeaders.cpp \
 | 
					 | 
				
			||||||
    ../ixwebsocket/IXHttpClient.cpp \
 | 
					 | 
				
			||||||
    ../ixwebsocket/IXUrlParser.cpp \
 | 
					 | 
				
			||||||
    ../ixwebsocket/IXSocketOpenSSL.cpp \
 | 
					    ../ixwebsocket/IXSocketOpenSSL.cpp \
 | 
				
			||||||
    ../ixwebsocket/linux/IXSetThreadName_linux.cpp \
 | 
					    ../ixwebsocket/linux/IXSetThreadName_linux.cpp \
 | 
				
			||||||
    ../third_party/msgpack11/msgpack11.cpp \
 | 
					    ../third_party/jsoncpp/jsoncpp.cpp \
 | 
				
			||||||
    ixcrypto/IXBase64.cpp \
 | 
					    ixcrypto/IXBase64.cpp \
 | 
				
			||||||
    ixcrypto/IXHash.cpp \
 | 
					    ixcrypto/IXHash.cpp \
 | 
				
			||||||
    ixcrypto/IXUuid.cpp \
 | 
					    ixcrypto/IXUuid.cpp \
 | 
				
			||||||
    ws_http_client.cpp \
 | 
					 | 
				
			||||||
    ws_ping_pong.cpp \
 | 
					    ws_ping_pong.cpp \
 | 
				
			||||||
    ws_broadcast_server.cpp \
 | 
					    ws_broadcast_server.cpp \
 | 
				
			||||||
    ws_echo_server.cpp \
 | 
					    ws_echo_server.cpp \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,52 +0,0 @@
 | 
				
			|||||||
#!/bin/sh
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
rm -rf /tmp/ws_test
 | 
					 | 
				
			||||||
mkdir -p /tmp/ws_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Start a transport server
 | 
					 | 
				
			||||||
cd /tmp/ws_test
 | 
					 | 
				
			||||||
ws transfer --port 8090 --pidfile /tmp/ws_test/pidfile &
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Wait until the transfer server is up 
 | 
					 | 
				
			||||||
while true
 | 
					 | 
				
			||||||
do
 | 
					 | 
				
			||||||
    nc -zv 127.0.0.1 8090 && {
 | 
					 | 
				
			||||||
        echo "Transfer server up and running"
 | 
					 | 
				
			||||||
        break
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    echo "sleep ..."
 | 
					 | 
				
			||||||
    sleep 0.1
 | 
					 | 
				
			||||||
done
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Start a receiver
 | 
					 | 
				
			||||||
mkdir -p /tmp/ws_test/receive
 | 
					 | 
				
			||||||
cd /tmp/ws_test/receive
 | 
					 | 
				
			||||||
ws receive ws://127.0.0.1:8090 &
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
mkdir /tmp/ws_test/send
 | 
					 | 
				
			||||||
cd /tmp/ws_test/send
 | 
					 | 
				
			||||||
# mkfile 10m 10M_file
 | 
					 | 
				
			||||||
dd if=/dev/urandom of=10M_file count=10000 bs=1024
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Start the sender job
 | 
					 | 
				
			||||||
ws send ws://127.0.0.1:8090 10M_file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Wait until the file has been written to disk
 | 
					 | 
				
			||||||
while true
 | 
					 | 
				
			||||||
do
 | 
					 | 
				
			||||||
    if test -f /tmp/ws_test/receive/10M_file ; then
 | 
					 | 
				
			||||||
        echo "Received file does exists, exiting loop"
 | 
					 | 
				
			||||||
        break
 | 
					 | 
				
			||||||
    fi
 | 
					 | 
				
			||||||
    echo "sleep ..."
 | 
					 | 
				
			||||||
    sleep 0.1
 | 
					 | 
				
			||||||
done
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cksum /tmp/ws_test/send/10M_file
 | 
					 | 
				
			||||||
cksum /tmp/ws_test/receive/10M_file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Give some time to ws receive to terminate
 | 
					 | 
				
			||||||
sleep 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Cleanup
 | 
					 | 
				
			||||||
kill `cat /tmp/ws_test/pidfile`
 | 
					 | 
				
			||||||
							
								
								
									
										30
									
								
								ws/ws.cpp
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								ws/ws.cpp
									
									
									
									
									
								
							@@ -16,8 +16,6 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <fstream>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cli11/CLI11.hpp>
 | 
					#include <cli11/CLI11.hpp>
 | 
				
			||||||
#include <ixwebsocket/IXSocket.h>
 | 
					#include <ixwebsocket/IXSocket.h>
 | 
				
			||||||
@@ -33,8 +31,6 @@ int main(int argc, char** argv)
 | 
				
			|||||||
    std::string data;
 | 
					    std::string data;
 | 
				
			||||||
    std::string headers;
 | 
					    std::string headers;
 | 
				
			||||||
    std::string output;
 | 
					    std::string output;
 | 
				
			||||||
    std::string hostname("127.0.0.1");
 | 
					 | 
				
			||||||
    std::string pidfile;
 | 
					 | 
				
			||||||
    bool headersOnly = false;
 | 
					    bool headersOnly = false;
 | 
				
			||||||
    bool followRedirects = false;
 | 
					    bool followRedirects = false;
 | 
				
			||||||
    bool verbose = false;
 | 
					    bool verbose = false;
 | 
				
			||||||
@@ -54,8 +50,6 @@ int main(int argc, char** argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    CLI::App* transferApp = app.add_subcommand("transfer", "Broadcasting server");
 | 
					    CLI::App* transferApp = app.add_subcommand("transfer", "Broadcasting server");
 | 
				
			||||||
    transferApp->add_option("--port", port, "Connection url");
 | 
					    transferApp->add_option("--port", port, "Connection url");
 | 
				
			||||||
    transferApp->add_option("--host", hostname, "Hostname");
 | 
					 | 
				
			||||||
    transferApp->add_option("--pidfile", pidfile, "Pid file");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CLI::App* connectApp = app.add_subcommand("connect", "Connect to a remote server");
 | 
					    CLI::App* connectApp = app.add_subcommand("connect", "Connect to a remote server");
 | 
				
			||||||
    connectApp->add_option("url", url, "Connection url")->required();
 | 
					    connectApp->add_option("url", url, "Connection url")->required();
 | 
				
			||||||
@@ -65,12 +59,10 @@ int main(int argc, char** argv)
 | 
				
			|||||||
    chatApp->add_option("user", user, "User name")->required();
 | 
					    chatApp->add_option("user", user, "User name")->required();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CLI::App* echoServerApp = app.add_subcommand("echo_server", "Echo server");
 | 
					    CLI::App* echoServerApp = app.add_subcommand("echo_server", "Echo server");
 | 
				
			||||||
    echoServerApp->add_option("--port", port, "Port");
 | 
					    echoServerApp->add_option("--port", port, "Connection url");
 | 
				
			||||||
    echoServerApp->add_option("--host", hostname, "Hostname");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CLI::App* broadcastServerApp = app.add_subcommand("broadcast_server", "Broadcasting server");
 | 
					    CLI::App* broadcastServerApp = app.add_subcommand("broadcast_server", "Broadcasting server");
 | 
				
			||||||
    broadcastServerApp->add_option("--port", port, "Port");
 | 
					    broadcastServerApp->add_option("--port", port, "Connection url");
 | 
				
			||||||
    broadcastServerApp->add_option("--host", hostname, "Hostname");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CLI::App* pingPongApp = app.add_subcommand("ping", "Ping pong");
 | 
					    CLI::App* pingPongApp = app.add_subcommand("ping", "Ping pong");
 | 
				
			||||||
    pingPongApp->add_option("url", url, "Connection url")->required();
 | 
					    pingPongApp->add_option("url", url, "Connection url")->required();
 | 
				
			||||||
@@ -94,21 +86,9 @@ int main(int argc, char** argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ix::Socket::init();
 | 
					    ix::Socket::init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // pid file handling
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (app.got_subcommand("transfer"))
 | 
					    if (app.got_subcommand("transfer"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!pidfile.empty())
 | 
					        return ix::ws_transfer_main(port);
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            unlink(pidfile.c_str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            std::ofstream f;
 | 
					 | 
				
			||||||
            f.open(pidfile);
 | 
					 | 
				
			||||||
            f << getpid();
 | 
					 | 
				
			||||||
            f.close();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return ix::ws_transfer_main(port, hostname);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (app.got_subcommand("send"))
 | 
					    else if (app.got_subcommand("send"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -129,11 +109,11 @@ int main(int argc, char** argv)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (app.got_subcommand("echo_server"))
 | 
					    else if (app.got_subcommand("echo_server"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return ix::ws_echo_server_main(port, hostname);
 | 
					        return ix::ws_echo_server_main(port);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (app.got_subcommand("broadcast_server"))
 | 
					    else if (app.got_subcommand("broadcast_server"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return ix::ws_broadcast_server_main(port, hostname);
 | 
					        return ix::ws_broadcast_server_main(port);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (app.got_subcommand("ping"))
 | 
					    else if (app.got_subcommand("ping"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								ws/ws.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								ws/ws.h
									
									
									
									
									
								
							@@ -24,9 +24,9 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    int ws_ping_pong_main(const std::string& url);
 | 
					    int ws_ping_pong_main(const std::string& url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int ws_echo_server_main(int port, const std::string& hostname);
 | 
					    int ws_echo_server_main(int port);
 | 
				
			||||||
    int ws_broadcast_server_main(int port, const std::string& hostname);
 | 
					
 | 
				
			||||||
    int ws_transfer_main(int port, const std::string& hostname);
 | 
					    int ws_broadcast_server_main(int port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int ws_chat_main(const std::string& url,
 | 
					    int ws_chat_main(const std::string& url,
 | 
				
			||||||
                     const std::string& user);
 | 
					                     const std::string& user);
 | 
				
			||||||
@@ -36,6 +36,8 @@ namespace ix
 | 
				
			|||||||
    int ws_receive_main(const std::string& url,
 | 
					    int ws_receive_main(const std::string& url,
 | 
				
			||||||
                        bool enablePerMessageDeflate);
 | 
					                        bool enablePerMessageDeflate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int ws_transfer_main(int port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int ws_send_main(const std::string& url,
 | 
					    int ws_send_main(const std::string& url,
 | 
				
			||||||
                     const std::string& path);
 | 
					                     const std::string& path);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,11 +10,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ws_broadcast_server_main(int port, const std::string& hostname)
 | 
					    int ws_broadcast_server_main(int port)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << "Listening on " << hostname << ":" << port << std::endl;
 | 
					        std::cout << "Listening on port " << port << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ix::WebSocketServer server(port, hostname);
 | 
					        ix::WebSocketServer server(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        server.setOnConnectionCallback(
 | 
					        server.setOnConnectionCallback(
 | 
				
			||||||
            [&server](std::shared_ptr<ix::WebSocket> webSocket)
 | 
					            [&server](std::shared_ptr<ix::WebSocket> webSocket)
 | 
				
			||||||
@@ -39,47 +39,16 @@ namespace ix
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::cerr << "Closed connection"
 | 
					                            std::cerr << "Closed connection" << std::endl;
 | 
				
			||||||
                                      << " code " << closeInfo.code
 | 
					 | 
				
			||||||
                                      << " reason " << closeInfo.reason << std::endl;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Error)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            std::stringstream ss;
 | 
					 | 
				
			||||||
                            ss << "Connection error: " << error.reason      << std::endl;
 | 
					 | 
				
			||||||
                            ss << "#retries: "         << error.retries     << std::endl;
 | 
					 | 
				
			||||||
                            ss << "Wait time(ms): "    << error.wait_time   << std::endl;
 | 
					 | 
				
			||||||
                            ss << "HTTP Status: "      << error.http_status << std::endl;
 | 
					 | 
				
			||||||
                            std::cerr << ss.str();
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            std::cerr << "Received message fragment" << std::endl;
 | 
					 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
					                            std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
				
			||||||
 | 
					 | 
				
			||||||
                            for (auto&& client : server.getClients())
 | 
					                            for (auto&& client : server.getClients())
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                if (client != webSocket)
 | 
					                                if (client != webSocket)
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
                                    client->send(str,
 | 
					                                    client->send(str);
 | 
				
			||||||
                                                 [](int current, int total) -> bool
 | 
					 | 
				
			||||||
                                    {
 | 
					 | 
				
			||||||
                                        std::cerr << "Step " << current
 | 
					 | 
				
			||||||
                                                  << " out of " << total << std::endl;
 | 
					 | 
				
			||||||
                                        return true;
 | 
					 | 
				
			||||||
                                    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                    do
 | 
					 | 
				
			||||||
                                    {
 | 
					 | 
				
			||||||
                                        size_t bufferedAmount = client->bufferedAmount();
 | 
					 | 
				
			||||||
                                        std::cerr << bufferedAmount << " bytes left to be sent" << std::endl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                        std::chrono::duration<double, std::milli> duration(10);
 | 
					 | 
				
			||||||
                                        std::this_thread::sleep_for(duration);
 | 
					 | 
				
			||||||
                                    } while (client->bufferedAmount() != 0);
 | 
					 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,26 +94,16 @@ namespace ix
 | 
				
			|||||||
                std::stringstream ss;
 | 
					                std::stringstream ss;
 | 
				
			||||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
					                if (messageType == ix::WebSocket_MessageType_Open)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    log("ws chat: connected");
 | 
					                    ss << "cmd_websocket_chat: user "
 | 
				
			||||||
                    std::cout << "Uri: " << openInfo.uri << std::endl;
 | 
					 | 
				
			||||||
                    std::cout << "Handshake Headers:" << std::endl;
 | 
					 | 
				
			||||||
                    for (auto it : openInfo.headers)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        std::cout << it.first << ": " << it.second << std::endl;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    ss << "ws chat: user "
 | 
					 | 
				
			||||||
                       << _user
 | 
					                       << _user
 | 
				
			||||||
                       << " Connected !";
 | 
					                       << " Connected !";
 | 
				
			||||||
                       log(ss.str());
 | 
					                       log(ss.str());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
					                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    ss << "ws chat: user "
 | 
					                    ss << "cmd_websocket_chat: user "
 | 
				
			||||||
                       << _user
 | 
					                       << _user
 | 
				
			||||||
                       << " disconnected !"
 | 
					                       << " disconnected !";
 | 
				
			||||||
                       << " code " << closeInfo.code
 | 
					 | 
				
			||||||
                       << " reason " << closeInfo.reason;
 | 
					 | 
				
			||||||
                       log(ss.str());
 | 
					                       log(ss.str());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
					                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
@@ -127,7 +117,7 @@ namespace ix
 | 
				
			|||||||
                    _receivedQueue.push(result.second);
 | 
					                    _receivedQueue.push(result.second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    ss << std::endl
 | 
					                    ss << std::endl
 | 
				
			||||||
                       << result.first << "(" << wireSize << " bytes)" << " > " << result.second
 | 
					                       << result.first << " > " << result.second
 | 
				
			||||||
                       << std::endl
 | 
					                       << std::endl
 | 
				
			||||||
                       << _user << " > ";
 | 
					                       << _user << " > ";
 | 
				
			||||||
                    log(ss.str());
 | 
					                    log(ss.str());
 | 
				
			||||||
@@ -198,7 +188,5 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        std::cout << std::endl;
 | 
					        std::cout << std::endl;
 | 
				
			||||||
        webSocketChat.stop();
 | 
					        webSocketChat.stop();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,8 +84,6 @@ namespace ix
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
					                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    ss << "ws_connect: received message: "
 | 
					                    ss << "ws_connect: received message: "
 | 
				
			||||||
                       << str;
 | 
					                       << str;
 | 
				
			||||||
                    log(ss.str());
 | 
					                    log(ss.str());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,17 +10,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ws_echo_server_main(int port, const std::string& hostname)
 | 
					    int ws_echo_server_main(int port)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << "Listening on " << hostname << ":" << port << std::endl;
 | 
					        std::cout << "Listening on port " << port << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ix::WebSocketServer server(port, hostname);
 | 
					        ix::WebSocketServer server(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        server.setOnConnectionCallback(
 | 
					        server.setOnConnectionCallback(
 | 
				
			||||||
            [](std::shared_ptr<ix::WebSocket> webSocket)
 | 
					            [&server](std::shared_ptr<ix::WebSocket> webSocket)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                webSocket->setOnMessageCallback(
 | 
					                webSocket->setOnMessageCallback(
 | 
				
			||||||
                    [webSocket](ix::WebSocketMessageType messageType,
 | 
					                    [webSocket, &server](ix::WebSocketMessageType messageType,
 | 
				
			||||||
                       const std::string& str,
 | 
					                       const std::string& str,
 | 
				
			||||||
                       size_t wireSize,
 | 
					                       size_t wireSize,
 | 
				
			||||||
                       const ix::WebSocketErrorInfo& error,
 | 
					                       const ix::WebSocketErrorInfo& error,
 | 
				
			||||||
@@ -39,18 +39,7 @@ namespace ix
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::cerr << "Closed connection"
 | 
					                            std::cerr << "Closed connection" << std::endl;
 | 
				
			||||||
                                      << " code " << closeInfo.code
 | 
					 | 
				
			||||||
                                      << " reason " << closeInfo.reason << std::endl;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Error)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            std::stringstream ss;
 | 
					 | 
				
			||||||
                            ss << "Connection error: " << error.reason      << std::endl;
 | 
					 | 
				
			||||||
                            ss << "#retries: "         << error.retries     << std::endl;
 | 
					 | 
				
			||||||
                            ss << "Wait time(ms): "    << error.wait_time   << std::endl;
 | 
					 | 
				
			||||||
                            ss << "HTTP Status: "      << error.http_status << std::endl;
 | 
					 | 
				
			||||||
                            std::cerr << ss.str();
 | 
					 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,12 +107,6 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            std::cout << msg;
 | 
					            std::cout << msg;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        args.onProgressCallback = [](int current, int total) -> bool
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            std::cerr << "\r" << "Downloaded "
 | 
					 | 
				
			||||||
                      << current << " bytes out of " << total;
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        HttpParameters httpParameters = parsePostParameters(data);
 | 
					        HttpParameters httpParameters = parsePostParameters(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -131,8 +125,6 @@ namespace ix
 | 
				
			|||||||
            out = httpClient.post(url, httpParameters, args);
 | 
					            out = httpClient.post(url, httpParameters, args);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::cerr << std::endl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto statusCode = std::get<0>(out);
 | 
					        auto statusCode = std::get<0>(out);
 | 
				
			||||||
        auto errorCode = std::get<1>(out);
 | 
					        auto errorCode = std::get<1>(out);
 | 
				
			||||||
        auto responseHeaders = std::get<2>(out);
 | 
					        auto responseHeaders = std::get<2>(out);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,19 +61,10 @@ namespace ix
 | 
				
			|||||||
               const ix::WebSocketOpenInfo& openInfo,
 | 
					               const ix::WebSocketOpenInfo& openInfo,
 | 
				
			||||||
               const ix::WebSocketCloseInfo& closeInfo)
 | 
					               const ix::WebSocketCloseInfo& closeInfo)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                std::stringstream ss;
 | 
					                std::stringstream ss;
 | 
				
			||||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
					                if (messageType == ix::WebSocket_MessageType_Open)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    log("ping_pong: connected");
 | 
					                    log("ping_pong: connected");
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    std::cout << "Uri: " << openInfo.uri << std::endl;
 | 
					 | 
				
			||||||
                    std::cout << "Handshake Headers:" << std::endl;
 | 
					 | 
				
			||||||
                    for (auto it : openInfo.headers)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        std::cout << it.first << ": " << it.second << std::endl;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
					                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@@ -162,7 +153,5 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        std::cout << std::endl;
 | 
					        std::cout << std::endl;
 | 
				
			||||||
        webSocketPingPong.stop();
 | 
					        webSocketPingPong.stop();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,16 +146,11 @@ namespace ix
 | 
				
			|||||||
        std::string filename = data["filename"].string_value();
 | 
					        std::string filename = data["filename"].string_value();
 | 
				
			||||||
        filename = extractFilename(filename);
 | 
					        filename = extractFilename(filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string filenameTmp = filename + ".tmp";
 | 
					        std::cout << "Writing to disk: " << filename << std::endl;
 | 
				
			||||||
 | 
					        std::ofstream out(filename);
 | 
				
			||||||
        std::cout << "Writing to disk: " << filenameTmp << std::endl;
 | 
					 | 
				
			||||||
        std::ofstream out(filenameTmp);
 | 
					 | 
				
			||||||
        out.write((char*)&content.front(), content.size());
 | 
					        out.write((char*)&content.front(), content.size());
 | 
				
			||||||
        out.close();
 | 
					        out.close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::cout << "Renaming " << filenameTmp << " to " << filename << std::endl;
 | 
					 | 
				
			||||||
        rename(filenameTmp.c_str(), filename.c_str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::map<MsgPack, MsgPack> pdu;
 | 
					        std::map<MsgPack, MsgPack> pdu;
 | 
				
			||||||
        pdu["ack"] = true;
 | 
					        pdu["ack"] = true;
 | 
				
			||||||
        pdu["id"] = data["id"];
 | 
					        pdu["id"] = data["id"];
 | 
				
			||||||
@@ -211,11 +206,6 @@ namespace ix
 | 
				
			|||||||
                    handleMessage(str);
 | 
					                    handleMessage(str);
 | 
				
			||||||
                    _condition.notify_one();
 | 
					                    _condition.notify_one();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    ss << "ws_receive: received fragment";
 | 
					 | 
				
			||||||
                    log(ss.str());
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
					                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    ss << "Connection error: " << error.reason      << std::endl;
 | 
					                    ss << "Connection error: " << error.reason      << std::endl;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -257,15 +257,6 @@ namespace ix
 | 
				
			|||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            size_t bufferedAmount = _webSocket.bufferedAmount();
 | 
					 | 
				
			||||||
            std::cout << bufferedAmount << " bytes left to be sent" << std::endl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            std::chrono::duration<double, std::milli> duration(10);
 | 
					 | 
				
			||||||
            std::this_thread::sleep_for(duration);
 | 
					 | 
				
			||||||
        } while (_webSocket.bufferedAmount() != 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bench.report();
 | 
					        bench.report();
 | 
				
			||||||
        auto duration = bench.getDuration();
 | 
					        auto duration = bench.getDuration();
 | 
				
			||||||
        auto transferRate = 1000 * content.size() / duration;
 | 
					        auto transferRate = 1000 * content.size() / duration;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,11 +10,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ws_transfer_main(int port, const std::string& hostname)
 | 
					    int ws_transfer_main(int port)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << "Listening on " << hostname << ":" << port << std::endl;
 | 
					        std::cout << "Listening on port " << port << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ix::WebSocketServer server(port, hostname);
 | 
					        ix::WebSocketServer server(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        server.setOnConnectionCallback(
 | 
					        server.setOnConnectionCallback(
 | 
				
			||||||
            [&server](std::shared_ptr<ix::WebSocket> webSocket)
 | 
					            [&server](std::shared_ptr<ix::WebSocket> webSocket)
 | 
				
			||||||
@@ -39,22 +39,7 @@ namespace ix
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::cerr << "Closed connection"
 | 
					                            std::cerr << "Closed connection" << std::endl;
 | 
				
			||||||
                                      << " code " << closeInfo.code
 | 
					 | 
				
			||||||
                                      << " reason " << closeInfo.reason << std::endl;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Error)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            std::stringstream ss;
 | 
					 | 
				
			||||||
                            ss << "Connection error: " << error.reason      << std::endl;
 | 
					 | 
				
			||||||
                            ss << "#retries: "         << error.retries     << std::endl;
 | 
					 | 
				
			||||||
                            ss << "Wait time(ms): "    << error.wait_time   << std::endl;
 | 
					 | 
				
			||||||
                            ss << "HTTP Status: "      << error.http_status << std::endl;
 | 
					 | 
				
			||||||
                            std::cerr << ss.str();
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            std::cerr << "Received message fragment" << std::endl;
 | 
					 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
@@ -63,22 +48,7 @@ namespace ix
 | 
				
			|||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                if (client != webSocket)
 | 
					                                if (client != webSocket)
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
                                    client->send(str,
 | 
					                                    client->send(str);
 | 
				
			||||||
                                                 [](int current, int total) -> bool
 | 
					 | 
				
			||||||
                                    {
 | 
					 | 
				
			||||||
                                        std::cerr << "Step " << current
 | 
					 | 
				
			||||||
                                                  << " out of " << total << std::endl;
 | 
					 | 
				
			||||||
                                        return true;
 | 
					 | 
				
			||||||
                                    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                    do
 | 
					 | 
				
			||||||
                                    {
 | 
					 | 
				
			||||||
                                        size_t bufferedAmount = client->bufferedAmount();
 | 
					 | 
				
			||||||
                                        std::cerr << bufferedAmount << " bytes left to be sent" << std::endl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                        std::chrono::duration<double, std::milli> duration(10);
 | 
					 | 
				
			||||||
                                        std::this_thread::sleep_for(duration);
 | 
					 | 
				
			||||||
                                    } while (client->bufferedAmount() != 0);
 | 
					 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user