reformat everything with clang-format
This commit is contained in:
		| @@ -10,14 +10,13 @@ | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     CancellationRequest makeCancellationRequestWithTimeout(int secs, | ||||
|                                                            std::atomic<bool>& requestInitCancellation) | ||||
|     CancellationRequest makeCancellationRequestWithTimeout( | ||||
|         int secs, std::atomic<bool>& requestInitCancellation) | ||||
|     { | ||||
|         auto start = std::chrono::system_clock::now(); | ||||
|         auto timeout = std::chrono::seconds(secs); | ||||
|  | ||||
|         auto isCancellationRequested = [&requestInitCancellation, start, timeout]() -> bool | ||||
|         { | ||||
|         auto isCancellationRequested = [&requestInitCancellation, start, timeout]() -> bool { | ||||
|             // Was an explicit cancellation requested ? | ||||
|             if (requestInitCancellation) return true; | ||||
|  | ||||
| @@ -30,4 +29,4 @@ namespace ix | ||||
|  | ||||
|         return isCancellationRequested; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -10,7 +10,8 @@ namespace ix | ||||
| { | ||||
|     std::atomic<uint64_t> ConnectionState::_globalId(0); | ||||
|  | ||||
|     ConnectionState::ConnectionState() : _terminated(false) | ||||
|     ConnectionState::ConnectionState() | ||||
|         : _terminated(false) | ||||
|     { | ||||
|         computeId(); | ||||
|     } | ||||
| @@ -39,5 +40,4 @@ namespace ix | ||||
|     { | ||||
|         _terminated = true; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,22 +5,22 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXDNSLookup.h" | ||||
| #include "IXNetSystem.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include "IXNetSystem.h" | ||||
| #include <chrono> | ||||
| #include <string.h> | ||||
| #include <thread> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     const int64_t DNSLookup::kDefaultWait = 1; // ms | ||||
|  | ||||
|     DNSLookup::DNSLookup(const std::string& hostname, int port, int64_t wait) : | ||||
|         _hostname(hostname), | ||||
|         _port(port), | ||||
|         _wait(wait), | ||||
|         _res(nullptr), | ||||
|         _done(false) | ||||
|     DNSLookup::DNSLookup(const std::string& hostname, int port, int64_t wait) | ||||
|         : _hostname(hostname) | ||||
|         , _port(port) | ||||
|         , _wait(wait) | ||||
|         , _res(nullptr) | ||||
|         , _done(false) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -38,8 +38,7 @@ namespace ix | ||||
|         std::string sport = std::to_string(port); | ||||
|  | ||||
|         struct addrinfo* res; | ||||
|         int getaddrinfo_result = getaddrinfo(hostname.c_str(), sport.c_str(), | ||||
|                                              &hints, &res); | ||||
|         int getaddrinfo_result = getaddrinfo(hostname.c_str(), sport.c_str(), &hints, &res); | ||||
|         if (getaddrinfo_result) | ||||
|         { | ||||
|             errMsg = gai_strerror(getaddrinfo_result); | ||||
| @@ -56,8 +55,8 @@ namespace ix | ||||
|                            : resolveUnCancellable(errMsg, isCancellationRequested); | ||||
|     } | ||||
|  | ||||
|     struct addrinfo* DNSLookup::resolveUnCancellable(std::string& errMsg, | ||||
|                                                      const CancellationRequest& isCancellationRequested) | ||||
|     struct addrinfo* DNSLookup::resolveUnCancellable( | ||||
|         std::string& errMsg, const CancellationRequest& isCancellationRequested) | ||||
|     { | ||||
|         errMsg = "no error"; | ||||
|  | ||||
| @@ -71,8 +70,8 @@ namespace ix | ||||
|         return getAddrInfo(_hostname, _port, errMsg); | ||||
|     } | ||||
|  | ||||
|     struct addrinfo* DNSLookup::resolveCancellable(std::string& errMsg, | ||||
|                                                    const CancellationRequest& isCancellationRequested) | ||||
|     struct addrinfo* DNSLookup::resolveCancellable( | ||||
|         std::string& errMsg, const CancellationRequest& isCancellationRequested) | ||||
|     { | ||||
|         errMsg = "no error"; | ||||
|  | ||||
| @@ -126,7 +125,9 @@ namespace ix | ||||
|         return getRes(); | ||||
|     } | ||||
|  | ||||
|     void DNSLookup::run(std::weak_ptr<DNSLookup> self, std::string hostname, int port) // thread runner | ||||
|     void DNSLookup::run(std::weak_ptr<DNSLookup> self, | ||||
|                         std::string hostname, | ||||
|                         int port) // thread runner | ||||
|     { | ||||
|         // We don't want to read or write into members variables of an object that could be | ||||
|         // gone, so we use temporary variables (res) or we pass in by copy everything that | ||||
| @@ -167,4 +168,4 @@ namespace ix | ||||
|         std::lock_guard<std::mutex> lock(_resMutex); | ||||
|         return _res; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -10,8 +10,7 @@ | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     uint32_t calculateRetryWaitMilliseconds( | ||||
|         uint32_t retry_count, | ||||
|     uint32_t calculateRetryWaitMilliseconds(uint32_t retry_count, | ||||
|                                             uint32_t maxWaitBetweenReconnectionRetries) | ||||
|     { | ||||
|         uint32_t wait_time = std::pow(2, retry_count) * 100; | ||||
| @@ -23,4 +22,4 @@ namespace ix | ||||
|  | ||||
|         return wait_time; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     uint32_t calculateRetryWaitMilliseconds( | ||||
|         uint32_t retry_count, | ||||
|     uint32_t calculateRetryWaitMilliseconds(uint32_t retry_count, | ||||
|                                             uint32_t maxWaitBetweenReconnectionRetries); | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,9 +5,9 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXHttp.h" | ||||
|  | ||||
| #include "IXCancellationRequest.h" | ||||
| #include "IXSocket.h" | ||||
|  | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| @@ -57,7 +57,8 @@ namespace ix | ||||
|         return std::make_pair(httpVersion, statusCode); | ||||
|     } | ||||
|  | ||||
|     std::tuple<std::string, std::string, std::string> Http::parseRequestLine(const std::string& line) | ||||
|     std::tuple<std::string, std::string, std::string> Http::parseRequestLine( | ||||
|         const std::string& line) | ||||
|     { | ||||
|         // Request-Line   = Method SP Request-URI SP HTTP-Version CRLF | ||||
|         std::string token; | ||||
| @@ -161,8 +162,6 @@ namespace ix | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return response->payload.empty() | ||||
|             ? true | ||||
|             : socket->writeBytes(response->payload, nullptr); | ||||
|     } | ||||
|         return response->payload.empty() ? true : socket->writeBytes(response->payload, nullptr); | ||||
|     } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -115,8 +115,7 @@ namespace ix | ||||
|             std::shared_ptr<Socket> socket); | ||||
|         static bool sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket); | ||||
|  | ||||
|         static std::pair<std::string, int> parseStatusLine( | ||||
|             const std::string& line); | ||||
|         static std::pair<std::string, int> parseStatusLine(const std::string& line); | ||||
|         static std::tuple<std::string, std::string, std::string> parseRequestLine( | ||||
|             const std::string& line); | ||||
|         static std::string trim(const std::string& str); | ||||
|   | ||||
| @@ -5,17 +5,16 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXHttpClient.h" | ||||
|  | ||||
| #include "IXSocketFactory.h" | ||||
| #include "IXUrlParser.h" | ||||
| #include "IXUserAgent.h" | ||||
| #include "IXWebSocketHttpHeaders.h" | ||||
| #include "IXSocketFactory.h" | ||||
|  | ||||
| #include <sstream> | ||||
| #include <iomanip> | ||||
| #include <vector> | ||||
| #include <cstring> | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <cstring> | ||||
| #include <iomanip> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
| #include <zlib.h> | ||||
|  | ||||
| namespace ix | ||||
| @@ -26,7 +25,9 @@ namespace ix | ||||
|     const std::string HttpClient::kDel = "DEL"; | ||||
|     const std::string HttpClient::kPut = "PUT"; | ||||
|  | ||||
|     HttpClient::HttpClient(bool async) : _async(async), _stop(false) | ||||
|     HttpClient::HttpClient(bool async) | ||||
|         : _async(async) | ||||
|         , _stop(false) | ||||
|     { | ||||
|         if (!_async) return; | ||||
|  | ||||
| @@ -42,8 +43,7 @@ namespace ix | ||||
|         _thread.join(); | ||||
|     } | ||||
|  | ||||
|     HttpRequestArgsPtr HttpClient::createRequest(const std::string& url, | ||||
|                                                  const std::string& verb) | ||||
|     HttpRequestArgsPtr HttpClient::createRequest(const std::string& url, const std::string& verb) | ||||
|     { | ||||
|         auto request = std::make_shared<HttpRequestArgs>(); | ||||
|         request->url = url; | ||||
| @@ -106,8 +106,7 @@ namespace ix | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     HttpResponsePtr HttpClient::request( | ||||
|         const std::string& url, | ||||
|     HttpResponsePtr HttpClient::request(const std::string& url, | ||||
|                                         const std::string& verb, | ||||
|                                         const std::string& body, | ||||
|                                         HttpRequestArgsPtr args, | ||||
| @@ -131,9 +130,14 @@ namespace ix | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "Cannot parse url: " << url; | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::UrlMalformed, | ||||
|                                                   headers, payload, ss.str(), | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::UrlMalformed, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   ss.str(), | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         bool tls = protocol == "https"; | ||||
| @@ -143,9 +147,14 @@ namespace ix | ||||
|  | ||||
|         if (!_socket) | ||||
|         { | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::CannotCreateSocket, | ||||
|                                                   headers, payload, errorMsg, | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::CannotCreateSocket, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   errorMsg, | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         // Build request string | ||||
| @@ -155,7 +164,8 @@ namespace ix | ||||
|  | ||||
|         if (args->compress) | ||||
|         { | ||||
|             ss << "Accept-Encoding: gzip" << "\r\n"; | ||||
|             ss << "Accept-Encoding: gzip" | ||||
|                << "\r\n"; | ||||
|         } | ||||
|  | ||||
|         // Append extra headers | ||||
| @@ -167,7 +177,8 @@ namespace ix | ||||
|         // Set a default Accept header if none is present | ||||
|         if (headers.find("Accept") == headers.end()) | ||||
|         { | ||||
|             ss << "Accept: */*" << "\r\n"; | ||||
|             ss << "Accept: */*" | ||||
|                << "\r\n"; | ||||
|         } | ||||
|  | ||||
|         // Set a default User agent if none is present | ||||
| @@ -183,7 +194,8 @@ namespace ix | ||||
|             // Set default Content-Type if unspecified | ||||
|             if (args->extraHeaders.find("Content-Type") == args->extraHeaders.end()) | ||||
|             { | ||||
|                 ss << "Content-Type: application/x-www-form-urlencoded" << "\r\n"; | ||||
|                 ss << "Content-Type: application/x-www-form-urlencoded" | ||||
|                    << "\r\n"; | ||||
|             } | ||||
|             ss << "\r\n"; | ||||
|             ss << body; | ||||
| @@ -206,9 +218,14 @@ namespace ix | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "Cannot connect to url: " << url << " / error : " << errMsg; | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::CannotConnect, | ||||
|                                                   headers, payload, ss.str(), | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::CannotConnect, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   ss.str(), | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         // Make a new cancellation object dealing with transfer timeout | ||||
| @@ -222,8 +239,7 @@ namespace ix | ||||
|                << "to " << host << ":" << port << std::endl | ||||
|                << "request size: " << req.size() << " bytes" << std::endl | ||||
|                << "=============" << std::endl | ||||
|                << req | ||||
|                << "=============" << std::endl | ||||
|                << req << "=============" << std::endl | ||||
|                << std::endl; | ||||
|  | ||||
|             log(ss.str(), args); | ||||
| @@ -232,9 +248,14 @@ namespace ix | ||||
|         if (!_socket->writeBytes(req, isCancellationRequested)) | ||||
|         { | ||||
|             std::string errorMsg("Cannot send request"); | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::SendError, | ||||
|                                                   headers, payload, errorMsg, | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::SendError, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   errorMsg, | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         uploadSize = req.size(); | ||||
| @@ -246,9 +267,14 @@ namespace ix | ||||
|         if (!lineValid) | ||||
|         { | ||||
|             std::string errorMsg("Cannot retrieve status line"); | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::CannotReadStatusLine, | ||||
|                                                   headers, payload, errorMsg, | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::CannotReadStatusLine, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   errorMsg, | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         if (args->verbose) | ||||
| @@ -261,9 +287,14 @@ namespace ix | ||||
|         if (sscanf(line.c_str(), "HTTP/1.1 %d", &code) != 1) | ||||
|         { | ||||
|             std::string errorMsg("Cannot parse response code from status line"); | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::MissingStatus, | ||||
|                                                   headers, payload, errorMsg, | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::MissingStatus, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   errorMsg, | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         auto result = parseHttpHeaders(_socket, isCancellationRequested); | ||||
| @@ -273,9 +304,14 @@ namespace ix | ||||
|         if (!headersValid) | ||||
|         { | ||||
|             std::string errorMsg("Cannot parse http headers"); | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::HeaderParsingError, | ||||
|                                                   headers, payload, errorMsg, | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::HeaderParsingError, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   errorMsg, | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         // Redirect ? | ||||
| @@ -284,18 +320,28 @@ namespace ix | ||||
|             if (headers.find("Location") == headers.end()) | ||||
|             { | ||||
|                 std::string errorMsg("Missing location header for redirect"); | ||||
|                 return std::make_shared<HttpResponse>(code, description, HttpErrorCode::MissingLocation, | ||||
|                                                       headers, payload, errorMsg, | ||||
|                                                       uploadSize, downloadSize); | ||||
|                 return std::make_shared<HttpResponse>(code, | ||||
|                                                       description, | ||||
|                                                       HttpErrorCode::MissingLocation, | ||||
|                                                       headers, | ||||
|                                                       payload, | ||||
|                                                       errorMsg, | ||||
|                                                       uploadSize, | ||||
|                                                       downloadSize); | ||||
|             } | ||||
|  | ||||
|             if (redirects >= args->maxRedirects) | ||||
|             { | ||||
|                 std::stringstream ss; | ||||
|                 ss << "Too many redirects: " << redirects; | ||||
|                 return std::make_shared<HttpResponse>(code, description, HttpErrorCode::TooManyRedirects, | ||||
|                                                       headers, payload, ss.str(), | ||||
|                                                       uploadSize, downloadSize); | ||||
|                 return std::make_shared<HttpResponse>(code, | ||||
|                                                       description, | ||||
|                                                       HttpErrorCode::TooManyRedirects, | ||||
|                                                       headers, | ||||
|                                                       payload, | ||||
|                                                       ss.str(), | ||||
|                                                       uploadSize, | ||||
|                                                       downloadSize); | ||||
|             } | ||||
|  | ||||
|             // Recurse | ||||
| @@ -305,9 +351,14 @@ namespace ix | ||||
|  | ||||
|         if (verb == "HEAD") | ||||
|         { | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::Ok, | ||||
|                                                   headers, payload, std::string(), | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::Ok, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   std::string(), | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         // Parse response: | ||||
| @@ -320,15 +371,19 @@ namespace ix | ||||
|  | ||||
|             payload.reserve(contentLength); | ||||
|  | ||||
|             auto chunkResult = _socket->readBytes(contentLength, | ||||
|                                                   args->onProgressCallback, | ||||
|                                                   isCancellationRequested); | ||||
|             auto chunkResult = _socket->readBytes( | ||||
|                 contentLength, args->onProgressCallback, isCancellationRequested); | ||||
|             if (!chunkResult.first) | ||||
|             { | ||||
|                 errorMsg = "Cannot read chunk"; | ||||
|                 return std::make_shared<HttpResponse>(code, description, HttpErrorCode::ChunkReadError, | ||||
|                                                       headers, payload, errorMsg, | ||||
|                                                       uploadSize, downloadSize); | ||||
|                 return std::make_shared<HttpResponse>(code, | ||||
|                                                       description, | ||||
|                                                       HttpErrorCode::ChunkReadError, | ||||
|                                                       headers, | ||||
|                                                       payload, | ||||
|                                                       errorMsg, | ||||
|                                                       uploadSize, | ||||
|                                                       downloadSize); | ||||
|             } | ||||
|             payload += chunkResult.second; | ||||
|         } | ||||
| @@ -344,9 +399,14 @@ namespace ix | ||||
|  | ||||
|                 if (!lineResult.first) | ||||
|                 { | ||||
|                     return std::make_shared<HttpResponse>(code, description, HttpErrorCode::ChunkReadError, | ||||
|                                                           headers, payload, errorMsg, | ||||
|                                                           uploadSize, downloadSize); | ||||
|                     return std::make_shared<HttpResponse>(code, | ||||
|                                                           description, | ||||
|                                                           HttpErrorCode::ChunkReadError, | ||||
|                                                           headers, | ||||
|                                                           payload, | ||||
|                                                           errorMsg, | ||||
|                                                           uploadSize, | ||||
|                                                           downloadSize); | ||||
|                 } | ||||
|  | ||||
|                 uint64_t chunkSize; | ||||
| @@ -357,23 +417,26 @@ namespace ix | ||||
|                 if (args->verbose) | ||||
|                 { | ||||
|                     std::stringstream oss; | ||||
|                     oss << "Reading " << chunkSize << " bytes" | ||||
|                         << std::endl; | ||||
|                     oss << "Reading " << chunkSize << " bytes" << std::endl; | ||||
|                     log(oss.str(), args); | ||||
|                 } | ||||
|  | ||||
|                 payload.reserve(payload.size() + (size_t) chunkSize); | ||||
|  | ||||
|                 // Read a chunk | ||||
|                 auto chunkResult = _socket->readBytes((size_t) chunkSize, | ||||
|                                                       args->onProgressCallback, | ||||
|                                                       isCancellationRequested); | ||||
|                 auto chunkResult = _socket->readBytes( | ||||
|                     (size_t) chunkSize, args->onProgressCallback, isCancellationRequested); | ||||
|                 if (!chunkResult.first) | ||||
|                 { | ||||
|                     errorMsg = "Cannot read chunk"; | ||||
|                     return std::make_shared<HttpResponse>(code, description, HttpErrorCode::ChunkReadError, | ||||
|                                                           headers, payload, errorMsg, | ||||
|                                                           uploadSize, downloadSize); | ||||
|                     return std::make_shared<HttpResponse>(code, | ||||
|                                                           description, | ||||
|                                                           HttpErrorCode::ChunkReadError, | ||||
|                                                           headers, | ||||
|                                                           payload, | ||||
|                                                           errorMsg, | ||||
|                                                           uploadSize, | ||||
|                                                           downloadSize); | ||||
|                 } | ||||
|                 payload += chunkResult.second; | ||||
|  | ||||
| @@ -382,9 +445,14 @@ namespace ix | ||||
|  | ||||
|                 if (!lineResult.first) | ||||
|                 { | ||||
|                     return std::make_shared<HttpResponse>(code, description, HttpErrorCode::ChunkReadError, | ||||
|                                                           headers, payload, errorMsg, | ||||
|                                                           uploadSize, downloadSize); | ||||
|                     return std::make_shared<HttpResponse>(code, | ||||
|                                                           description, | ||||
|                                                           HttpErrorCode::ChunkReadError, | ||||
|                                                           headers, | ||||
|                                                           payload, | ||||
|                                                           errorMsg, | ||||
|                                                           uploadSize, | ||||
|                                                           downloadSize); | ||||
|                 } | ||||
|  | ||||
|                 if (chunkSize == 0) break; | ||||
| @@ -397,9 +465,14 @@ namespace ix | ||||
|         else | ||||
|         { | ||||
|             std::string errorMsg("Cannot read http body"); | ||||
|             return std::make_shared<HttpResponse>(code, description, HttpErrorCode::CannotReadBody, | ||||
|                                                   headers, payload, errorMsg, | ||||
|                                                   uploadSize, downloadSize); | ||||
|             return std::make_shared<HttpResponse>(code, | ||||
|                                                   description, | ||||
|                                                   HttpErrorCode::CannotReadBody, | ||||
|                                                   headers, | ||||
|                                                   payload, | ||||
|                                                   errorMsg, | ||||
|                                                   uploadSize, | ||||
|                                                   downloadSize); | ||||
|         } | ||||
|  | ||||
|         downloadSize = payload.size(); | ||||
| @@ -411,32 +484,39 @@ namespace ix | ||||
|             if (!gzipInflate(payload, decompressedPayload)) | ||||
|             { | ||||
|                 std::string errorMsg("Error decompressing payload"); | ||||
|                 return std::make_shared<HttpResponse>(code, description, HttpErrorCode::Gzip, | ||||
|                                                       headers, payload, errorMsg, | ||||
|                                                       uploadSize, downloadSize); | ||||
|                 return std::make_shared<HttpResponse>(code, | ||||
|                                                       description, | ||||
|                                                       HttpErrorCode::Gzip, | ||||
|                                                       headers, | ||||
|                                                       payload, | ||||
|                                                       errorMsg, | ||||
|                                                       uploadSize, | ||||
|                                                       downloadSize); | ||||
|             } | ||||
|             payload = decompressedPayload; | ||||
|         } | ||||
|  | ||||
|         return std::make_shared<HttpResponse>(code, description, HttpErrorCode::Ok, | ||||
|                                               headers, payload, std::string(), | ||||
|                                               uploadSize, downloadSize); | ||||
|         return std::make_shared<HttpResponse>(code, | ||||
|                                               description, | ||||
|                                               HttpErrorCode::Ok, | ||||
|                                               headers, | ||||
|                                               payload, | ||||
|                                               std::string(), | ||||
|                                               uploadSize, | ||||
|                                               downloadSize); | ||||
|     } | ||||
|  | ||||
|     HttpResponsePtr HttpClient::get(const std::string& url, | ||||
|                                     HttpRequestArgsPtr args) | ||||
|     HttpResponsePtr HttpClient::get(const std::string& url, HttpRequestArgsPtr args) | ||||
|     { | ||||
|         return request(url, kGet, std::string(), args); | ||||
|     } | ||||
|  | ||||
|     HttpResponsePtr HttpClient::head(const std::string& url, | ||||
|                                      HttpRequestArgsPtr args) | ||||
|     HttpResponsePtr HttpClient::head(const std::string& url, HttpRequestArgsPtr args) | ||||
|     { | ||||
|         return request(url, kHead, std::string(), args); | ||||
|     } | ||||
|  | ||||
|     HttpResponsePtr HttpClient::del(const std::string& url, | ||||
|                                     HttpRequestArgsPtr args) | ||||
|     HttpResponsePtr HttpClient::del(const std::string& url, HttpRequestArgsPtr args) | ||||
|     { | ||||
|         return request(url, kDel, std::string(), args); | ||||
|     } | ||||
| @@ -475,8 +555,7 @@ namespace ix | ||||
|         escaped.fill('0'); | ||||
|         escaped << std::hex; | ||||
|  | ||||
|         for (std::string::const_iterator i = value.begin(), n = value.end(); | ||||
|              i != n; ++i) | ||||
|         for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) | ||||
|         { | ||||
|             std::string::value_type c = (*i); | ||||
|  | ||||
| @@ -504,9 +583,7 @@ namespace ix | ||||
|  | ||||
|         for (auto&& it : httpParameters) | ||||
|         { | ||||
|             ss << urlEncode(it.first) | ||||
|                << "=" | ||||
|                << urlEncode(it.second); | ||||
|             ss << urlEncode(it.first) << "=" << urlEncode(it.second); | ||||
|  | ||||
|             if (i++ < (count - 1)) | ||||
|             { | ||||
| @@ -516,9 +593,7 @@ namespace ix | ||||
|         return ss.str(); | ||||
|     } | ||||
|  | ||||
|     bool HttpClient::gzipInflate( | ||||
|         const std::string& in, | ||||
|         std::string& out) | ||||
|     bool HttpClient::gzipInflate(const std::string& in, std::string& out) | ||||
|     { | ||||
|         z_stream inflateState; | ||||
|         std::memset(&inflateState, 0, sizeof(inflateState)); | ||||
| @@ -555,22 +630,19 @@ namespace ix | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             out.append( | ||||
|                 reinterpret_cast<char *>(compressBuffer.get()), | ||||
|                 kBufferSize - inflateState.avail_out | ||||
|             ); | ||||
|             out.append(reinterpret_cast<char*>(compressBuffer.get()), | ||||
|                        kBufferSize - inflateState.avail_out); | ||||
|         } while (inflateState.avail_out == 0); | ||||
|  | ||||
|         inflateEnd(&inflateState); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     void HttpClient::log(const std::string& msg, | ||||
|                          HttpRequestArgsPtr args) | ||||
|     void HttpClient::log(const std::string& msg, HttpRequestArgsPtr args) | ||||
|     { | ||||
|         if (args->logger) | ||||
|         { | ||||
|             args->logger(msg); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,13 +5,13 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXHttpServer.h" | ||||
|  | ||||
| #include "IXNetSystem.h" | ||||
| #include "IXSocketConnect.h" | ||||
| #include "IXSocketFactory.h" | ||||
| #include "IXNetSystem.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <fstream> | ||||
| #include <vector> | ||||
|  | ||||
| namespace | ||||
| @@ -39,15 +39,13 @@ namespace | ||||
|         auto vec = res.second; | ||||
|         return std::make_pair(res.first, std::string(vec.begin(), vec.end())); | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     HttpServer::HttpServer(int port, | ||||
|                            const std::string& host, | ||||
|                            int backlog, | ||||
|                            size_t maxConnections) : SocketServer(port, host, backlog, maxConnections), | ||||
|         _connectedClientsCount(0) | ||||
|     HttpServer::HttpServer(int port, const std::string& host, int backlog, size_t maxConnections) | ||||
|         : SocketServer(port, host, backlog, maxConnections) | ||||
|         , _connectedClientsCount(0) | ||||
|     { | ||||
|         setDefaultConnectionCallback(); | ||||
|     } | ||||
| @@ -71,9 +69,7 @@ namespace ix | ||||
|         _onConnectionCallback = callback; | ||||
|     } | ||||
|  | ||||
|     void HttpServer::handleConnection( | ||||
|         int fd, | ||||
|         std::shared_ptr<ConnectionState> connectionState) | ||||
|     void HttpServer::handleConnection(int fd, std::shared_ptr<ConnectionState> connectionState) | ||||
|     { | ||||
|         _connectedClientsCount++; | ||||
|  | ||||
| @@ -109,8 +105,7 @@ namespace ix | ||||
|     { | ||||
|         setOnConnectionCallback( | ||||
|             [this](HttpRequestPtr request, | ||||
|                    std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr | ||||
|             { | ||||
|                    std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr { | ||||
|                 std::string uri(request->uri); | ||||
|                 if (uri.empty() || uri == "/") | ||||
|                 { | ||||
| @@ -122,23 +117,16 @@ namespace ix | ||||
|                 bool found = res.first; | ||||
|                 if (!found) | ||||
|                 { | ||||
|                     return std::make_shared<HttpResponse>(404, "Not Found", | ||||
|                                                           HttpErrorCode::Ok, | ||||
|                                                           WebSocketHttpHeaders(), | ||||
|                                                           std::string()); | ||||
|                     return std::make_shared<HttpResponse>( | ||||
|                         404, "Not Found", HttpErrorCode::Ok, WebSocketHttpHeaders(), std::string()); | ||||
|                 } | ||||
|  | ||||
|                 std::string content = res.second; | ||||
|  | ||||
|                 // Log request | ||||
|                 std::stringstream ss; | ||||
|                 ss << request->method | ||||
|                    << " " | ||||
|                    << request->headers["User-Agent"] | ||||
|                    << " " | ||||
|                    << request->uri | ||||
|                    << " " | ||||
|                    << content.size(); | ||||
|                 ss << request->method << " " << request->headers["User-Agent"] << " " | ||||
|                    << request->uri << " " << content.size(); | ||||
|                 logInfo(ss.str()); | ||||
|  | ||||
|                 WebSocketHttpHeaders headers; | ||||
| @@ -151,11 +139,8 @@ namespace ix | ||||
|                     headers[it.first] = it.second; | ||||
|                 } | ||||
|  | ||||
|                 return std::make_shared<HttpResponse>(200, "OK", | ||||
|                                                       HttpErrorCode::Ok, | ||||
|                                                       headers, | ||||
|                                                       content); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|                 return std::make_shared<HttpResponse>( | ||||
|                     200, "OK", HttpErrorCode::Ok, headers, content); | ||||
|             }); | ||||
|     } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -77,8 +77,7 @@ namespace ix | ||||
|         tv.tv_sec = timeout / 1000; | ||||
|         tv.tv_usec = (timeout % 1000) * 1000; | ||||
|  | ||||
|         int ret = select(maxfd + 1, &readfds, &writefds, &errorfds, | ||||
|                          timeout != -1 ? &tv : NULL); | ||||
|         int ret = select(maxfd + 1, &readfds, &writefds, &errorfds, timeout != -1 ? &tv : NULL); | ||||
|  | ||||
|         if (ret < 0) | ||||
|         { | ||||
|   | ||||
| @@ -42,5 +42,4 @@ namespace ix | ||||
|     { | ||||
|         return -1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -26,14 +26,13 @@ | ||||
|  | ||||
| #include "IXSelectInterruptEventFd.h" | ||||
|  | ||||
| #include <sys/eventfd.h> | ||||
|  | ||||
| #include <unistd.h> // for write | ||||
| #include <string.h> // for strerror | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <assert.h> | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <sstream> | ||||
| #include <string.h> // for strerror | ||||
| #include <sys/eventfd.h> | ||||
| #include <unistd.h> // for write | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -113,4 +112,4 @@ namespace ix | ||||
|     { | ||||
|         return _eventfd; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -22,4 +22,4 @@ namespace ix | ||||
|         return std::make_shared<SelectInterrupt>(); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -10,12 +10,12 @@ | ||||
|  | ||||
| #include "IXSelectInterruptPipe.h" | ||||
|  | ||||
| #include <unistd.h> // for write | ||||
| #include <string.h> // for strerror | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <assert.h> | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <sstream> | ||||
| #include <string.h> // for strerror | ||||
| #include <unistd.h> // for write | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -143,4 +143,4 @@ namespace ix | ||||
|  | ||||
|         return _fildes[kPipeReadIndex]; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,21 +5,20 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXSocket.h" | ||||
| #include "IXSocketConnect.h" | ||||
|  | ||||
| #include "IXNetSystem.h" | ||||
| #include "IXSelectInterrupt.h" | ||||
| #include "IXSelectInterruptFactory.h" | ||||
|  | ||||
| #include "IXSocketConnect.h" | ||||
| #include <algorithm> | ||||
| #include <assert.h> | ||||
| #include <fcntl.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| #include <stdint.h> | ||||
| #include <fcntl.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| #ifdef min | ||||
| #undef min | ||||
| #endif | ||||
| @@ -32,9 +31,9 @@ namespace ix | ||||
|     const uint64_t Socket::kCloseRequest = 2; | ||||
|     constexpr size_t Socket::kChunkSize; | ||||
|  | ||||
|     Socket::Socket(int fd) : | ||||
|         _sockfd(fd), | ||||
|         _selectInterrupt(createSelectInterrupt()) | ||||
|     Socket::Socket(int fd) | ||||
|         : _sockfd(fd) | ||||
|         , _selectInterrupt(createSelectInterrupt()) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -123,8 +122,7 @@ namespace ix | ||||
|  | ||||
|             // getsockopt() puts the errno value for connect into optval so 0 | ||||
|             // means no-error. | ||||
|             if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1 || | ||||
|                 optval != 0) | ||||
|             if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1 || optval != 0) | ||||
|             { | ||||
|                 pollResult = PollResultType::Error; | ||||
|  | ||||
| @@ -292,8 +290,7 @@ namespace ix | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     bool Socket::readByte(void* buffer, | ||||
|                           const CancellationRequest& isCancellationRequested) | ||||
|     bool Socket::readByte(void* buffer, const CancellationRequest& isCancellationRequested) | ||||
|     { | ||||
|         while (true) | ||||
|         { | ||||
| @@ -369,9 +366,7 @@ namespace ix | ||||
|  | ||||
|             if (ret > 0) | ||||
|             { | ||||
|                 output.insert(output.end(), | ||||
|                               _readBuffer.begin(), | ||||
|                               _readBuffer.begin() + ret); | ||||
|                 output.insert(output.end(), _readBuffer.begin(), _readBuffer.begin() + ret); | ||||
|             } | ||||
|             else if (ret <= 0 && !Socket::isWaitNeeded()) | ||||
|             { | ||||
| @@ -388,7 +383,6 @@ namespace ix | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return std::make_pair(true, std::string(output.begin(), | ||||
|                                                 output.end())); | ||||
|     } | ||||
|         return std::make_pair(true, std::string(output.begin(), output.end())); | ||||
|     } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -6,11 +6,13 @@ | ||||
|  *  Adapted from Satori SDK Apple SSL code. | ||||
|  */ | ||||
| #include "IXSocketAppleSSL.h" | ||||
| #include "IXSocketConnect.h" | ||||
|  | ||||
| #include "IXSocketConnect.h" | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <netdb.h> | ||||
| #include <netinet/tcp.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| @@ -18,20 +20,16 @@ | ||||
| #include <sys/time.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #include <errno.h> | ||||
| #define socketerrno errno | ||||
|  | ||||
| #include <Security/SecureTransport.h> | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     OSStatus read_from_socket(SSLConnectionRef connection, void* data, size_t* len) | ||||
|     { | ||||
|         int fd = (int) (long) connection; | ||||
|     if (fd < 0) | ||||
|         return errSSLInternal; | ||||
|         if (fd < 0) return errSSLInternal; | ||||
|  | ||||
|         assert(data != nullptr); | ||||
|         assert(len != nullptr); | ||||
| @@ -56,18 +54,15 @@ OSStatus read_from_socket(SSLConnectionRef connection, void *data, size_t *len) | ||||
|         else | ||||
|         { | ||||
|             *len = 0; | ||||
|         switch (errno) { | ||||
|             case ENOENT: | ||||
|                 return errSSLClosedGraceful; | ||||
|             switch (errno) | ||||
|             { | ||||
|                 case ENOENT: return errSSLClosedGraceful; | ||||
|  | ||||
|             case EAGAIN: | ||||
|                 return errSSLWouldBlock; | ||||
|                 case EAGAIN: return errSSLWouldBlock; | ||||
|  | ||||
|             case ECONNRESET: | ||||
|                 return errSSLClosedAbort; | ||||
|                 case ECONNRESET: return errSSLClosedAbort; | ||||
|  | ||||
|             default: | ||||
|                 return errSecIO; | ||||
|                 default: return errSecIO; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -75,8 +70,7 @@ OSStatus read_from_socket(SSLConnectionRef connection, void *data, size_t *len) | ||||
|     OSStatus write_to_socket(SSLConnectionRef connection, const void* data, size_t* len) | ||||
|     { | ||||
|         int fd = (int) (long) connection; | ||||
|     if (fd < 0) | ||||
|         return errSSLInternal; | ||||
|         if (fd < 0) return errSSLInternal; | ||||
|  | ||||
|         assert(data != nullptr); | ||||
|         assert(len != nullptr); | ||||
| @@ -123,8 +117,8 @@ std::string getSSLErrorDescription(OSStatus status) | ||||
|             { | ||||
|                 char localBuffer[128]; | ||||
|                 Boolean success; | ||||
|             success = CFStringGetCString(message, localBuffer, 128, | ||||
|                                          CFStringGetSystemEncoding()); | ||||
|                 success = | ||||
|                     CFStringGetCString(message, localBuffer, 128, CFStringGetSystemEncoding()); | ||||
|                 if (success) | ||||
|                 { | ||||
|                     errMsg = localBuffer; | ||||
| @@ -141,9 +135,10 @@ std::string getSSLErrorDescription(OSStatus status) | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     SocketAppleSSL::SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd) : Socket(fd), | ||||
|         _sslContext(nullptr), | ||||
|         _tlsOptions(tlsOptions) | ||||
|     SocketAppleSSL::SocketAppleSSL(const SocketTLSOptions& tlsOptions, int fd) | ||||
|         : Socket(fd) | ||||
|         , _sslContext(nullptr) | ||||
|         , _tlsOptions(tlsOptions) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -173,10 +168,10 @@ namespace ix | ||||
|             SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12); | ||||
|             SSLSetPeerDomainName(_sslContext, host.c_str(), host.size()); | ||||
|  | ||||
|             do { | ||||
|             do | ||||
|             { | ||||
|                 status = SSLHandshake(_sslContext); | ||||
|             } while (errSSLWouldBlock == status || | ||||
|                      errSSLServerAuthCompleted == status); | ||||
|             } while (errSSLWouldBlock == status || errSSLServerAuthCompleted == status); | ||||
|         } | ||||
|  | ||||
|         if (noErr != status) | ||||
| @@ -206,7 +201,8 @@ namespace ix | ||||
|     { | ||||
|         ssize_t ret = 0; | ||||
|         OSStatus status; | ||||
|         do { | ||||
|         do | ||||
|         { | ||||
|             size_t processed = 0; | ||||
|             std::lock_guard<std::mutex> lock(_mutex); | ||||
|             status = SSLWrite(_sslContext, buf, nbyte, &processed); | ||||
| @@ -215,8 +211,7 @@ namespace ix | ||||
|             nbyte -= processed; | ||||
|         } while (nbyte > 0 && errSSLWouldBlock == status); | ||||
|  | ||||
|         if (ret == 0 && errSSLClosedAbort != status) | ||||
|             ret = -1; | ||||
|         if (ret == 0 && errSSLClosedAbort != status) ret = -1; | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
| @@ -235,13 +230,11 @@ namespace ix | ||||
|             std::lock_guard<std::mutex> lock(_mutex); | ||||
|             status = SSLRead(_sslContext, buf, nbyte, &processed); | ||||
|  | ||||
|             if (processed > 0) | ||||
|                 return (ssize_t) processed; | ||||
|             if (processed > 0) return (ssize_t) processed; | ||||
|  | ||||
|             // The connection was reset, inform the caller that this | ||||
|             // Socket should close | ||||
|             if (status == errSSLClosedGraceful || | ||||
|                 status == errSSLClosedNoNotify || | ||||
|             if (status == errSSLClosedGraceful || status == errSSLClosedNoNotify || | ||||
|                 status == errSSLClosedAbort) | ||||
|             { | ||||
|                 errno = ECONNRESET; | ||||
| @@ -257,4 +250,4 @@ namespace ix | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,12 +5,12 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXSocketConnect.h" | ||||
|  | ||||
| #include "IXDNSLookup.h" | ||||
| #include "IXNetSystem.h" | ||||
| #include "IXSocket.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <fcntl.h> | ||||
| #include <string.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| // Android needs extra headers for TCP_NODELAY and IPPROTO_TCP | ||||
| @@ -23,8 +23,8 @@ namespace ix | ||||
| { | ||||
|     // | ||||
|     // This function can be cancelled every 50 ms | ||||
|     // This is important so that we don't block the main UI thread when shutting down a connection which is | ||||
|     // already trying to reconnect, and can be blocked waiting for ::connect to respond. | ||||
|     // This is important so that we don't block the main UI thread when shutting down a connection | ||||
|     // which is already trying to reconnect, and can be blocked waiting for ::connect to respond. | ||||
|     // | ||||
|     int SocketConnect::connectToAddress(const struct addrinfo* address, | ||||
|                                         std::string& errMsg, | ||||
| @@ -32,9 +32,7 @@ namespace ix | ||||
|     { | ||||
|         errMsg = "no error"; | ||||
|  | ||||
|         int fd = socket(address->ai_family, | ||||
|                         address->ai_socktype, | ||||
|                         address->ai_protocol); | ||||
|         int fd = socket(address->ai_family, address->ai_socktype, address->ai_protocol); | ||||
|         if (fd < 0) | ||||
|         { | ||||
|             errMsg = "Cannot create a socket"; | ||||
| @@ -74,8 +72,7 @@ namespace ix | ||||
|             else if (pollResult == PollResultType::Error) | ||||
|             { | ||||
|                 Socket::closeSocket(fd); | ||||
|                 errMsg = std::string("Connect error: ") + | ||||
|                             strerror(Socket::getErrno()); | ||||
|                 errMsg = std::string("Connect error: ") + strerror(Socket::getErrno()); | ||||
|                 return -1; | ||||
|             } | ||||
|             else if (pollResult == PollResultType::ReadyForWrite) | ||||
| @@ -85,8 +82,7 @@ namespace ix | ||||
|             else | ||||
|             { | ||||
|                 Socket::closeSocket(fd); | ||||
|                 errMsg = std::string("Connect error: ") + | ||||
|                             strerror(Socket::getErrno()); | ||||
|                 errMsg = std::string("Connect error: ") + strerror(Socket::getErrno()); | ||||
|                 return -1; | ||||
|             } | ||||
|         } | ||||
| @@ -149,8 +145,7 @@ namespace ix | ||||
|         // 3. (apple) prevent SIGPIPE from being emitted when the remote end disconnect | ||||
| #ifdef SO_NOSIGPIPE | ||||
|         int value = 1; | ||||
|         setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, | ||||
|                    (void *)&value, sizeof(value)); | ||||
|         setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*) &value, sizeof(value)); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -7,15 +7,16 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "IXSocketTLSOptions.h" | ||||
| #include <memory> | ||||
| #include <string> | ||||
|  | ||||
| #include "IXSocketTLSOptions.h" | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     class Socket; | ||||
|     std::shared_ptr<Socket> createSocket(bool tls, std::string& errorMsg, const SocketTLSOptions& tlsOptions); | ||||
|     std::shared_ptr<Socket> createSocket(bool tls, | ||||
|                                          std::string& errorMsg, | ||||
|                                          const SocketTLSOptions& tlsOptions); | ||||
|  | ||||
|     std::shared_ptr<Socket> createSocket(int fd, std::string& errorMsg); | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -9,16 +9,16 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXSocketMbedTLS.h" | ||||
| #include "IXSocketConnect.h" | ||||
|  | ||||
| #include "IXNetSystem.h" | ||||
| #include "IXSocket.h" | ||||
|  | ||||
| #include "IXSocketConnect.h" | ||||
| #include <string.h> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions& tlsOptions) : | ||||
|         _tlsOptions(tlsOptions) | ||||
|     SocketMbedTLS::SocketMbedTLS(const SocketTLSOptions& tlsOptions) | ||||
|         : _tlsOptions(tlsOptions) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -102,8 +102,7 @@ namespace ix | ||||
|         { | ||||
|             std::lock_guard<std::mutex> lock(_mutex); | ||||
|             res = mbedtls_ssl_handshake(&_ssl); | ||||
|         } | ||||
|         while (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE); | ||||
|         } while (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE); | ||||
|  | ||||
|         if (res != 0) | ||||
|         { | ||||
| @@ -142,13 +141,18 @@ namespace ix | ||||
|  | ||||
|             ssize_t res = mbedtls_ssl_write(&_ssl, (unsigned char*) buf, nbyte); | ||||
|  | ||||
|             if (res > 0) { | ||||
|             if (res > 0) | ||||
|             { | ||||
|                 nbyte -= res; | ||||
|                 sent += res; | ||||
|             } else if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE) { | ||||
|             } | ||||
|             else if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE) | ||||
|             { | ||||
|                 errno = EWOULDBLOCK; | ||||
|                 return -1; | ||||
|             } else { | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return -1; | ||||
|             } | ||||
|         } | ||||
| @@ -181,4 +185,4 @@ namespace ix | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -121,7 +121,9 @@ namespace ix | ||||
|                 }); | ||||
|  | ||||
|                 SSL_CTX_set_verify_depth(ctx, 4); | ||||
|             } else { | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr); | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -13,12 +13,12 @@ | ||||
| #include "IXSocketSChannel.h" | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| # include <basetsd.h> | ||||
| # include <WinSock2.h> | ||||
| # include <ws2def.h> | ||||
| #include <WS2tcpip.h> | ||||
| # include <schannel.h> | ||||
| #include <WinSock2.h> | ||||
| #include <basetsd.h> | ||||
| #include <io.h> | ||||
| #include <schannel.h> | ||||
| #include <ws2def.h> | ||||
|  | ||||
| #define WIN32_LEAN_AND_MEAN | ||||
|  | ||||
| @@ -26,14 +26,15 @@ | ||||
| #define UNICODE | ||||
| #endif | ||||
|  | ||||
| #include <windows.h> | ||||
| #include <winsock2.h> | ||||
| #include <mstcpip.h> | ||||
| #include <ws2tcpip.h> | ||||
| #include <rpc.h> | ||||
| #include <ntdsapi.h> | ||||
| #include <rpc.h> | ||||
| #include <stdio.h> | ||||
| #include <tchar.h> | ||||
| #include <winsock2.h> | ||||
| #include <ws2tcpip.h> | ||||
|  | ||||
| #include <windows.h> | ||||
|  | ||||
| #define RECV_DATA_BUF_SIZE 256 | ||||
|  | ||||
| @@ -50,10 +51,6 @@ | ||||
| // has already been initialized | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #else | ||||
| #error("This file should only be built on Windows") | ||||
| #endif | ||||
| @@ -67,12 +64,9 @@ namespace ix | ||||
|  | ||||
|     SocketSChannel::~SocketSChannel() | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     bool SocketSChannel::connect(const std::string& host, | ||||
|                                  int port, | ||||
|                                  std::string& errMsg) | ||||
|     bool SocketSChannel::connect(const std::string& host, int port, std::string& errMsg) | ||||
|     { | ||||
|         return Socket::connect(host, port, errMsg, nullptr); | ||||
|     } | ||||
| @@ -103,4 +97,4 @@ namespace ix | ||||
|         return Socket::recv(buf, nbyte); | ||||
|     } | ||||
|  | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,14 +5,14 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXSocketServer.h" | ||||
|  | ||||
| #include "IXNetSystem.h" | ||||
| #include "IXSocket.h" | ||||
| #include "IXSocketConnect.h" | ||||
| #include "IXNetSystem.h" | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -24,17 +24,16 @@ namespace ix | ||||
|     SocketServer::SocketServer(int port, | ||||
|                                const std::string& host, | ||||
|                                int backlog, | ||||
|                                size_t maxConnections) : | ||||
|         _port(port), | ||||
|         _host(host), | ||||
|         _backlog(backlog), | ||||
|         _maxConnections(maxConnections), | ||||
|         _serverFd(-1), | ||||
|         _stop(false), | ||||
|         _stopGc(false), | ||||
|         _connectionStateFactory(&ConnectionState::createConnectionState) | ||||
|                                size_t maxConnections) | ||||
|         : _port(port) | ||||
|         , _host(host) | ||||
|         , _backlog(backlog) | ||||
|         , _maxConnections(maxConnections) | ||||
|         , _serverFd(-1) | ||||
|         , _stop(false) | ||||
|         , _stopGc(false) | ||||
|         , _connectionStateFactory(&ConnectionState::createConnectionState) | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     SocketServer::~SocketServer() | ||||
| @@ -62,21 +61,18 @@ namespace ix | ||||
|         if ((_serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "SocketServer::listen() error creating socket): " | ||||
|                << strerror(Socket::getErrno()); | ||||
|             ss << "SocketServer::listen() error creating socket): " << strerror(Socket::getErrno()); | ||||
|  | ||||
|             return std::make_pair(false, ss.str()); | ||||
|         } | ||||
|  | ||||
|         // Make that socket reusable. (allow restarting this server at will) | ||||
|         int enable = 1; | ||||
|         if (setsockopt(_serverFd, SOL_SOCKET, SO_REUSEADDR, | ||||
|                        (char*) &enable, sizeof(enable)) < 0) | ||||
|         if (setsockopt(_serverFd, SOL_SOCKET, SO_REUSEADDR, (char*) &enable, sizeof(enable)) < 0) | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "SocketServer::listen() error calling setsockopt(SO_REUSEADDR) " | ||||
|                << "at address " << _host << ":" << _port | ||||
|                << " : " << strerror(Socket::getErrno()); | ||||
|                << "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno()); | ||||
|  | ||||
|             Socket::closeSocket(_serverFd); | ||||
|             return std::make_pair(false, ss.str()); | ||||
| @@ -99,8 +95,7 @@ namespace ix | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "SocketServer::listen() error calling bind " | ||||
|                << "at address " << _host << ":" << _port | ||||
|                << " : " << strerror(Socket::getErrno()); | ||||
|                << "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno()); | ||||
|  | ||||
|             Socket::closeSocket(_serverFd); | ||||
|             return std::make_pair(false, ss.str()); | ||||
| @@ -113,8 +108,7 @@ namespace ix | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "SocketServer::listen() error calling listen " | ||||
|                << "at address " << _host << ":" << _port | ||||
|                << " : " << strerror(Socket::getErrno()); | ||||
|                << "at address " << _host << ":" << _port << " : " << strerror(Socket::getErrno()); | ||||
|  | ||||
|             Socket::closeSocket(_serverFd); | ||||
|             return std::make_pair(false, ss.str()); | ||||
| @@ -221,8 +215,7 @@ namespace ix | ||||
|             if (pollResult == PollResultType::Error) | ||||
|             { | ||||
|                 std::stringstream ss; | ||||
|                 ss << "SocketServer::run() error in select: " | ||||
|                    << strerror(Socket::getErrno()); | ||||
|                 ss << "SocketServer::run() error in select: " << strerror(Socket::getErrno()); | ||||
|                 logError(ss.str()); | ||||
|                 continue; | ||||
|             } | ||||
| @@ -245,8 +238,8 @@ namespace ix | ||||
|                     // FIXME: that error should be propagated | ||||
|                     int err = Socket::getErrno(); | ||||
|                     std::stringstream ss; | ||||
|                     ss << "SocketServer::run() error accepting connection: " | ||||
|                        << err << ", " << strerror(err); | ||||
|                     ss << "SocketServer::run() error accepting connection: " << err << ", " | ||||
|                        << strerror(err); | ||||
|                     logError(ss.str()); | ||||
|                 } | ||||
|                 continue; | ||||
| @@ -255,8 +248,7 @@ namespace ix | ||||
|             if (getConnectedClientsCount() >= _maxConnections) | ||||
|             { | ||||
|                 std::stringstream ss; | ||||
|                 ss << "SocketServer::run() reached max connections = " | ||||
|                    << _maxConnections << ". " | ||||
|                 ss << "SocketServer::run() reached max connections = " << _maxConnections << ". " | ||||
|                    << "Not accepting connection"; | ||||
|                 logError(ss.str()); | ||||
|  | ||||
| @@ -277,10 +269,7 @@ namespace ix | ||||
|             std::lock_guard<std::mutex> lock(_connectionsThreadsMutex); | ||||
|             _connectionsThreads.push_back(std::make_pair( | ||||
|                 connectionState, | ||||
|                     std::thread(&SocketServer::handleConnection, | ||||
|                                 this, | ||||
|                                 clientFd, | ||||
|                                 connectionState))); | ||||
|                 std::thread(&SocketServer::handleConnection, this, clientFd, connectionState))); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -308,5 +297,4 @@ namespace ix | ||||
|             std::this_thread::sleep_for(std::chrono::milliseconds(10)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,13 +4,14 @@ | ||||
|  *  Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <assert.h> | ||||
| #include "IXSocketTLSOptions.h" | ||||
|  | ||||
| #include <assert.h> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|  | ||||
|     SocketTLSOptions::SocketTLSOptions() { | ||||
|     SocketTLSOptions::SocketTLSOptions() | ||||
|     { | ||||
| #ifndef IXWEBSOCKET_USE_TLS | ||||
|         assert(false && "To use TLS features the library must be compiled with USE_TLS"); | ||||
| #endif | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXUrlParser.h" | ||||
|  | ||||
| #include "LUrlParser.h" | ||||
|  | ||||
| namespace ix | ||||
| @@ -64,4 +65,4 @@ namespace ix | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,8 +5,8 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXUserAgent.h" | ||||
| #include "IXWebSocketVersion.h" | ||||
|  | ||||
| #include "IXWebSocketVersion.h" | ||||
| #include <sstream> | ||||
| #include <zlib.h> | ||||
|  | ||||
| @@ -80,4 +80,4 @@ namespace ix | ||||
|  | ||||
|         return ss.str(); | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -48,20 +48,31 @@ namespace ix | ||||
|  | ||||
|     /// Lookup table for the UTF8 decode state machine | ||||
|     static uint8_t const utf8d[] = { | ||||
|       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f | ||||
|       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f | ||||
|       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f | ||||
|       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f | ||||
|       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f | ||||
|       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf | ||||
|       8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df | ||||
|         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, | ||||
|         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 00..1f | ||||
|         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, | ||||
|         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20..3f | ||||
|         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, | ||||
|         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 40..5f | ||||
|         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, | ||||
|         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 60..7f | ||||
|         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1, | ||||
|         9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9, // 80..9f | ||||
|         7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7, | ||||
|         7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7,   7, // a0..bf | ||||
|         8,   8,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2, | ||||
|         2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   // c0..df | ||||
|         0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef | ||||
|         0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff | ||||
|         0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 | ||||
|       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2 | ||||
|       1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4 | ||||
|       1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6 | ||||
|       1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 | ||||
|         1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1, | ||||
|         1,   0,   1,   1,   1,   1,   1,   0,   1,   0,   1,   1,   1,   1,   1,   1, // s1..s2 | ||||
|         1,   2,   1,   1,   1,   1,   1,   2,   1,   2,   1,   1,   1,   1,   1,   1, | ||||
|         1,   1,   1,   1,   1,   1,   1,   2,   1,   1,   1,   1,   1,   1,   1,   1, // s3..s4 | ||||
|         1,   2,   1,   1,   1,   1,   1,   1,   1,   2,   1,   1,   1,   1,   1,   1, | ||||
|         1,   1,   1,   1,   1,   1,   1,   3,   1,   3,   1,   1,   1,   1,   1,   1, // s5..s6 | ||||
|         1,   3,   1,   1,   1,   1,   1,   3,   1,   3,   1,   1,   1,   1,   1,   1, | ||||
|         1,   3,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1, // s7..s8 | ||||
|     }; | ||||
|  | ||||
|     /// Decode the next byte of a UTF8 sequence | ||||
| @@ -75,9 +86,7 @@ namespace ix | ||||
|     { | ||||
|         uint32_t type = utf8d[byte]; | ||||
|  | ||||
|       *codep = (*state != utf8_accept) ? | ||||
|         (byte & 0x3fu) | (*codep << 6) : | ||||
|         (0xff >> type) & (byte); | ||||
|         *codep = (*state != utf8_accept) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte); | ||||
|  | ||||
|         *state = utf8d[256 + *state * 16 + type]; | ||||
|         return *state; | ||||
| @@ -88,7 +97,11 @@ namespace ix | ||||
|     { | ||||
|     public: | ||||
|         /// Construct and initialize the validator | ||||
|         Utf8Validator() : m_state(utf8_accept),m_codepoint(0) {} | ||||
|         Utf8Validator() | ||||
|             : m_state(utf8_accept) | ||||
|             , m_codepoint(0) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// Advance the state of the validator with the next input byte | ||||
|         /** | ||||
| @@ -115,11 +128,8 @@ namespace ix | ||||
|         { | ||||
|             for (iterator_type it = begin; it != end; ++it) | ||||
|             { | ||||
|                 unsigned int result = decodeNextByte( | ||||
|                     &m_state, | ||||
|                     &m_codepoint, | ||||
|                     static_cast<uint8_t>(*it) | ||||
|                 ); | ||||
|                 unsigned int result = | ||||
|                     decodeNextByte(&m_state, &m_codepoint, static_cast<uint8_t>(*it)); | ||||
|  | ||||
|                 if (result == utf8_reject) | ||||
|                 { | ||||
| @@ -144,6 +154,7 @@ namespace ix | ||||
|             m_state = utf8_accept; | ||||
|             m_codepoint = 0; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         uint32_t m_state; | ||||
|         uint32_t m_codepoint; | ||||
|   | ||||
| @@ -5,13 +5,13 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXWebSocket.h" | ||||
| #include "IXSetThreadName.h" | ||||
| #include "IXWebSocketHandshake.h" | ||||
| #include "IXExponentialBackoff.h" | ||||
| #include "IXUtf8Validator.h" | ||||
|  | ||||
| #include <cmath> | ||||
| #include "IXExponentialBackoff.h" | ||||
| #include "IXSetThreadName.h" | ||||
| #include "IXUtf8Validator.h" | ||||
| #include "IXWebSocketHandshake.h" | ||||
| #include <cassert> | ||||
| #include <cmath> | ||||
|  | ||||
|  | ||||
| namespace ix | ||||
| @@ -23,26 +23,26 @@ namespace ix | ||||
|     const bool WebSocket::kDefaultEnablePong(true); | ||||
|     const uint32_t WebSocket::kDefaultMaxWaitBetweenReconnectionRetries(10 * 1000); // 10s | ||||
|  | ||||
|     WebSocket::WebSocket() : | ||||
|         _onMessageCallback(OnMessageCallback()), | ||||
|         _stop(false), | ||||
|         _automaticReconnection(true), | ||||
|         _maxWaitBetweenReconnectionRetries(kDefaultMaxWaitBetweenReconnectionRetries), | ||||
|         _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs), | ||||
|         _enablePong(kDefaultEnablePong), | ||||
|         _pingIntervalSecs(kDefaultPingIntervalSecs), | ||||
|         _pingTimeoutSecs(kDefaultPingTimeoutSecs) | ||||
|     WebSocket::WebSocket() | ||||
|         : _onMessageCallback(OnMessageCallback()) | ||||
|         , _stop(false) | ||||
|         , _automaticReconnection(true) | ||||
|         , _maxWaitBetweenReconnectionRetries(kDefaultMaxWaitBetweenReconnectionRetries) | ||||
|         , _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs) | ||||
|         , _enablePong(kDefaultEnablePong) | ||||
|         , _pingIntervalSecs(kDefaultPingIntervalSecs) | ||||
|         , _pingTimeoutSecs(kDefaultPingTimeoutSecs) | ||||
|     { | ||||
|         _ws.setOnCloseCallback( | ||||
|             [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) | ||||
|             { | ||||
|             [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) { | ||||
|                 _onMessageCallback( | ||||
|                     std::make_shared<WebSocketMessage>( | ||||
|                         WebSocketMessageType::Close, "", wireSize, | ||||
|                         WebSocketErrorInfo(), WebSocketOpenInfo(), | ||||
|                     std::make_shared<WebSocketMessage>(WebSocketMessageType::Close, | ||||
|                                                        "", | ||||
|                                                        wireSize, | ||||
|                                                        WebSocketErrorInfo(), | ||||
|                                                        WebSocketOpenInfo(), | ||||
|                                                        WebSocketCloseInfo(code, reason, remote))); | ||||
|             } | ||||
|         ); | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     WebSocket::~WebSocket() | ||||
| @@ -67,7 +67,8 @@ namespace ix | ||||
|         return _url; | ||||
|     } | ||||
|  | ||||
|     void WebSocket::setPerMessageDeflateOptions(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions) | ||||
|     void WebSocket::setPerMessageDeflateOptions( | ||||
|         const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions) | ||||
|     { | ||||
|         std::lock_guard<std::mutex> lock(_configMutex); | ||||
|         _perMessageDeflateOptions = perMessageDeflateOptions; | ||||
| @@ -159,8 +160,7 @@ namespace ix | ||||
|         _thread = std::thread(&WebSocket::run, this); | ||||
|     } | ||||
|  | ||||
|     void WebSocket::stop(uint16_t code, | ||||
|                          const std::string& reason) | ||||
|     void WebSocket::stop(uint16_t code, const std::string& reason) | ||||
|     { | ||||
|         close(code, reason); | ||||
|  | ||||
| @@ -192,8 +192,9 @@ namespace ix | ||||
|         } | ||||
|  | ||||
|         _onMessageCallback( | ||||
|             std::make_shared<WebSocketMessage>( | ||||
|                 WebSocketMessageType::Open, "", 0, | ||||
|             std::make_shared<WebSocketMessage>(WebSocketMessageType::Open, | ||||
|                                                "", | ||||
|                                                0, | ||||
|                                                WebSocketErrorInfo(), | ||||
|                                                WebSocketOpenInfo(status.uri, status.headers), | ||||
|                                                WebSocketCloseInfo())); | ||||
| @@ -218,8 +219,9 @@ namespace ix | ||||
|         } | ||||
|  | ||||
|         _onMessageCallback( | ||||
|                 std::make_shared<WebSocketMessage>( | ||||
|                     WebSocketMessageType::Open, "", 0, | ||||
|             std::make_shared<WebSocketMessage>(WebSocketMessageType::Open, | ||||
|                                                "", | ||||
|                                                0, | ||||
|                                                WebSocketErrorInfo(), | ||||
|                                                WebSocketOpenInfo(status.uri, status.headers), | ||||
|                                                WebSocketCloseInfo())); | ||||
| @@ -236,8 +238,7 @@ namespace ix | ||||
|         return getReadyState() == ReadyState::Closing; | ||||
|     } | ||||
|  | ||||
|     void WebSocket::close(uint16_t code, | ||||
|                           const std::string& reason) | ||||
|     void WebSocket::close(uint16_t code, const std::string& reason) | ||||
|     { | ||||
|         _ws.close(code, reason); | ||||
|     } | ||||
| @@ -281,7 +282,8 @@ namespace ix | ||||
|  | ||||
|                 if (_automaticReconnection) | ||||
|                 { | ||||
|                     duration = millis(calculateRetryWaitMilliseconds(retries++, _maxWaitBetweenReconnectionRetries)); | ||||
|                     duration = millis(calculateRetryWaitMilliseconds( | ||||
|                         retries++, _maxWaitBetweenReconnectionRetries)); | ||||
|  | ||||
|                     connectErr.wait_time = duration.count(); | ||||
|                     connectErr.retries = retries; | ||||
| @@ -290,10 +292,11 @@ namespace ix | ||||
|                 connectErr.reason = status.errorStr; | ||||
|                 connectErr.http_status = status.http_status; | ||||
|  | ||||
|                 _onMessageCallback( | ||||
|                      std::make_shared<WebSocketMessage>( | ||||
|                         WebSocketMessageType::Error, "", 0, | ||||
|                         connectErr, WebSocketOpenInfo(), | ||||
|                 _onMessageCallback(std::make_shared<WebSocketMessage>(WebSocketMessageType::Error, | ||||
|                                                                       "", | ||||
|                                                                       0, | ||||
|                                                                       connectErr, | ||||
|                                                                       WebSocketOpenInfo(), | ||||
|                                                                       WebSocketCloseInfo())); | ||||
|             } | ||||
|         } | ||||
| @@ -330,8 +333,7 @@ namespace ix | ||||
|                 [this](const std::string& msg, | ||||
|                        size_t wireSize, | ||||
|                        bool decompressionError, | ||||
|                        WebSocketTransport::MessageKind messageKind) | ||||
|                 { | ||||
|                        WebSocketTransport::MessageKind messageKind) { | ||||
|                     WebSocketMessageType webSocketMessageType; | ||||
|                     switch (messageKind) | ||||
|                     { | ||||
| @@ -339,22 +341,26 @@ namespace ix | ||||
|                         case WebSocketTransport::MessageKind::MSG_BINARY: | ||||
|                         { | ||||
|                             webSocketMessageType = WebSocketMessageType::Message; | ||||
|                         } break; | ||||
|                         } | ||||
|                         break; | ||||
|  | ||||
|                         case WebSocketTransport::MessageKind::PING: | ||||
|                         { | ||||
|                             webSocketMessageType = WebSocketMessageType::Ping; | ||||
|                         } break; | ||||
|                         } | ||||
|                         break; | ||||
|  | ||||
|                         case WebSocketTransport::MessageKind::PONG: | ||||
|                         { | ||||
|                             webSocketMessageType = WebSocketMessageType::Pong; | ||||
|                         } break; | ||||
|                         } | ||||
|                         break; | ||||
|  | ||||
|                         case WebSocketTransport::MessageKind::FRAGMENT: | ||||
|                         { | ||||
|                             webSocketMessageType = WebSocketMessageType::Fragment; | ||||
|                         } break; | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     WebSocketErrorInfo webSocketErrorInfo; | ||||
| @@ -362,11 +368,13 @@ namespace ix | ||||
|  | ||||
|                     bool binary = messageKind == WebSocketTransport::MessageKind::MSG_BINARY; | ||||
|  | ||||
|                     _onMessageCallback( | ||||
|                          std::make_shared<WebSocketMessage>( | ||||
|                             webSocketMessageType, msg, wireSize, | ||||
|                             webSocketErrorInfo, WebSocketOpenInfo(), | ||||
|                             WebSocketCloseInfo(), binary)); | ||||
|                     _onMessageCallback(std::make_shared<WebSocketMessage>(webSocketMessageType, | ||||
|                                                                           msg, | ||||
|                                                                           wireSize, | ||||
|                                                                           webSocketErrorInfo, | ||||
|                                                                           WebSocketOpenInfo(), | ||||
|                                                                           WebSocketCloseInfo(), | ||||
|                                                                           binary)); | ||||
|  | ||||
|                     WebSocket::invokeTrafficTrackerCallback(msg.size(), true); | ||||
|                 }); | ||||
| @@ -453,17 +461,20 @@ namespace ix | ||||
|             case SendMessageKind::Text: | ||||
|             { | ||||
|                 webSocketSendInfo = _ws.sendText(text, onProgressCallback); | ||||
|             } break; | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|             case SendMessageKind::Binary: | ||||
|             { | ||||
|                 webSocketSendInfo = _ws.sendBinary(text, onProgressCallback); | ||||
|             } break; | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|             case SendMessageKind::Ping: | ||||
|             { | ||||
|                 webSocketSendInfo = _ws.sendPing(text); | ||||
|             } break; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         WebSocket::invokeTrafficTrackerCallback(webSocketSendInfo.wireSize, false); | ||||
| @@ -514,4 +525,4 @@ namespace ix | ||||
|     { | ||||
|         return _ws.bufferedAmount(); | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -22,10 +22,15 @@ namespace ix | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorMessage("Protocol error"); | ||||
|     const std::string WebSocketCloseConstants::kNoStatusCodeErrorMessage("No status code"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorReservedBitUsed("Reserved bit used"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorPingPayloadOversized("Ping reason control frame with payload length > 125 octets"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorCodeControlMessageFragmented("Control message fragmented"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorCodeDataOpcodeOutOfSequence("Fragmentation: data message out of sequence"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorCodeContinuationOpCodeOutOfSequence("Fragmentation: continuation opcode out of sequence"); | ||||
|     const std::string WebSocketCloseConstants::kInvalidFramePayloadDataMessage("Invalid frame payload data"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorPingPayloadOversized( | ||||
|         "Ping reason control frame with payload length > 125 octets"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorCodeControlMessageFragmented( | ||||
|         "Control message fragmented"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorCodeDataOpcodeOutOfSequence( | ||||
|         "Fragmentation: data message out of sequence"); | ||||
|     const std::string WebSocketCloseConstants::kProtocolErrorCodeContinuationOpCodeOutOfSequence( | ||||
|         "Fragmentation: continuation opcode out of sequence"); | ||||
|     const std::string WebSocketCloseConstants::kInvalidFramePayloadDataMessage( | ||||
|         "Invalid frame payload data"); | ||||
|     const std::string WebSocketCloseConstants::kInvalidCloseCodeMessage("Invalid close code"); | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,48 +5,43 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXWebSocketHandshake.h" | ||||
|  | ||||
| #include "IXHttp.h" | ||||
| #include "IXSocketConnect.h" | ||||
| #include "IXUrlParser.h" | ||||
| #include "IXHttp.h" | ||||
| #include "IXUserAgent.h" | ||||
|  | ||||
| #include "libwshandshake.hpp" | ||||
|  | ||||
| #include <sstream> | ||||
| #include <random> | ||||
| #include <algorithm> | ||||
| #include <random> | ||||
| #include <sstream> | ||||
|  | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     WebSocketHandshake::WebSocketHandshake(std::atomic<bool>& requestInitCancellation, | ||||
|     WebSocketHandshake::WebSocketHandshake( | ||||
|         std::atomic<bool>& requestInitCancellation, | ||||
|         std::shared_ptr<Socket> socket, | ||||
|         WebSocketPerMessageDeflate& perMessageDeflate, | ||||
|         WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, | ||||
|                                            std::atomic<bool>& enablePerMessageDeflate) : | ||||
|         _requestInitCancellation(requestInitCancellation), | ||||
|         _socket(socket), | ||||
|         _perMessageDeflate(perMessageDeflate), | ||||
|         _perMessageDeflateOptions(perMessageDeflateOptions), | ||||
|         _enablePerMessageDeflate(enablePerMessageDeflate) | ||||
|         std::atomic<bool>& enablePerMessageDeflate) | ||||
|         : _requestInitCancellation(requestInitCancellation) | ||||
|         , _socket(socket) | ||||
|         , _perMessageDeflate(perMessageDeflate) | ||||
|         , _perMessageDeflateOptions(perMessageDeflateOptions) | ||||
|         , _enablePerMessageDeflate(enablePerMessageDeflate) | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     bool WebSocketHandshake::insensitiveStringCompare(const std::string& a, const std::string& b) | ||||
|     { | ||||
|         return std::equal(a.begin(), a.end(), | ||||
|                           b.begin(), b.end(), | ||||
|                           [](char a, char b) | ||||
|                           { | ||||
|         return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { | ||||
|             return tolower(a) == tolower(b); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     std::string WebSocketHandshake::genRandomString(const int len) | ||||
|     { | ||||
|         std::string alphanum = | ||||
|             "0123456789" | ||||
|         std::string alphanum = "0123456789" | ||||
|                                "ABCDEFGH" | ||||
|                                "abcdefgh"; | ||||
|  | ||||
| @@ -88,7 +83,8 @@ namespace ix | ||||
|         return WebSocketInitResult(false, code, reason); | ||||
|     } | ||||
|  | ||||
|     WebSocketInitResult WebSocketHandshake::clientHandshake(const std::string& url, | ||||
|     WebSocketInitResult WebSocketHandshake::clientHandshake( | ||||
|         const std::string& url, | ||||
|         const WebSocketHttpHeaders& extraHeaders, | ||||
|         const std::string& host, | ||||
|         const std::string& path, | ||||
| @@ -105,9 +101,7 @@ namespace ix | ||||
|         if (!success) | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "Unable to connect to " << host | ||||
|                << " on port " << port | ||||
|                << ", error: " << errMsg; | ||||
|             ss << "Unable to connect to " << host << " on port " << port << ", error: " << errMsg; | ||||
|             return WebSocketInitResult(false, 0, ss.str()); | ||||
|         } | ||||
|  | ||||
| @@ -149,7 +143,8 @@ namespace ix | ||||
|  | ||||
|         if (!_socket->writeBytes(ss.str(), isCancellationRequested)) | ||||
|         { | ||||
|             return WebSocketInitResult(false, 0, std::string("Failed sending GET request to ") + url); | ||||
|             return WebSocketInitResult( | ||||
|                 false, 0, std::string("Failed sending GET request to ") + url); | ||||
|         } | ||||
|  | ||||
|         // Read HTTP status line | ||||
| @@ -159,8 +154,8 @@ namespace ix | ||||
|  | ||||
|         if (!lineValid) | ||||
|         { | ||||
|             return WebSocketInitResult(false, 0, | ||||
|                                        std::string("Failed reading HTTP status line from ") + url); | ||||
|             return WebSocketInitResult( | ||||
|                 false, 0, std::string("Failed reading HTTP status line from ") + url); | ||||
|         } | ||||
|  | ||||
|         // Validate status | ||||
| @@ -173,8 +168,7 @@ namespace ix | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "Expecting HTTP/1.1, got " << httpVersion << ". " | ||||
|                << "Rejecting connection to " << host << ":" << port | ||||
|                << ", status: " << status | ||||
|                << "Rejecting connection to " << host << ":" << port << ", status: " << status | ||||
|                << ", HTTP Status line: " << line; | ||||
|             return WebSocketInitResult(false, status, ss.str()); | ||||
|         } | ||||
| @@ -183,8 +177,7 @@ namespace ix | ||||
|         if (status != 101) | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "Got bad status connecting to " << host << ":" << port | ||||
|                << ", status: " << status | ||||
|             ss << "Got bad status connecting to " << host << ":" << port << ", status: " << status | ||||
|                << ", HTTP Status line: " << line; | ||||
|             return WebSocketInitResult(false, status, ss.str()); | ||||
|         } | ||||
| @@ -280,7 +273,8 @@ namespace ix | ||||
|  | ||||
|         if (httpVersion != "HTTP/1.1") | ||||
|         { | ||||
|             return sendErrorResponse(400, "Invalid HTTP version, need HTTP/1.1, got: " + httpVersion); | ||||
|             return sendErrorResponse(400, | ||||
|                                      "Invalid HTTP version, need HTTP/1.1, got: " + httpVersion); | ||||
|         } | ||||
|  | ||||
|         // Retrieve and validate HTTP headers | ||||
| @@ -305,8 +299,10 @@ namespace ix | ||||
|  | ||||
|         if (!insensitiveStringCompare(headers["upgrade"], "WebSocket")) | ||||
|         { | ||||
|             return sendErrorResponse(400, "Invalid Upgrade header, " | ||||
|                                           "need WebSocket, got " + headers["upgrade"]); | ||||
|             return sendErrorResponse(400, | ||||
|                                      "Invalid Upgrade header, " | ||||
|                                      "need WebSocket, got " + | ||||
|                                          headers["upgrade"]); | ||||
|         } | ||||
|  | ||||
|         if (headers.find("sec-websocket-version") == headers.end()) | ||||
| @@ -322,8 +318,10 @@ namespace ix | ||||
|  | ||||
|             if (version != 13) | ||||
|             { | ||||
|                 return sendErrorResponse(400, "Invalid Sec-WebSocket-Version, " | ||||
|                                               "need 13, got " + ss.str()); | ||||
|                 return sendErrorResponse(400, | ||||
|                                          "Invalid Sec-WebSocket-Version, " | ||||
|                                          "need 13, got " + | ||||
|                                              ss.str()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -358,9 +356,10 @@ namespace ix | ||||
|  | ||||
|         if (!_socket->writeBytes(ss.str(), isCancellationRequested)) | ||||
|         { | ||||
|             return WebSocketInitResult(false, 0, std::string("Failed sending response to ") + remote); | ||||
|             return WebSocketInitResult( | ||||
|                 false, 0, std::string("Failed sending response to ") + remote); | ||||
|         } | ||||
|  | ||||
|         return WebSocketInitResult(true, 200, "", headers, uri); | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -49,8 +49,7 @@ namespace ix | ||||
|                            WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, | ||||
|                            std::atomic<bool>& enablePerMessageDeflate); | ||||
|  | ||||
|         WebSocketInitResult clientHandshake( | ||||
|             const std::string& url, | ||||
|         WebSocketInitResult clientHandshake(const std::string& url, | ||||
|                                             const WebSocketHttpHeaders& extraHeaders, | ||||
|                                             const std::string& host, | ||||
|                                             const std::string& path, | ||||
|   | ||||
| @@ -5,13 +5,15 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXWebSocketHttpHeaders.h" | ||||
|  | ||||
| #include "IXSocket.h" | ||||
| #include <algorithm> | ||||
| #include <locale> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     bool CaseInsensitiveLess::NocaseCompare::operator()(const unsigned char & c1, const unsigned char & c2) const | ||||
|     bool CaseInsensitiveLess::NocaseCompare::operator()(const unsigned char& c1, | ||||
|                                                         const unsigned char& c2) const | ||||
|     { | ||||
| #ifdef _WIN32 | ||||
|         return std::tolower(c1, std::locale()) < std::tolower(c2, std::locale()); | ||||
| @@ -22,15 +24,15 @@ namespace ix | ||||
|  | ||||
|     bool CaseInsensitiveLess::operator()(const std::string& s1, const std::string& s2) const | ||||
|     { | ||||
|         return std::lexicographical_compare | ||||
|                 (s1.begin(), s1.end(),   // source range | ||||
|                  s2.begin(), s2.end(),   // dest range | ||||
|         return std::lexicographical_compare(s1.begin(), | ||||
|                                             s1.end(), // source range | ||||
|                                             s2.begin(), | ||||
|                                             s2.end(),         // dest range | ||||
|                                             NocaseCompare()); // comparison | ||||
|     } | ||||
|  | ||||
|     std::pair<bool, WebSocketHttpHeaders> parseHttpHeaders( | ||||
|         std::shared_ptr<Socket> socket, | ||||
|         const CancellationRequest& isCancellationRequested) | ||||
|         std::shared_ptr<Socket> socket, const CancellationRequest& isCancellationRequested) | ||||
|     { | ||||
|         WebSocketHttpHeaders headers; | ||||
|  | ||||
| @@ -41,9 +43,7 @@ namespace ix | ||||
|         { | ||||
|             int colon = 0; | ||||
|  | ||||
|             for (i = 0; | ||||
|                  i < 2 || (i < 1023 && line[i-2] != '\r' && line[i-1] != '\n'); | ||||
|                  ++i) | ||||
|             for (i = 0; i < 2 || (i < 1023 && line[i - 2] != '\r' && line[i - 1] != '\n'); ++i) | ||||
|             { | ||||
|                 if (!socket->readByte(line + i, isCancellationRequested)) | ||||
|                 { | ||||
| @@ -79,4 +79,4 @@ namespace ix | ||||
|  | ||||
|         return std::make_pair(true, headers); | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -8,7 +8,6 @@ | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|  | ||||
|     WebSocketMessageQueue::WebSocketMessageQueue(WebSocket* websocket) | ||||
|     { | ||||
|         bindWebsocket(websocket); | ||||
| @@ -40,8 +39,7 @@ namespace ix | ||||
|         // bind new | ||||
|         if (_websocket) | ||||
|         { | ||||
|             _websocket->setOnMessageCallback([this](const WebSocketMessagePtr& msg) | ||||
|             { | ||||
|             _websocket->setOnMessageCallback([this](const WebSocketMessagePtr& msg) { | ||||
|                 std::lock_guard<std::mutex> lock(_messagesMutex); | ||||
|                 _messages.emplace_back(std::move(msg)); | ||||
|             }); | ||||
| @@ -74,8 +72,7 @@ namespace ix | ||||
|  | ||||
|     void WebSocketMessageQueue::poll(int count) | ||||
|     { | ||||
|         if (!_onMessageUserCallback) | ||||
|             return; | ||||
|         if (!_onMessageUserCallback) return; | ||||
|  | ||||
|         WebSocketMessagePtr message; | ||||
|  | ||||
| @@ -86,4 +83,4 @@ namespace ix | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -41,19 +41,21 @@ | ||||
|  *  - Added more documentation. | ||||
|  * | ||||
|  *  Per message Deflate RFC: https://tools.ietf.org/html/rfc7692 | ||||
|  *  Chrome websocket -> https://github.com/chromium/chromium/tree/2ca8c5037021c9d2ecc00b787d58a31ed8fc8bcb/net/websockets | ||||
|  *  Chrome websocket -> | ||||
|  * https://github.com/chromium/chromium/tree/2ca8c5037021c9d2ecc00b787d58a31ed8fc8bcb/net/websockets | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "IXWebSocketPerMessageDeflate.h" | ||||
| #include "IXWebSocketPerMessageDeflateOptions.h" | ||||
|  | ||||
| #include "IXWebSocketPerMessageDeflateCodec.h" | ||||
| #include "IXWebSocketPerMessageDeflateOptions.h" | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     WebSocketPerMessageDeflate::WebSocketPerMessageDeflate() : | ||||
|         _compressor(std::make_unique<WebSocketPerMessageDeflateCompressor>()), | ||||
|         _decompressor(std::make_unique<WebSocketPerMessageDeflateDecompressor>()) | ||||
|     WebSocketPerMessageDeflate::WebSocketPerMessageDeflate() | ||||
|         : _compressor(std::make_unique<WebSocketPerMessageDeflateCompressor>()) | ||||
|         , _decompressor(std::make_unique<WebSocketPerMessageDeflateDecompressor>()) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -63,10 +65,10 @@ namespace ix | ||||
|         ; | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflate::init(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions) | ||||
|     bool WebSocketPerMessageDeflate::init( | ||||
|         const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions) | ||||
|     { | ||||
|         bool clientNoContextTakeover = | ||||
|             perMessageDeflateOptions.getClientNoContextTakeover(); | ||||
|         bool clientNoContextTakeover = perMessageDeflateOptions.getClientNoContextTakeover(); | ||||
|  | ||||
|         uint8_t deflateBits = perMessageDeflateOptions.getClientMaxWindowBits(); | ||||
|         uint8_t inflateBits = perMessageDeflateOptions.getServerMaxWindowBits(); | ||||
| @@ -75,16 +77,14 @@ namespace ix | ||||
|                _decompressor->init(inflateBits, clientNoContextTakeover); | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflate::compress(const std::string& in, | ||||
|                                               std::string& out) | ||||
|     bool WebSocketPerMessageDeflate::compress(const std::string& in, std::string& out) | ||||
|     { | ||||
|         return _compressor->compress(in, out); | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflate::decompress(const std::string& in, | ||||
|                                                 std::string &out) | ||||
|     bool WebSocketPerMessageDeflate::decompress(const std::string& in, std::string& out) | ||||
|     { | ||||
|         return _decompressor->decompress(in, out); | ||||
|     } | ||||
|  | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,8 +5,8 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXWebSocketPerMessageDeflateCodec.h" | ||||
| #include "IXWebSocketPerMessageDeflateOptions.h" | ||||
|  | ||||
| #include "IXWebSocketPerMessageDeflateOptions.h" | ||||
| #include <cassert> | ||||
| #include <string.h> | ||||
|  | ||||
| @@ -18,7 +18,7 @@ namespace | ||||
|     const std::string kEmptyUncompressedBlock = std::string("\x00\x00\xff\xff", 4); | ||||
|  | ||||
|     const int kBufferSize = 1 << 14; | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -43,22 +43,18 @@ namespace ix | ||||
|     bool WebSocketPerMessageDeflateCompressor::init(uint8_t deflateBits, | ||||
|                                                     bool clientNoContextTakeOver) | ||||
|     { | ||||
|         int ret = deflateInit2( | ||||
|             &_deflateState, | ||||
|         int ret = deflateInit2(&_deflateState, | ||||
|                                Z_DEFAULT_COMPRESSION, | ||||
|                                Z_DEFLATED, | ||||
|                                -1 * deflateBits, | ||||
|                                4, // memory level 1-9 | ||||
|             Z_DEFAULT_STRATEGY | ||||
|         ); | ||||
|                                Z_DEFAULT_STRATEGY); | ||||
|  | ||||
|         if (ret != Z_OK) return false; | ||||
|  | ||||
|         _compressBuffer = std::make_unique<unsigned char[]>(_compressBufferSize); | ||||
|  | ||||
|         _flush = (clientNoContextTakeOver) | ||||
|                  ? Z_FULL_FLUSH | ||||
|                  : Z_SYNC_FLUSH; | ||||
|         _flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH; | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| @@ -70,8 +66,7 @@ namespace ix | ||||
|         return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in, | ||||
|                                                         std::string& out) | ||||
|     bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in, std::string& out) | ||||
|     { | ||||
|         // | ||||
|         // 7.2.1.  Compression | ||||
| @@ -146,24 +141,18 @@ namespace ix | ||||
|     bool WebSocketPerMessageDeflateDecompressor::init(uint8_t inflateBits, | ||||
|                                                       bool clientNoContextTakeOver) | ||||
|     { | ||||
|         int ret = inflateInit2( | ||||
|             &_inflateState, | ||||
|             -1*inflateBits | ||||
|         ); | ||||
|         int ret = inflateInit2(&_inflateState, -1 * inflateBits); | ||||
|  | ||||
|         if (ret != Z_OK) return false; | ||||
|  | ||||
|         _compressBuffer = std::make_unique<unsigned char[]>(_compressBufferSize); | ||||
|  | ||||
|         _flush = (clientNoContextTakeOver) | ||||
|                  ? Z_FULL_FLUSH | ||||
|                  : Z_SYNC_FLUSH; | ||||
|         _flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH; | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string& in, | ||||
|                                                             std::string& out) | ||||
|     bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string& in, std::string& out) | ||||
|     { | ||||
|         // | ||||
|         // 7.2.2.  Decompression | ||||
| @@ -193,13 +182,10 @@ namespace ix | ||||
|                 return false; // zlib error | ||||
|             } | ||||
|  | ||||
|             out.append( | ||||
|                 reinterpret_cast<char *>(_compressBuffer.get()), | ||||
|                 _compressBufferSize - _inflateState.avail_out | ||||
|             ); | ||||
|             out.append(reinterpret_cast<char*>(_compressBuffer.get()), | ||||
|                        _compressBufferSize - _inflateState.avail_out); | ||||
|         } while (_inflateState.avail_out == 0); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -6,9 +6,9 @@ | ||||
|  | ||||
| #include "IXWebSocketPerMessageDeflateOptions.h" | ||||
|  | ||||
| #include <sstream> | ||||
| #include <algorithm> | ||||
| #include <cctype> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -48,7 +48,8 @@ namespace ix | ||||
|     // | ||||
|     // Server response could look like that: | ||||
|     // | ||||
|     // Sec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover; server_no_context_takeover | ||||
|     // Sec-WebSocket-Extensions: permessage-deflate; client_no_context_takeover; | ||||
|     // server_no_context_takeover | ||||
|     // | ||||
|     WebSocketPerMessageDeflateOptions::WebSocketPerMessageDeflateOptions(std::string extension) | ||||
|     { | ||||
| @@ -92,8 +93,7 @@ namespace ix | ||||
|                 // Sanitize values to be in the proper range [8, 15] in | ||||
|                 // case a server would give us bogus values | ||||
|                 _serverMaxWindowBits = | ||||
|                     std::min(maxServerMaxWindowBits, | ||||
|                         std::max(x, minServerMaxWindowBits)); | ||||
|                     std::min(maxServerMaxWindowBits, std::max(x, minServerMaxWindowBits)); | ||||
|             } | ||||
|  | ||||
|             if (startsWith(token, "client_max_window_bits=")) | ||||
| @@ -107,8 +107,7 @@ namespace ix | ||||
|                 // Sanitize values to be in the proper range [8, 15] in | ||||
|                 // case a server would give us bogus values | ||||
|                 _clientMaxWindowBits = | ||||
|                     std::min(maxClientMaxWindowBits, | ||||
|                         std::max(x, minClientMaxWindowBits)); | ||||
|                     std::min(maxClientMaxWindowBits, std::max(x, minClientMaxWindowBits)); | ||||
|  | ||||
|                 sanitizeClientMaxWindowBits(); | ||||
|             } | ||||
| @@ -175,11 +174,10 @@ namespace ix | ||||
|     std::string WebSocketPerMessageDeflateOptions::removeSpaces(const std::string& str) | ||||
|     { | ||||
|         std::string out(str); | ||||
|         out.erase(std::remove_if(out.begin(), | ||||
|                                  out.end(), | ||||
|                                  [](unsigned char x){ return std::isspace(x); }), | ||||
|         out.erase( | ||||
|             std::remove_if(out.begin(), out.end(), [](unsigned char x) { return std::isspace(x); }), | ||||
|             out.end()); | ||||
|  | ||||
|         return out; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,13 +5,13 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXWebSocketServer.h" | ||||
| #include "IXWebSocketTransport.h" | ||||
| #include "IXWebSocket.h" | ||||
| #include "IXSocketConnect.h" | ||||
| #include "IXNetSystem.h" | ||||
|  | ||||
| #include <sstream> | ||||
| #include "IXNetSystem.h" | ||||
| #include "IXSocketConnect.h" | ||||
| #include "IXWebSocket.h" | ||||
| #include "IXWebSocketTransport.h" | ||||
| #include <future> | ||||
| #include <sstream> | ||||
| #include <string.h> | ||||
|  | ||||
| namespace ix | ||||
| @@ -23,11 +23,11 @@ namespace ix | ||||
|                                      const std::string& host, | ||||
|                                      int backlog, | ||||
|                                      size_t maxConnections, | ||||
|                                      int handshakeTimeoutSecs) : SocketServer(port, host, backlog, maxConnections), | ||||
|         _handshakeTimeoutSecs(handshakeTimeoutSecs), | ||||
|         _enablePong(kDefaultEnablePong) | ||||
|                                      int handshakeTimeoutSecs) | ||||
|         : SocketServer(port, host, backlog, maxConnections) | ||||
|         , _handshakeTimeoutSecs(handshakeTimeoutSecs) | ||||
|         , _enablePong(kDefaultEnablePong) | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     WebSocketServer::~WebSocketServer() | ||||
| @@ -63,9 +63,7 @@ namespace ix | ||||
|         _onConnectionCallback = callback; | ||||
|     } | ||||
|  | ||||
|     void WebSocketServer::handleConnection( | ||||
|         int fd, | ||||
|         std::shared_ptr<ConnectionState> connectionState) | ||||
|     void WebSocketServer::handleConnection(int fd, std::shared_ptr<ConnectionState> connectionState) | ||||
|     { | ||||
|         auto webSocket = std::make_shared<WebSocket>(); | ||||
|         _onConnectionCallback(webSocket, connectionState); | ||||
| @@ -93,10 +91,8 @@ namespace ix | ||||
|         else | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "WebSocketServer::handleConnection() HTTP status: " | ||||
|                << status.http_status | ||||
|                << " error: " | ||||
|                << status.errorStr; | ||||
|             ss << "WebSocketServer::handleConnection() HTTP status: " << status.http_status | ||||
|                << " error: " << status.errorStr; | ||||
|             logError(ss.str()); | ||||
|         } | ||||
|  | ||||
| @@ -126,4 +122,4 @@ namespace ix | ||||
|         std::lock_guard<std::mutex> lock(_clientsMutex); | ||||
|         return _clients.size(); | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -32,24 +32,23 @@ | ||||
| // Adapted from https://github.com/dhbaird/easywsclient | ||||
| // | ||||
|  | ||||
| #include "IXSocketTLSOptions.h" | ||||
| #include "IXWebSocketTransport.h" | ||||
|  | ||||
| #include "IXSocketFactory.h" | ||||
| #include "IXSocketTLSOptions.h" | ||||
| #include "IXUrlParser.h" | ||||
| #include "IXUtf8Validator.h" | ||||
| #include "IXWebSocketHandshake.h" | ||||
| #include "IXWebSocketHttpHeaders.h" | ||||
| #include "IXUrlParser.h" | ||||
| #include "IXSocketFactory.h" | ||||
| #include "IXUtf8Validator.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <cstdlib> | ||||
| #include <vector> | ||||
| #include <string> | ||||
| #include <cstdarg> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
| #include <cstdarg> | ||||
| #include <cstdlib> | ||||
| #include <sstream> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <string> | ||||
| #include <thread> | ||||
| #include <vector> | ||||
|  | ||||
|  | ||||
| namespace | ||||
| @@ -65,7 +64,7 @@ namespace | ||||
|  | ||||
|         return a; | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -76,24 +75,24 @@ namespace ix | ||||
|     const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300); | ||||
|     constexpr size_t WebSocketTransport::kChunkSize; | ||||
|  | ||||
|     WebSocketTransport::WebSocketTransport() : | ||||
|         _useMask(true), | ||||
|         _compressedMessage(false), | ||||
|         _readyState(ReadyState::CLOSED), | ||||
|         _closeCode(WebSocketCloseConstants::kInternalErrorCode), | ||||
|         _closeReason(WebSocketCloseConstants::kInternalErrorMessage), | ||||
|         _closeWireSize(0), | ||||
|         _closeRemote(false), | ||||
|         _enablePerMessageDeflate(false), | ||||
|         _requestInitCancellation(false), | ||||
|         _closingTimePoint(std::chrono::steady_clock::now()), | ||||
|         _enablePong(kDefaultEnablePong), | ||||
|         _pingIntervalSecs(kDefaultPingIntervalSecs), | ||||
|         _pingTimeoutSecs(kDefaultPingTimeoutSecs), | ||||
|         _pingIntervalOrTimeoutGCDSecs(-1), | ||||
|         _nextGCDTimePoint(std::chrono::steady_clock::now()), | ||||
|         _lastSendPingTimePoint(std::chrono::steady_clock::now()), | ||||
|         _lastReceivePongTimePoint(std::chrono::steady_clock::now()) | ||||
|     WebSocketTransport::WebSocketTransport() | ||||
|         : _useMask(true) | ||||
|         , _compressedMessage(false) | ||||
|         , _readyState(ReadyState::CLOSED) | ||||
|         , _closeCode(WebSocketCloseConstants::kInternalErrorCode) | ||||
|         , _closeReason(WebSocketCloseConstants::kInternalErrorMessage) | ||||
|         , _closeWireSize(0) | ||||
|         , _closeRemote(false) | ||||
|         , _enablePerMessageDeflate(false) | ||||
|         , _requestInitCancellation(false) | ||||
|         , _closingTimePoint(std::chrono::steady_clock::now()) | ||||
|         , _enablePong(kDefaultEnablePong) | ||||
|         , _pingIntervalSecs(kDefaultPingIntervalSecs) | ||||
|         , _pingTimeoutSecs(kDefaultPingTimeoutSecs) | ||||
|         , _pingIntervalOrTimeoutGCDSecs(-1) | ||||
|         , _nextGCDTimePoint(std::chrono::steady_clock::now()) | ||||
|         , _lastSendPingTimePoint(std::chrono::steady_clock::now()) | ||||
|         , _lastReceivePongTimePoint(std::chrono::steady_clock::now()) | ||||
|     { | ||||
|         _readbuf.resize(kChunkSize); | ||||
|     } | ||||
| @@ -103,7 +102,8 @@ namespace ix | ||||
|         ; | ||||
|     } | ||||
|  | ||||
|     void WebSocketTransport::configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, | ||||
|     void WebSocketTransport::configure( | ||||
|         const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions, | ||||
|         const SocketTLSOptions& socketTLSOptions, | ||||
|         bool enablePong, | ||||
|         int pingIntervalSecs, | ||||
| @@ -118,8 +118,8 @@ namespace ix | ||||
|  | ||||
|         if (pingIntervalSecs > 0 && pingTimeoutSecs > 0) | ||||
|         { | ||||
|             _pingIntervalOrTimeoutGCDSecs = greatestCommonDivisor(pingIntervalSecs, | ||||
|                                                                   pingTimeoutSecs); | ||||
|             _pingIntervalOrTimeoutGCDSecs = | ||||
|                 greatestCommonDivisor(pingIntervalSecs, pingTimeoutSecs); | ||||
|         } | ||||
|         else if (_pingTimeoutSecs > 0) | ||||
|         { | ||||
| @@ -132,8 +132,7 @@ namespace ix | ||||
|     } | ||||
|  | ||||
|     // Client | ||||
|     WebSocketInitResult WebSocketTransport::connectToUrl( | ||||
|         const std::string& url, | ||||
|     WebSocketInitResult WebSocketTransport::connectToUrl(const std::string& url, | ||||
|                                                          const WebSocketHttpHeaders& headers, | ||||
|                                                          int timeoutSecs) | ||||
|     { | ||||
| @@ -144,8 +143,7 @@ namespace ix | ||||
|  | ||||
|         if (!UrlParser::parse(url, protocol, host, path, query, port)) | ||||
|         { | ||||
|             return WebSocketInitResult(false, 0, | ||||
|                                        std::string("Could not parse URL ") + url); | ||||
|             return WebSocketInitResult(false, 0, std::string("Could not parse URL ") + url); | ||||
|         } | ||||
|  | ||||
|         std::string errorMsg; | ||||
| @@ -163,8 +161,8 @@ namespace ix | ||||
|                                               _perMessageDeflateOptions, | ||||
|                                               _enablePerMessageDeflate); | ||||
|  | ||||
|         auto result = webSocketHandshake.clientHandshake(url, headers, host, path, | ||||
|                                                          port, timeoutSecs); | ||||
|         auto result = | ||||
|             webSocketHandshake.clientHandshake(url, headers, host, path, port, timeoutSecs); | ||||
|         if (result.success) | ||||
|         { | ||||
|             setReadyState(ReadyState::OPEN); | ||||
| @@ -247,15 +245,15 @@ namespace ix | ||||
|  | ||||
|         if (_pingIntervalOrTimeoutGCDSecs > 0) | ||||
|         { | ||||
|             _nextGCDTimePoint = std::chrono::steady_clock::now() + std::chrono::seconds(_pingIntervalOrTimeoutGCDSecs); | ||||
|             _nextGCDTimePoint = std::chrono::steady_clock::now() + | ||||
|                                 std::chrono::seconds(_pingIntervalOrTimeoutGCDSecs); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Only consider send PING time points for that computation. | ||||
|     bool WebSocketTransport::pingIntervalExceeded() | ||||
|     { | ||||
|         if (_pingIntervalSecs <= 0) | ||||
|             return false; | ||||
|         if (_pingIntervalSecs <= 0) return false; | ||||
|  | ||||
|         std::lock_guard<std::mutex> lock(_lastSendPingTimePointMutex); | ||||
|         auto now = std::chrono::steady_clock::now(); | ||||
| @@ -264,8 +262,7 @@ namespace ix | ||||
|  | ||||
|     bool WebSocketTransport::pingTimeoutExceeded() | ||||
|     { | ||||
|         if (_pingTimeoutSecs <= 0) | ||||
|             return false; | ||||
|         if (_pingTimeoutSecs <= 0) return false; | ||||
|  | ||||
|         std::lock_guard<std::mutex> lock(_lastReceivePongTimePointMutex); | ||||
|         auto now = std::chrono::steady_clock::now(); | ||||
| @@ -302,7 +299,8 @@ namespace ix | ||||
|  | ||||
|         // No timeout if state is not OPEN, otherwise computed | ||||
|         // pingIntervalOrTimeoutGCD (equals to -1 if no ping and no ping timeout are set) | ||||
|         int lastingTimeoutDelayInMs = (_readyState != ReadyState::OPEN) ? 0 : _pingIntervalOrTimeoutGCDSecs; | ||||
|         int lastingTimeoutDelayInMs = | ||||
|             (_readyState != ReadyState::OPEN) ? 0 : _pingIntervalOrTimeoutGCDSecs; | ||||
|  | ||||
|         if (_pingIntervalOrTimeoutGCDSecs > 0) | ||||
|         { | ||||
| @@ -317,7 +315,10 @@ namespace ix | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 lastingTimeoutDelayInMs = (int)std::chrono::duration_cast<std::chrono::milliseconds>(_nextGCDTimePoint - now).count(); | ||||
|                 lastingTimeoutDelayInMs = | ||||
|                     (int) std::chrono::duration_cast<std::chrono::milliseconds>(_nextGCDTimePoint - | ||||
|                                                                                 now) | ||||
|                         .count(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -373,8 +374,9 @@ namespace ix | ||||
|                 } | ||||
|                 else if (ret <= 0) | ||||
|                 { | ||||
|                     // if there are received data pending to be processed, then delay the abnormal closure | ||||
|                     // to after dispatch (other close code/reason could be read from the buffer) | ||||
|                     // if there are received data pending to be processed, then delay the abnormal | ||||
|                     // closure to after dispatch (other close code/reason could be read from the | ||||
|                     // buffer) | ||||
|  | ||||
|                     closeSocket(); | ||||
|  | ||||
| @@ -382,9 +384,7 @@ namespace ix | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     _rxbuf.insert(_rxbuf.end(), | ||||
|                                   _readbuf.begin(), | ||||
|                                   _readbuf.begin() + ret); | ||||
|                     _rxbuf.insert(_rxbuf.end(), _readbuf.begin(), _readbuf.begin() + ret); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -482,7 +482,8 @@ namespace ix | ||||
|             ws.opcode = (wsheader_type::opcode_type)(data[0] & 0x0f); | ||||
|             ws.mask = (data[1] & 0x80) == 0x80; | ||||
|             ws.N0 = (data[1] & 0x7f); | ||||
|             ws.header_size = 2 + (ws.N0 == 126? 2 : 0) + (ws.N0 == 127? 8 : 0) + (ws.mask? 4 : 0); | ||||
|             ws.header_size = | ||||
|                 2 + (ws.N0 == 126 ? 2 : 0) + (ws.N0 == 127 ? 8 : 0) + (ws.mask ? 4 : 0); | ||||
|             if (_rxbuf.size() < ws.header_size) break; /* Need: ws.header_size - _rxbuf.size() */ | ||||
|  | ||||
|             if ((ws.rsv1 && !_enablePerMessageDeflate) || ws.rsv2 || ws.rsv3) | ||||
| @@ -551,11 +552,9 @@ namespace ix | ||||
|                 return; /* Need: ws.header_size+ws.N - _rxbuf.size() */ | ||||
|             } | ||||
|  | ||||
|             if (!ws.fin && ( | ||||
|                    ws.opcode == wsheader_type::PING | ||||
|                 || ws.opcode == wsheader_type::PONG | ||||
|                 || ws.opcode == wsheader_type::CLOSE | ||||
|             )){ | ||||
|             if (!ws.fin && (ws.opcode == wsheader_type::PING || ws.opcode == wsheader_type::PONG || | ||||
|                             ws.opcode == wsheader_type::CLOSE)) | ||||
|             { | ||||
|                 // Control messages should not be fragmented | ||||
|                 close(WebSocketCloseConstants::kProtocolErrorCode, | ||||
|                       WebSocketCloseConstants::kProtocolErrorCodeControlMessageFragmented); | ||||
| @@ -567,16 +566,13 @@ namespace ix | ||||
|                                   _rxbuf.begin() + ws.header_size + (size_t) ws.N); | ||||
|  | ||||
|             // We got a whole message, now do something with it: | ||||
|             if ( | ||||
|                    ws.opcode == wsheader_type::TEXT_FRAME | ||||
|                 || ws.opcode == wsheader_type::BINARY_FRAME | ||||
|                 || ws.opcode == wsheader_type::CONTINUATION | ||||
|             ) { | ||||
|  | ||||
|             if (ws.opcode == wsheader_type::TEXT_FRAME || | ||||
|                 ws.opcode == wsheader_type::BINARY_FRAME || | ||||
|                 ws.opcode == wsheader_type::CONTINUATION) | ||||
|             { | ||||
|                 if (ws.opcode != wsheader_type::CONTINUATION) | ||||
|                 { | ||||
|                     _fragmentedMessageKind = | ||||
|                         (ws.opcode == wsheader_type::TEXT_FRAME) | ||||
|                     _fragmentedMessageKind = (ws.opcode == wsheader_type::TEXT_FRAME) | ||||
|                                                  ? MessageKind::MSG_TEXT | ||||
|                                                  : MessageKind::MSG_BINARY; | ||||
|  | ||||
| @@ -592,7 +588,8 @@ namespace ix | ||||
|                 else if (_chunks.empty()) | ||||
|                 { | ||||
|                     // Continuation message need to follow a non-fin TEXT or BINARY message | ||||
|                     close(WebSocketCloseConstants::kProtocolErrorCode, | ||||
|                     close( | ||||
|                         WebSocketCloseConstants::kProtocolErrorCode, | ||||
|                         WebSocketCloseConstants::kProtocolErrorCodeContinuationOpCodeOutOfSequence); | ||||
|                 } | ||||
|  | ||||
| @@ -601,10 +598,8 @@ namespace ix | ||||
|                 // | ||||
|                 if (ws.fin && _chunks.empty()) | ||||
|                 { | ||||
|                     emitMessage(_fragmentedMessageKind, | ||||
|                                 frameData, | ||||
|                                 _compressedMessage, | ||||
|                                 onMessageCallback); | ||||
|                     emitMessage( | ||||
|                         _fragmentedMessageKind, frameData, _compressedMessage, onMessageCallback); | ||||
|  | ||||
|                     _compressedMessage = false; | ||||
|                 } | ||||
| @@ -621,8 +616,10 @@ namespace ix | ||||
|  | ||||
|                     if (ws.fin) | ||||
|                     { | ||||
|                         emitMessage(_fragmentedMessageKind, getMergedChunks(), | ||||
|                                     _compressedMessage, onMessageCallback); | ||||
|                         emitMessage(_fragmentedMessageKind, | ||||
|                                     getMergedChunks(), | ||||
|                                     _compressedMessage, | ||||
|                                     onMessageCallback); | ||||
|  | ||||
|                         _chunks.clear(); | ||||
|                         _compressedMessage = false; | ||||
| @@ -690,13 +687,11 @@ namespace ix | ||||
|                     // Full list of status code and status range is defined in the dedicated | ||||
|                     // RFC section at https://tools.ietf.org/html/rfc6455#page-45 | ||||
|                     // | ||||
|                     if (code < 1000 || code == 1004 || code == 1006 || | ||||
|                         (code > 1013 && code < 3000)) | ||||
|                     if (code < 1000 || code == 1004 || code == 1006 || (code > 1013 && code < 3000)) | ||||
|                     { | ||||
|                         // build up an error message containing the bad error code | ||||
|                         std::stringstream ss; | ||||
|                         ss << WebSocketCloseConstants::kInvalidCloseCodeMessage | ||||
|                            << ": " << code; | ||||
|                         ss << WebSocketCloseConstants::kInvalidCloseCodeMessage << ": " << code; | ||||
|                         reason = ss.str(); | ||||
|  | ||||
|                         code = WebSocketCloseConstants::kProtocolErrorCode; | ||||
| @@ -722,8 +717,8 @@ namespace ix | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // we got the CLOSE frame answer from our close, so we can close the connection if | ||||
|                     // the code/reason are the same | ||||
|                     // we got the CLOSE frame answer from our close, so we can close the connection | ||||
|                     // if the code/reason are the same | ||||
|                     bool identicalReason; | ||||
|                     { | ||||
|                         std::lock_guard<std::mutex> lock(_closeDataMutex); | ||||
| @@ -746,8 +741,7 @@ namespace ix | ||||
|             } | ||||
|  | ||||
|             // Erase the message that has been processed from the input/read buffer | ||||
|             _rxbuf.erase(_rxbuf.begin(), | ||||
|                          _rxbuf.begin() + ws.header_size + (size_t) ws.N); | ||||
|             _rxbuf.erase(_rxbuf.begin(), _rxbuf.begin() + ws.header_size + (size_t) ws.N); | ||||
|         } | ||||
|  | ||||
|         // if an abnormal closure was raised in poll, and nothing else triggered a CLOSED state in | ||||
| @@ -756,7 +750,8 @@ namespace ix | ||||
|         { | ||||
|             _rxbuf.clear(); | ||||
|  | ||||
|             // if we previously closed the connection (CLOSING state), then set state to CLOSED (code/reason were set before) | ||||
|             // if we previously closed the connection (CLOSING state), then set state to CLOSED | ||||
|             // (code/reason were set before) | ||||
|             if (_readyState == ReadyState::CLOSING) | ||||
|             { | ||||
|                 closeSocket(); | ||||
| @@ -767,7 +762,8 @@ namespace ix | ||||
|             { | ||||
|                 closeSocketAndSwitchToClosedState(WebSocketCloseConstants::kAbnormalCloseCode, | ||||
|                                                   WebSocketCloseConstants::kAbnormalCloseMessage, | ||||
|                                                   0, false); | ||||
|                                                   0, | ||||
|                                                   false); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -832,13 +828,11 @@ namespace ix | ||||
|     { | ||||
|         auto now = std::chrono::system_clock::now(); | ||||
|         auto seconds = | ||||
|             std::chrono::duration_cast<std::chrono::seconds>( | ||||
|                 now.time_since_epoch()).count(); | ||||
|             std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count(); | ||||
|         return static_cast<unsigned>(seconds); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocketTransport::sendData( | ||||
|         wsheader_type::opcode_type type, | ||||
|     WebSocketSendInfo WebSocketTransport::sendData(wsheader_type::opcode_type type, | ||||
|                                                    const std::string& message, | ||||
|                                                    bool compress, | ||||
|                                                    const OnProgressCallback& onProgressCallback) | ||||
| @@ -950,10 +944,9 @@ namespace ix | ||||
|         masking_key[3] = (x) &0xff; | ||||
|  | ||||
|         std::vector<uint8_t> header; | ||||
|         header.assign(2 + | ||||
|                       (message_size >= 126 ? 2 : 0) + | ||||
|                       (message_size >= 65536 ? 6 : 0) + | ||||
|                       (_useMask ? 4 : 0), 0); | ||||
|         header.assign(2 + (message_size >= 126 ? 2 : 0) + (message_size >= 65536 ? 6 : 0) + | ||||
|                           (_useMask ? 4 : 0), | ||||
|                       0); | ||||
|         header[0] = type; | ||||
|  | ||||
|         // The fin bit indicate that this is the last fragment. Fin is French for end. | ||||
| @@ -1017,8 +1010,7 @@ namespace ix | ||||
|         } | ||||
|  | ||||
|         // _txbuf will keep growing until it can be transmitted over the socket: | ||||
|         appendToSendBuffer(header, message_begin, message_end, | ||||
|                            message_size, masking_key); | ||||
|         appendToSendBuffer(header, message_begin, message_end, message_size, masking_key); | ||||
|  | ||||
|         // Now actually send this data | ||||
|         sendOnSocket(); | ||||
| @@ -1038,22 +1030,20 @@ namespace ix | ||||
|         return info; | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocketTransport::sendBinary( | ||||
|         const std::string& message, | ||||
|     WebSocketSendInfo WebSocketTransport::sendBinary(const std::string& message, | ||||
|                                                      const OnProgressCallback& onProgressCallback) | ||||
|  | ||||
|     { | ||||
|         return sendData(wsheader_type::BINARY_FRAME, message, | ||||
|                         _enablePerMessageDeflate, onProgressCallback); | ||||
|         return sendData( | ||||
|             wsheader_type::BINARY_FRAME, message, _enablePerMessageDeflate, onProgressCallback); | ||||
|     } | ||||
|  | ||||
|     WebSocketSendInfo WebSocketTransport::sendText( | ||||
|         const std::string& message, | ||||
|     WebSocketSendInfo WebSocketTransport::sendText(const std::string& message, | ||||
|                                                    const OnProgressCallback& onProgressCallback) | ||||
|  | ||||
|     { | ||||
|         return sendData(wsheader_type::TEXT_FRAME, message, | ||||
|                         _enablePerMessageDeflate, onProgressCallback); | ||||
|         return sendData( | ||||
|             wsheader_type::TEXT_FRAME, message, _enablePerMessageDeflate, onProgressCallback); | ||||
|     } | ||||
|  | ||||
|     ssize_t WebSocketTransport::send() | ||||
| @@ -1116,8 +1106,10 @@ namespace ix | ||||
|         _socket->close(); | ||||
|     } | ||||
|  | ||||
|     void WebSocketTransport::closeSocketAndSwitchToClosedState( | ||||
|         uint16_t code, const std::string& reason, size_t closeWireSize, bool remote) | ||||
|     void WebSocketTransport::closeSocketAndSwitchToClosedState(uint16_t code, | ||||
|                                                                const std::string& reason, | ||||
|                                                                size_t closeWireSize, | ||||
|                                                                bool remote) | ||||
|     { | ||||
|         closeSocket(); | ||||
|  | ||||
| @@ -1133,8 +1125,10 @@ namespace ix | ||||
|         _requestInitCancellation = false; | ||||
|     } | ||||
|  | ||||
|     void WebSocketTransport::close( | ||||
|         uint16_t code, const std::string& reason, size_t closeWireSize, bool remote) | ||||
|     void WebSocketTransport::close(uint16_t code, | ||||
|                                    const std::string& reason, | ||||
|                                    size_t closeWireSize, | ||||
|                                    bool remote) | ||||
|     { | ||||
|         _requestInitCancellation = true; | ||||
|  | ||||
|   | ||||
| @@ -25,7 +25,6 @@ | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| #include <string> | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| namespace ix | ||||
|   | ||||
| @@ -44,13 +44,22 @@ static bool IsSchemeValid( const std::string& SchemeName ) | ||||
|  | ||||
| bool LUrlParser::clParseURL::GetPort(int* OutPort) const | ||||
| { | ||||
| 	if ( !IsValid() ) { return false; } | ||||
|     if (!IsValid()) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     int Port = atoi(m_Port.c_str()); | ||||
|  | ||||
| 	if ( Port <= 0 || Port > 65535 ) { return false; } | ||||
|     if (Port <= 0 || Port > 65535) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| 	if ( OutPort ) { *OutPort = Port; } | ||||
|     if (OutPort) | ||||
|     { | ||||
|         *OutPort = Port; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
| @@ -65,7 +74,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL | ||||
|     /* | ||||
|      *	<scheme>:<scheme-specific-part> | ||||
|      *	<scheme> := [a-z\+\-\.]+ | ||||
| 	 *	For resiliency, programs interpreting URLs should treat upper case letters as equivalent to lower case in scheme names | ||||
|      *	For resiliency, programs interpreting URLs should treat upper case letters as equivalent to | ||||
|      *lower case in scheme names | ||||
|      */ | ||||
|  | ||||
|     // try to read scheme | ||||
| @@ -86,7 +96,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL | ||||
|         } | ||||
|  | ||||
|         // scheme should be lowercase | ||||
| 		std::transform( Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower ); | ||||
|         std::transform( | ||||
|             Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower); | ||||
|  | ||||
|         // skip ':' | ||||
|         CurrentString = LocalString + 1; | ||||
| @@ -130,7 +141,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL | ||||
|     if (bHasUserName) | ||||
|     { | ||||
|         // read user name | ||||
| 		while ( *LocalString && *LocalString != ':' && *LocalString != '@' ) LocalString++; | ||||
|         while (*LocalString && *LocalString != ':' && *LocalString != '@') | ||||
|             LocalString++; | ||||
|  | ||||
|         Result.m_UserName = std::string(CurrentString, LocalString - CurrentString); | ||||
|  | ||||
| @@ -145,7 +157,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL | ||||
|             // read password | ||||
|             LocalString = CurrentString; | ||||
|  | ||||
| 			while ( *LocalString && *LocalString != '@' ) LocalString++; | ||||
|             while (*LocalString && *LocalString != '@') | ||||
|                 LocalString++; | ||||
|  | ||||
|             Result.m_Password = std::string(CurrentString, LocalString - CurrentString); | ||||
|  | ||||
| @@ -195,7 +208,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL | ||||
|         // read port number | ||||
|         LocalString = CurrentString; | ||||
|  | ||||
| 		while ( *LocalString && *LocalString != '/' ) LocalString++; | ||||
|         while (*LocalString && *LocalString != '/') | ||||
|             LocalString++; | ||||
|  | ||||
|         Result.m_Port = std::string(CurrentString, LocalString - CurrentString); | ||||
|  | ||||
| @@ -221,7 +235,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL | ||||
|     // parse the path | ||||
|     LocalString = CurrentString; | ||||
|  | ||||
| 	while ( *LocalString && *LocalString != '#' && *LocalString != '?' ) LocalString++; | ||||
|     while (*LocalString && *LocalString != '#' && *LocalString != '?') | ||||
|         LocalString++; | ||||
|  | ||||
|     Result.m_Path = std::string(CurrentString, LocalString - CurrentString); | ||||
|  | ||||
| @@ -236,7 +251,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL | ||||
|         // read query | ||||
|         LocalString = CurrentString; | ||||
|  | ||||
| 		while ( *LocalString && *LocalString != '#' ) LocalString++; | ||||
|         while (*LocalString && *LocalString != '#') | ||||
|             LocalString++; | ||||
|  | ||||
|         Result.m_Query = std::string(CurrentString, LocalString - CurrentString); | ||||
|  | ||||
| @@ -252,7 +268,8 @@ LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL | ||||
|         // read fragment | ||||
|         LocalString = CurrentString; | ||||
|  | ||||
| 		while ( *LocalString ) LocalString++; | ||||
|         while (*LocalString) | ||||
|             LocalString++; | ||||
|  | ||||
|         Result.m_Fragment = std::string(CurrentString, LocalString - CurrentString); | ||||
|     } | ||||
|   | ||||
| @@ -62,7 +62,10 @@ namespace LUrlParser | ||||
|         } | ||||
|  | ||||
|         /// return 'true' if the parsing was successful | ||||
|         bool IsValid() const { return m_ErrorCode == LUrlParserError_Ok; } | ||||
|         bool IsValid() const | ||||
|         { | ||||
|             return m_ErrorCode == LUrlParserError_Ok; | ||||
|         } | ||||
|  | ||||
|         /// helper to convert the port number to int, return 'true' if the port is valid (within the | ||||
|         /// 0..65535 range) | ||||
|   | ||||
| @@ -17,4 +17,4 @@ namespace ix | ||||
|         // | ||||
|         pthread_setname_np(name.substr(0, 63).c_str()); | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -15,7 +15,6 @@ namespace ix | ||||
|         // See prctl and PR_SET_NAME property in | ||||
|         // http://man7.org/linux/man-pages/man2/prctl.2.html | ||||
|         // | ||||
|         pthread_setname_np(pthread_self(), | ||||
|                            name.substr(0, 15).c_str()); | ||||
|     } | ||||
|         pthread_setname_np(pthread_self(), name.substr(0, 15).c_str()); | ||||
|     } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
| #include "../IXSetThreadName.h" | ||||
|  | ||||
| #include <Windows.h> | ||||
|  | ||||
| namespace ix | ||||
| @@ -30,7 +31,8 @@ namespace ix | ||||
|  | ||||
|         __try | ||||
|         { | ||||
|             RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)& info); | ||||
|             RaiseException( | ||||
|                 MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*) &info); | ||||
|         } | ||||
|         __except (EXCEPTION_EXECUTE_HANDLER) | ||||
|         { | ||||
| @@ -41,4 +43,4 @@ namespace ix | ||||
|     { | ||||
|         SetThreadName(-1, name.c_str()); | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,14 +4,13 @@ | ||||
|  *  Copyright (c) 2017 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include "IXSnakeServer.h" | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <chrono> | ||||
| #include <iostream> | ||||
| #include <ixcobra/IXCobraConnection.h> | ||||
| #include <ixcrypto/IXUuid.h> | ||||
| #include "IXTest.h" | ||||
| #include "IXSnakeServer.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -22,9 +21,7 @@ namespace | ||||
|  | ||||
|     void setupTrafficTrackerCallback() | ||||
|     { | ||||
|         ix::CobraConnection::setTrafficTrackerCallback( | ||||
|             [](size_t size, bool incoming) | ||||
|             { | ||||
|         ix::CobraConnection::setTrafficTrackerCallback([](size_t size, bool incoming) { | ||||
|             if (incoming) | ||||
|             { | ||||
|                 incomingBytes += size; | ||||
| @@ -33,8 +30,7 @@ namespace | ||||
|             { | ||||
|                 outgoingBytes += size; | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     class SatoriChat | ||||
| @@ -77,12 +73,12 @@ namespace | ||||
|  | ||||
|     SatoriChat::SatoriChat(const std::string& user, | ||||
|                            const std::string& session, | ||||
|                            const std::string& endpoint) : | ||||
|         _user(user), | ||||
|         _session(session), | ||||
|         _endpoint(endpoint), | ||||
|         _stop(false), | ||||
|         _connectedAndSubscribed(false) | ||||
|                            const std::string& endpoint) | ||||
|         : _user(user) | ||||
|         , _session(session) | ||||
|         , _endpoint(endpoint) | ||||
|         , _stop(false) | ||||
|         , _connectedAndSubscribed(false) | ||||
|     { | ||||
|     } | ||||
|  | ||||
| @@ -127,9 +123,7 @@ namespace | ||||
|     void SatoriChat::subscribe(const std::string& channel) | ||||
|     { | ||||
|         std::string filter; | ||||
|         _conn.subscribe(channel, filter, | ||||
|                         [this](const Json::Value& msg) | ||||
|                         { | ||||
|         _conn.subscribe(channel, filter, [this](const Json::Value& msg) { | ||||
|             std::cout << msg.toStyledString() << std::endl; | ||||
|             if (!msg.isObject()) return; | ||||
|             if (!msg.isMember("user")) return; | ||||
| @@ -150,10 +144,7 @@ namespace | ||||
|             _receivedQueue.push(msg); | ||||
|  | ||||
|             std::stringstream ss; | ||||
|                             ss << std::endl | ||||
|                                << msg_user << " > " << msg_text | ||||
|                                << std::endl | ||||
|                                << _user << " > "; | ||||
|             ss << std::endl << msg_user << " > " << msg_text << std::endl << _user << " > "; | ||||
|             log(ss.str()); | ||||
|         }); | ||||
|     } | ||||
| @@ -189,18 +180,15 @@ namespace | ||||
|         std::string role = "_sub"; | ||||
|         std::string secret = "66B1dA3ED5fA074EB5AE84Dd8CE3b5ba"; | ||||
|  | ||||
|         _conn.configure(appkey, _endpoint, role, secret, | ||||
|                         ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         _conn.configure( | ||||
|             appkey, _endpoint, role, secret, ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         _conn.connect(); | ||||
|  | ||||
|         _conn.setEventCallback( | ||||
|             [this, channel] | ||||
|             (ix::CobraConnectionEventType eventType, | ||||
|         _conn.setEventCallback([this, channel](ix::CobraConnectionEventType eventType, | ||||
|                                                const std::string& errMsg, | ||||
|                                                const ix::WebSocketHttpHeaders& /*headers*/, | ||||
|                                                const std::string& subscriptionId, | ||||
|              CobraConnection::MsgId msgId) | ||||
|             { | ||||
|                                                CobraConnection::MsgId msgId) { | ||||
|             if (eventType == ix::CobraConnection_EventType_Open) | ||||
|             { | ||||
|                 log("Subscriber connected: " + _user); | ||||
| @@ -231,8 +219,7 @@ namespace | ||||
|             { | ||||
|                 Logger() << "Subscriber: published message acked: " << msgId; | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|  | ||||
|         while (!_stop) | ||||
|         { | ||||
| @@ -261,19 +248,15 @@ namespace | ||||
|         ix::msleep(50); | ||||
|         _conn.disconnect(); | ||||
|  | ||||
|         _conn.setEventCallback([] | ||||
|                                (ix::CobraConnectionEventType /*eventType*/, | ||||
|         _conn.setEventCallback([](ix::CobraConnectionEventType /*eventType*/, | ||||
|                                   const std::string& /*errMsg*/, | ||||
|                                   const ix::WebSocketHttpHeaders& /*headers*/, | ||||
|                                   const std::string& /*subscriptionId*/, | ||||
|                                 CobraConnection::MsgId /*msgId*/) | ||||
|         { | ||||
|             ; | ||||
|         }); | ||||
|                                   CobraConnection::MsgId /*msgId*/) { ; }); | ||||
|  | ||||
|         snakeServer.stop(); | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| TEST_CASE("Cobra_chat", "[cobra_chat]") | ||||
| { | ||||
|   | ||||
| @@ -3,14 +3,13 @@ | ||||
|  *  Copyright (c) 2018 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <set> | ||||
| #include <ixcrypto/IXUuid.h> | ||||
| #include <ixcobra/IXCobraMetricsPublisher.h> | ||||
| #include "IXTest.h" | ||||
| #include "IXSnakeServer.h" | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixcobra/IXCobraMetricsPublisher.h> | ||||
| #include <ixcrypto/IXUuid.h> | ||||
| #include <set> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -45,18 +44,18 @@ namespace | ||||
|         gMessageCount = 0; | ||||
|  | ||||
|         ix::CobraConnection conn; | ||||
|         conn.configure(APPKEY, endpoint, SUBSCRIBER_ROLE, SUBSCRIBER_SECRET, | ||||
|         conn.configure(APPKEY, | ||||
|                        endpoint, | ||||
|                        SUBSCRIBER_ROLE, | ||||
|                        SUBSCRIBER_SECRET, | ||||
|                        ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.connect(); | ||||
|  | ||||
|         conn.setEventCallback( | ||||
|             [&conn] | ||||
|             (ix::CobraConnectionEventType eventType, | ||||
|         conn.setEventCallback([&conn](ix::CobraConnectionEventType eventType, | ||||
|                                       const std::string& errMsg, | ||||
|                                       const ix::WebSocketHttpHeaders& /*headers*/, | ||||
|                                       const std::string& subscriptionId, | ||||
|              CobraConnection::MsgId msgId) | ||||
|             { | ||||
|                                       CobraConnection::MsgId msgId) { | ||||
|             if (eventType == ix::CobraConnection_EventType_Open) | ||||
|             { | ||||
|                 Logger() << "Subscriber connected:"; | ||||
| @@ -69,9 +68,7 @@ namespace | ||||
|             { | ||||
|                 log("Subscriber authenticated"); | ||||
|                 std::string filter; | ||||
|                     conn.subscribe(CHANNEL, filter, | ||||
|                                    [](const Json::Value& msg) | ||||
|                                    { | ||||
|                 conn.subscribe(CHANNEL, filter, [](const Json::Value& msg) { | ||||
|                     log(msg.toStyledString()); | ||||
|  | ||||
|                     std::string id = msg["id"].asString(); | ||||
| @@ -107,8 +104,7 @@ namespace | ||||
|             { | ||||
|                 Logger() << "Subscriber: published message acked: " << msgId; | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|  | ||||
|         while (!gStop) | ||||
|         { | ||||
| @@ -121,7 +117,7 @@ namespace | ||||
|  | ||||
|         gUniqueMessageIdsCount = gIds.size(); | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| TEST_CASE("Cobra_Metrics_Publisher", "[cobra]") | ||||
| { | ||||
| @@ -158,8 +154,8 @@ TEST_CASE("Cobra_Metrics_Publisher", "[cobra]") | ||||
|     ix::CobraMetricsPublisher cobraMetricsPublisher; | ||||
|  | ||||
|     bool perMessageDeflate = true; | ||||
|     cobraMetricsPublisher.configure(APPKEY, endpoint, CHANNEL, | ||||
|                                     PUBLISHER_ROLE, PUBLISHER_SECRET, perMessageDeflate); | ||||
|     cobraMetricsPublisher.configure( | ||||
|         APPKEY, endpoint, CHANNEL, PUBLISHER_ROLE, PUBLISHER_SECRET, perMessageDeflate); | ||||
|     cobraMetricsPublisher.setSession(uuid4()); | ||||
|     cobraMetricsPublisher.enable(true); // disabled by default, needs to be enabled to be active | ||||
|  | ||||
|   | ||||
| @@ -4,11 +4,10 @@ | ||||
|  *  Copyright (c) 2018 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include <ixwebsocket/IXDNSLookup.h> | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXDNSLookup.h> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -32,7 +31,11 @@ TEST_CASE("dns", "[net]") | ||||
|         auto dnsLookup = std::make_shared<DNSLookup>("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww", 80); | ||||
|  | ||||
|         std::string errMsg; | ||||
|         struct addrinfo* res = dnsLookup->resolve(errMsg, [] { return false; }); | ||||
|         struct addrinfo* res = dnsLookup->resolve(errMsg, | ||||
|                                                   [] | ||||
|                                                   { | ||||
|                                                       return false; | ||||
|                                                   }); | ||||
|         std::cerr << "Error message: " << errMsg << std::endl; | ||||
|         REQUIRE(res == nullptr); | ||||
|     } | ||||
| @@ -43,7 +46,11 @@ TEST_CASE("dns", "[net]") | ||||
|  | ||||
|         std::string errMsg; | ||||
|         // The callback returning true means we are requesting cancellation | ||||
|         struct addrinfo* res = dnsLookup->resolve(errMsg, [] { return true; }); | ||||
|         struct addrinfo* res = dnsLookup->resolve(errMsg, | ||||
|                                                   [] | ||||
|                                                   { | ||||
|                                                       return true; | ||||
|                                                   }); | ||||
|         std::cerr << "Error message: " << errMsg << std::endl; | ||||
|         REQUIRE(res == nullptr); | ||||
|     } | ||||
|   | ||||
| @@ -5,11 +5,11 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXGetFreePort.h" | ||||
|  | ||||
| #include <ixwebsocket/IXNetSystem.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
|  | ||||
| #include <string> | ||||
| #include <random> | ||||
| #include <string> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -30,8 +30,7 @@ namespace ix | ||||
|         } | ||||
|  | ||||
|         int enable = 1; | ||||
|         if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, | ||||
|                        (char*) &enable, sizeof(enable)) < 0) | ||||
|         if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*) &enable, sizeof(enable)) < 0) | ||||
|         { | ||||
|             return getAnyFreePortRandom(); | ||||
|         } | ||||
|   | ||||
| @@ -4,11 +4,10 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXHttpClient.h> | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| TEST_CASE("http client", "[http]") | ||||
| @@ -28,14 +27,10 @@ TEST_CASE("http client", "[http]") | ||||
|         args->maxRedirects = 10; | ||||
|         args->verbose = true; | ||||
|         args->compress = true; | ||||
|         args->logger = [](const std::string& msg) | ||||
|         { | ||||
|             std::cout << msg; | ||||
|         }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool | ||||
|         { | ||||
|             std::cerr << "\r" << "Downloaded " | ||||
|                       << current << " bytes out of " << total; | ||||
|         args->logger = [](const std::string& msg) { std::cout << msg; }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool { | ||||
|             std::cerr << "\r" | ||||
|                       << "Downloaded " << current << " bytes out of " << total; | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
| @@ -70,14 +65,10 @@ TEST_CASE("http client", "[http]") | ||||
|         args->maxRedirects = 10; | ||||
|         args->verbose = true; | ||||
|         args->compress = true; | ||||
|         args->logger = [](const std::string& msg) | ||||
|         { | ||||
|             std::cout << msg; | ||||
|         }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool | ||||
|         { | ||||
|             std::cerr << "\r" << "Downloaded " | ||||
|                       << current << " bytes out of " << total; | ||||
|         args->logger = [](const std::string& msg) { std::cout << msg; }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool { | ||||
|             std::cerr << "\r" | ||||
|                       << "Downloaded " << current << " bytes out of " << total; | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
| @@ -113,23 +104,18 @@ TEST_CASE("http client", "[http]") | ||||
|         args->maxRedirects = 10; | ||||
|         args->verbose = true; | ||||
|         args->compress = true; | ||||
|         args->logger = [](const std::string& msg) | ||||
|         { | ||||
|             std::cout << msg; | ||||
|         }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool | ||||
|         { | ||||
|             std::cerr << "\r" << "Downloaded " | ||||
|                       << current << " bytes out of " << total; | ||||
|         args->logger = [](const std::string& msg) { std::cout << msg; }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool { | ||||
|             std::cerr << "\r" | ||||
|                       << "Downloaded " << current << " bytes out of " << total; | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
|         std::atomic<bool> requestCompleted(false); | ||||
|         std::atomic<int> statusCode(0); | ||||
|  | ||||
|         httpClient.performRequest(args, [&requestCompleted, &statusCode] | ||||
|             (const HttpResponsePtr& response) | ||||
|             { | ||||
|         httpClient.performRequest( | ||||
|             args, [&requestCompleted, &statusCode](const HttpResponsePtr& response) { | ||||
|                 std::cerr << "Upload size: " << response->uploadSize << std::endl; | ||||
|                 std::cerr << "Download size: " << response->downloadSize << std::endl; | ||||
|                 std::cerr << "Status: " << response->statusCode << std::endl; | ||||
| @@ -138,8 +124,7 @@ TEST_CASE("http client", "[http]") | ||||
|                 // In case of failure, print response->errorMsg | ||||
|                 statusCode = response->statusCode; | ||||
|                 requestCompleted = true; | ||||
|             } | ||||
|         ); | ||||
|             }); | ||||
|  | ||||
|         int wait = 0; | ||||
|         while (wait < 5000) | ||||
| @@ -171,14 +156,10 @@ TEST_CASE("http client", "[http]") | ||||
|         args->maxRedirects = 10; | ||||
|         args->verbose = true; | ||||
|         args->compress = true; | ||||
|         args->logger = [](const std::string& msg) | ||||
|         { | ||||
|             std::cout << msg; | ||||
|         }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool | ||||
|         { | ||||
|             std::cerr << "\r" << "Downloaded " | ||||
|                       << current << " bytes out of " << total; | ||||
|         args->logger = [](const std::string& msg) { std::cout << msg; }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool { | ||||
|             std::cerr << "\r" | ||||
|                       << "Downloaded " << current << " bytes out of " << total; | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
| @@ -189,9 +170,10 @@ TEST_CASE("http client", "[http]") | ||||
|  | ||||
|         for (int i = 0; i < 3; ++i) | ||||
|         { | ||||
|             httpClient.performRequest(args, [i, &requestCompleted, &statusCode0, &statusCode1, &statusCode2] | ||||
|                 (const HttpResponsePtr& response) | ||||
|                 { | ||||
|             httpClient.performRequest( | ||||
|                 args, | ||||
|                 [i, &requestCompleted, &statusCode0, &statusCode1, &statusCode2]( | ||||
|                     const HttpResponsePtr& response) { | ||||
|                     std::cerr << "Upload size: " << response->uploadSize << std::endl; | ||||
|                     std::cerr << "Download size: " << response->downloadSize << std::endl; | ||||
|                     std::cerr << "Status: " << response->statusCode << std::endl; | ||||
| @@ -211,8 +193,7 @@ TEST_CASE("http client", "[http]") | ||||
|                         statusCode2 = response->statusCode; | ||||
|                         requestCompleted = true; | ||||
|                     } | ||||
|                 } | ||||
|             ); | ||||
|                 }); | ||||
|         } | ||||
|  | ||||
|         int wait = 0; | ||||
|   | ||||
| @@ -4,12 +4,11 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "IXGetFreePort.h" | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXHttpClient.h> | ||||
| #include <ixwebsocket/IXHttpServer.h> | ||||
| #include "IXGetFreePort.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -39,14 +38,10 @@ TEST_CASE("http server", "[httpd]") | ||||
|         args->maxRedirects = 10; | ||||
|         args->verbose = true; | ||||
|         args->compress = true; | ||||
|         args->logger = [](const std::string& msg) | ||||
|         { | ||||
|             std::cout << msg; | ||||
|         }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool | ||||
|         { | ||||
|             std::cerr << "\r" << "Downloaded " | ||||
|                       << current << " bytes out of " << total; | ||||
|         args->logger = [](const std::string& msg) { std::cout << msg; }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool { | ||||
|             std::cerr << "\r" | ||||
|                       << "Downloaded " << current << " bytes out of " << total; | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
|   | ||||
| @@ -4,15 +4,13 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXHttp.h> | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <string.h> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|  | ||||
|     TEST_CASE("http", "[http]") | ||||
|     { | ||||
|         SECTION("Normal case") | ||||
| @@ -52,4 +50,4 @@ TEST_CASE("http", "[http]") | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,11 +4,10 @@ | ||||
|  *  Copyright (c) 2018 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include <ixwebsocket/IXSocketConnect.h> | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXSocketConnect.h> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
|   | ||||
| @@ -4,13 +4,12 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXSocketFactory.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXCancellationRequest.h> | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXCancellationRequest.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXSocketFactory.h> | ||||
| #include <string.h> | ||||
|  | ||||
| using namespace ix; | ||||
| @@ -33,8 +32,7 @@ namespace ix | ||||
|         Logger() << "errMsg: " << errMsg; | ||||
|         REQUIRE(success); | ||||
|  | ||||
|         Logger() << "Sending request: " << request | ||||
|                  << "to " << host << ":" << port; | ||||
|         Logger() << "Sending request: " << request << "to " << host << ":" << port; | ||||
|         REQUIRE(socket->writeBytes(request, isCancellationRequested)); | ||||
|  | ||||
|         auto lineResult = socket->readLine(isCancellationRequested); | ||||
| @@ -49,11 +47,12 @@ namespace ix | ||||
|         REQUIRE(sscanf(line.c_str(), "HTTP/1.1 %d", &status) == 1); | ||||
|         REQUIRE(status == expectedStatus); | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|  | ||||
| TEST_CASE("socket", "[socket]") | ||||
| { | ||||
|     SECTION("Connect to a local websocket server over a free port. Send GET request without header. Should return 400") | ||||
|     SECTION("Connect to a local websocket server over a free port. Send GET request without " | ||||
|             "header. Should return 400") | ||||
|     { | ||||
|         // Start a server first which we'll hit with our socket code | ||||
|         int port = getFreePort(); | ||||
| @@ -78,7 +77,8 @@ TEST_CASE("socket", "[socket]") | ||||
|     } | ||||
|  | ||||
| #if defined(IXWEBSOCKET_USE_TLS) | ||||
|     SECTION("Connect to google HTTPS server over port 443. Send GET request without header. Should return 200") | ||||
|     SECTION("Connect to google HTTPS server over port 443. Send GET request without header. Should " | ||||
|             "return 200") | ||||
|     { | ||||
|         std::string errMsg; | ||||
|         bool tls = true; | ||||
|   | ||||
| @@ -5,19 +5,19 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXNetSystem.h> | ||||
|  | ||||
| #include <chrono> | ||||
| #include <thread> | ||||
| #include <mutex> | ||||
| #include <string> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <stdlib.h> | ||||
| #include <stack> | ||||
| #include <iomanip> | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXNetSystem.h> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <mutex> | ||||
| #include <random> | ||||
| #include <stack> | ||||
| #include <stdlib.h> | ||||
| #include <string> | ||||
| #include <thread> | ||||
|  | ||||
|  | ||||
| namespace ix | ||||
| @@ -29,9 +29,7 @@ namespace ix | ||||
|  | ||||
|     void setupWebSocketTrafficTrackerCallback() | ||||
|     { | ||||
|         ix::WebSocket::setTrafficTrackerCallback( | ||||
|             [](size_t size, bool incoming) | ||||
|             { | ||||
|         ix::WebSocket::setTrafficTrackerCallback([](size_t size, bool incoming) { | ||||
|             if (incoming) | ||||
|             { | ||||
|                 incomingBytes += size; | ||||
| @@ -40,8 +38,7 @@ namespace ix | ||||
|             { | ||||
|                 outgoingBytes += size; | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     void reportWebSocketTraffic() | ||||
| @@ -61,8 +58,7 @@ namespace ix | ||||
|     { | ||||
|         auto now = std::chrono::system_clock::now(); | ||||
|         auto seconds = | ||||
|             std::chrono::duration_cast<std::chrono::seconds>( | ||||
|                 now.time_since_epoch()).count(); | ||||
|             std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count(); | ||||
|  | ||||
|         return std::to_string(seconds); | ||||
|     } | ||||
| @@ -72,17 +68,14 @@ namespace ix | ||||
|         Logger() << msg; | ||||
|     } | ||||
|  | ||||
|     void hexDump(const std::string& prefix, | ||||
|                  const std::string& s) | ||||
|     void hexDump(const std::string& prefix, const std::string& s) | ||||
|     { | ||||
|         std::ostringstream ss; | ||||
|         bool upper_case = false; | ||||
|  | ||||
|         for (std::string::size_type i = 0; i < s.length(); ++i) | ||||
|         { | ||||
|             ss << std::hex | ||||
|                << std::setfill('0') | ||||
|                << std::setw(2) | ||||
|             ss << std::hex << std::setfill('0') << std::setw(2) | ||||
|                << (upper_case ? std::uppercase : std::nouppercase) << (int) s[i]; | ||||
|         } | ||||
|  | ||||
| @@ -91,13 +84,10 @@ namespace ix | ||||
|  | ||||
|     bool startWebSocketEchoServer(ix::WebSocketServer& server) | ||||
|     { | ||||
|         server.setOnConnectionCallback( | ||||
|             [&server](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                       std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|         server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                                  std::shared_ptr<ConnectionState> connectionState) { | ||||
|             webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) | ||||
|                     { | ||||
|                 [webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) { | ||||
|                     if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                     { | ||||
|                         Logger() << "New connection"; | ||||
| @@ -122,10 +112,8 @@ namespace ix | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -190,4 +178,4 @@ namespace ix | ||||
|  | ||||
|         return appConfig; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -6,10 +6,10 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "IXAppConfig.h" | ||||
| #include "IXGetFreePort.h" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
| #include "IXAppConfig.h" | ||||
| #include <mutex> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <ixwebsocket/IXCancellationRequest.h> | ||||
| #include <ixwebsocket/IXConnectionState.h> | ||||
| #include <ixwebsocket/IXDNSLookup.h> | ||||
| @@ -39,8 +40,6 @@ | ||||
| #include <ixwebsocket/LUrlParser.h> | ||||
| #include <ixwebsocket/libwshandshake.hpp> | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| TEST_CASE("unity build", "[unity_build]") | ||||
|   | ||||
| @@ -4,18 +4,16 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXUrlParser.h> | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXUrlParser.h> | ||||
| #include <string.h> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|  | ||||
|     TEST_CASE("urlParser", "[urlParser]") | ||||
|     { | ||||
|         SECTION("http://google.com") | ||||
| @@ -88,7 +86,12 @@ TEST_CASE("urlParser", "[urlParser]") | ||||
|  | ||||
|         SECTION("real test") | ||||
|         { | ||||
|         std::string url = "ws://127.0.0.1:7350/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf"; | ||||
|             std::string url = | ||||
|                 "ws://127.0.0.1:7350/" | ||||
|                 "ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." | ||||
|                 "eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZi" | ||||
|                 "IsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=" | ||||
|                 "true&format=protobuf"; | ||||
|             std::string protocol, host, path, query; | ||||
|             int port; | ||||
|             bool res; | ||||
| @@ -98,11 +101,18 @@ TEST_CASE("urlParser", "[urlParser]") | ||||
|             REQUIRE(res); | ||||
|             REQUIRE(protocol == "ws"); | ||||
|             REQUIRE(host == "127.0.0.1"); | ||||
|         REQUIRE(path == "/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf"); | ||||
|         REQUIRE(query == "token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf"); | ||||
|             REQUIRE(path == | ||||
|                     "/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." | ||||
|                     "eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNW" | ||||
|                     "QxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&" | ||||
|                     "status=true&format=protobuf"); | ||||
|             REQUIRE(query == | ||||
|                     "token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." | ||||
|                     "eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNW" | ||||
|                     "QxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&" | ||||
|                     "status=true&format=protobuf"); | ||||
|             REQUIRE(port == 7350); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -9,17 +9,15 @@ | ||||
| // websocket_chat_server/broacast-server.js | ||||
| // | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include "msgpack11.hpp" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
| #include <mutex> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
| #include "msgpack11.hpp" | ||||
|  | ||||
| #include "IXTest.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <mutex> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| using msgpack11::MsgPack; | ||||
| using namespace ix; | ||||
| @@ -29,9 +27,7 @@ namespace | ||||
|     class WebSocketChat | ||||
|     { | ||||
|     public: | ||||
|             WebSocketChat(const std::string& user, | ||||
|                           const std::string& session, | ||||
|                           int port); | ||||
|         WebSocketChat(const std::string& user, const std::string& session, int port); | ||||
|  | ||||
|         void subscribe(const std::string& channel); | ||||
|         void start(); | ||||
| @@ -57,12 +53,10 @@ namespace | ||||
|         mutable std::mutex _mutex; | ||||
|     }; | ||||
|  | ||||
|     WebSocketChat::WebSocketChat(const std::string& user, | ||||
|                                  const std::string& session, | ||||
|                                  int port) : | ||||
|         _user(user), | ||||
|         _session(session), | ||||
|         _port(port) | ||||
|     WebSocketChat::WebSocketChat(const std::string& user, const std::string& session, int port) | ||||
|         : _user(user) | ||||
|         , _session(session) | ||||
|         , _port(port) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -100,10 +94,7 @@ namespace | ||||
|         std::string url; | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "ws://127.0.0.1:" | ||||
|                << _port | ||||
|                << "/" | ||||
|                << _user; | ||||
|             ss << "ws://127.0.0.1:" << _port << "/" << _user; | ||||
|  | ||||
|             url = ss.str(); | ||||
|         } | ||||
| @@ -113,22 +104,16 @@ namespace | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) { | ||||
|             std::stringstream ss; | ||||
|             if (msg->type == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
|                     ss << "cmd_websocket_chat: user " | ||||
|                        << _user | ||||
|                        << " Connected !"; | ||||
|                 ss << "cmd_websocket_chat: user " << _user << " Connected !"; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|             { | ||||
|                     ss << "cmd_websocket_chat: user " | ||||
|                        << _user | ||||
|                        << " disconnected !"; | ||||
|                 ss << "cmd_websocket_chat: user " << _user << " disconnected !"; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Message) | ||||
| @@ -148,10 +133,7 @@ namespace | ||||
|                     payload = "<message too large>"; | ||||
|                 } | ||||
|  | ||||
|                     ss << std::endl | ||||
|                        << result.first << " > " << payload | ||||
|                        << std::endl | ||||
|                        << _user << " > "; | ||||
|                 ss << std::endl << result.first << " > " << payload << std::endl << _user << " > "; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Error) | ||||
| @@ -211,13 +193,10 @@ namespace | ||||
|  | ||||
|     bool startServer(ix::WebSocketServer& server) | ||||
|     { | ||||
|         server.setOnConnectionCallback( | ||||
|             [&server](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                       std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|         server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                                  std::shared_ptr<ConnectionState> connectionState) { | ||||
|             webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) | ||||
|                     { | ||||
|                 [webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) { | ||||
|                     if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                     { | ||||
|                         Logger() << "New connection"; | ||||
| @@ -243,10 +222,8 @@ namespace | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -258,7 +235,7 @@ namespace | ||||
|         server.start(); | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| TEST_CASE("Websocket_chat", "[websocket_chat]") | ||||
| { | ||||
| @@ -305,8 +282,7 @@ TEST_CASE("Websocket_chat", "[websocket_chat]") | ||||
|  | ||||
|         // Wait until all messages are received. 10s timeout | ||||
|         int attempts = 0; | ||||
|         while (chatA.getReceivedMessagesCount() != 3 || | ||||
|                chatB.getReceivedMessagesCount() != 3) | ||||
|         while (chatA.getReceivedMessagesCount() != 3 || chatB.getReceivedMessagesCount() != 3) | ||||
|         { | ||||
|             REQUIRE(attempts++ < 10); | ||||
|             ix::msleep(1000); | ||||
|   | ||||
| @@ -4,15 +4,13 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <queue> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
|  | ||||
| #include "IXTest.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <queue> | ||||
| #include <sstream> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -102,9 +100,7 @@ namespace | ||||
|         std::string url; | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "ws://localhost:" | ||||
|                << _port | ||||
|                << "/"; | ||||
|             ss << "ws://localhost:" << _port << "/"; | ||||
|  | ||||
|             url = ss.str(); | ||||
|         } | ||||
| @@ -115,9 +111,7 @@ namespace | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) { | ||||
|             std::stringstream ss; | ||||
|             if (msg->type == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
| @@ -126,10 +120,7 @@ namespace | ||||
|             else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|             { | ||||
|                 std::stringstream ss; | ||||
|                     ss << "client disconnected(" | ||||
|                        << msg->closeInfo.code | ||||
|                        << "," | ||||
|                        << msg->closeInfo.reason | ||||
|                 ss << "client disconnected(" << msg->closeInfo.code << "," << msg->closeInfo.reason | ||||
|                    << ")"; | ||||
|                 log(ss.str()); | ||||
|  | ||||
| @@ -178,12 +169,15 @@ namespace | ||||
|     { | ||||
|         // A dev/null server | ||||
|         server.setOnConnectionCallback( | ||||
|             [&receivedCloseCode, &receivedCloseReason, &receivedCloseRemote, &mutexWrite](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                              std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|                 webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, &receivedCloseCode, &receivedCloseReason, &receivedCloseRemote, &mutexWrite](const ix::WebSocketMessagePtr& msg) | ||||
|                     { | ||||
|             [&receivedCloseCode, &receivedCloseReason, &receivedCloseRemote, &mutexWrite]( | ||||
|                 std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                 std::shared_ptr<ConnectionState> connectionState) { | ||||
|                 webSocket->setOnMessageCallback([webSocket, | ||||
|                                                  connectionState, | ||||
|                                                  &receivedCloseCode, | ||||
|                                                  &receivedCloseReason, | ||||
|                                                  &receivedCloseRemote, | ||||
|                                                  &mutexWrite](const ix::WebSocketMessagePtr& msg) { | ||||
|                     if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                     { | ||||
|                         Logger() << "New server connection"; | ||||
| @@ -198,11 +192,8 @@ namespace | ||||
|                     else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|                     { | ||||
|                         std::stringstream ss; | ||||
|                             ss << "Server closed connection(" | ||||
|                                << msg->closeInfo.code | ||||
|                                << "," | ||||
|                                << msg->closeInfo.reason | ||||
|                                << ")"; | ||||
|                         ss << "Server closed connection(" << msg->closeInfo.code << "," | ||||
|                            << msg->closeInfo.reason << ")"; | ||||
|                         log(ss.str()); | ||||
|  | ||||
|                         std::lock_guard<std::mutex> lck(mutexWrite); | ||||
| @@ -211,10 +202,8 @@ namespace | ||||
|                         receivedCloseReason = std::string(msg->closeInfo.reason); | ||||
|                         receivedCloseRemote = msg->closeInfo.remote; | ||||
|                     } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -226,7 +215,7 @@ namespace | ||||
|         server.start(); | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| TEST_CASE("Websocket_client_close_default", "[close]") | ||||
| { | ||||
| @@ -242,7 +231,11 @@ TEST_CASE("Websocket_client_close_default", "[close]") | ||||
|         std::string serverReceivedCloseReason(""); | ||||
|         std::mutex mutexWrite; | ||||
|  | ||||
|         REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite)); | ||||
|         REQUIRE(startServer(server, | ||||
|                             serverReceivedCloseCode, | ||||
|                             serverReceivedCloseReason, | ||||
|                             serverReceivedCloseRemote, | ||||
|                             mutexWrite)); | ||||
|  | ||||
|         std::string session = ix::generateSessionId(); | ||||
|         WebSocketClient webSocketClient(port); | ||||
| @@ -301,7 +294,11 @@ TEST_CASE("Websocket_client_close_params_given", "[close]") | ||||
|         std::string serverReceivedCloseReason(""); | ||||
|         std::mutex mutexWrite; | ||||
|  | ||||
|         REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite)); | ||||
|         REQUIRE(startServer(server, | ||||
|                             serverReceivedCloseCode, | ||||
|                             serverReceivedCloseReason, | ||||
|                             serverReceivedCloseRemote, | ||||
|                             mutexWrite)); | ||||
|  | ||||
|         std::string session = ix::generateSessionId(); | ||||
|         WebSocketClient webSocketClient(port); | ||||
| @@ -359,7 +356,11 @@ TEST_CASE("Websocket_server_close", "[close]") | ||||
|         std::string serverReceivedCloseReason(""); | ||||
|         std::mutex mutexWrite; | ||||
|  | ||||
|         REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite)); | ||||
|         REQUIRE(startServer(server, | ||||
|                             serverReceivedCloseCode, | ||||
|                             serverReceivedCloseReason, | ||||
|                             serverReceivedCloseRemote, | ||||
|                             mutexWrite)); | ||||
|  | ||||
|         std::string session = ix::generateSessionId(); | ||||
|         WebSocketClient webSocketClient(port); | ||||
| @@ -417,7 +418,11 @@ TEST_CASE("Websocket_server_close_immediatly", "[close]") | ||||
|         std::string serverReceivedCloseReason(""); | ||||
|         std::mutex mutexWrite; | ||||
|  | ||||
|         REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite)); | ||||
|         REQUIRE(startServer(server, | ||||
|                             serverReceivedCloseCode, | ||||
|                             serverReceivedCloseReason, | ||||
|                             serverReceivedCloseRemote, | ||||
|                             mutexWrite)); | ||||
|  | ||||
|         std::string session = ix::generateSessionId(); | ||||
|         WebSocketClient webSocketClient(port); | ||||
|   | ||||
| @@ -4,12 +4,11 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
| #include <ixwebsocket/IXWebSocketMessageQueue.h> | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXWebSocketMessageQueue.h> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
| #include <thread> | ||||
|  | ||||
| using namespace ix; | ||||
| @@ -18,13 +17,10 @@ namespace | ||||
| { | ||||
|     bool startServer(ix::WebSocketServer& server) | ||||
|     { | ||||
|         server.setOnConnectionCallback( | ||||
|             [&server](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                       std::shared_ptr<ConnectionState> connectionState) | ||||
|         { | ||||
|         server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                                  std::shared_ptr<ConnectionState> connectionState) { | ||||
|             webSocket->setOnMessageCallback( | ||||
|                 [connectionState, &server](const WebSocketMessagePtr& msg) | ||||
|             { | ||||
|                 [connectionState, &server](const WebSocketMessagePtr& msg) { | ||||
|                     if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                     { | ||||
|                         Logger() << "New connection"; | ||||
| @@ -50,10 +46,8 @@ namespace | ||||
|                             client->send(msg->str); | ||||
|                         } | ||||
|                     } | ||||
|             } | ||||
|             ); | ||||
|         } | ||||
|         ); | ||||
|                 }); | ||||
|         }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -73,8 +67,7 @@ namespace | ||||
|         { | ||||
|             msgQ.bindWebsocket(&ws); | ||||
|  | ||||
|             msgQ.setOnMessageCallback([this](const WebSocketMessagePtr& msg) | ||||
|             { | ||||
|             msgQ.setOnMessageCallback([this](const WebSocketMessagePtr& msg) { | ||||
|                 REQUIRE(mainThreadId == std::this_thread::get_id()); | ||||
|  | ||||
|                 std::stringstream ss; | ||||
| @@ -153,7 +146,10 @@ namespace | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         bool isSucceeded() const { return succeeded; } | ||||
|         bool isSucceeded() const | ||||
|         { | ||||
|             return succeeded; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         WebSocket ws; | ||||
| @@ -163,7 +159,7 @@ namespace | ||||
|         std::thread::id mainThreadId; | ||||
|         bool succeeded = false; | ||||
|     }; | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| TEST_CASE("Websocket_message_queue", "[websocket_message_q]") | ||||
| { | ||||
|   | ||||
| @@ -4,15 +4,13 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <queue> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
|  | ||||
| #include "IXTest.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <queue> | ||||
| #include <sstream> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -35,8 +33,8 @@ namespace | ||||
|     }; | ||||
|  | ||||
|     WebSocketClient::WebSocketClient(int port, bool useHeartBeatMethod) | ||||
|         : _port(port), | ||||
|           _useHeartBeatMethod(useHeartBeatMethod) | ||||
|         : _port(port) | ||||
|         , _useHeartBeatMethod(useHeartBeatMethod) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -56,9 +54,7 @@ namespace | ||||
|         std::string url; | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "ws://127.0.0.1:" | ||||
|                << _port | ||||
|                << "/"; | ||||
|             ss << "ws://127.0.0.1:" << _port << "/"; | ||||
|  | ||||
|             url = ss.str(); | ||||
|         } | ||||
| @@ -79,14 +75,12 @@ namespace | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [](ix::WebSocketMessageType messageType, | ||||
|         _webSocket.setOnMessageCallback([](ix::WebSocketMessageType messageType, | ||||
|                                            const std::string& str, | ||||
|                                            size_t wireSize, | ||||
|                                            const ix::WebSocketErrorInfo& error, | ||||
|                                            const ix::WebSocketOpenInfo& openInfo, | ||||
|                    const ix::WebSocketCloseInfo& closeInfo) | ||||
|             { | ||||
|                                            const ix::WebSocketCloseInfo& closeInfo) { | ||||
|             std::stringstream ss; | ||||
|             if (messageType == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
| @@ -135,16 +129,15 @@ namespace | ||||
|         // A dev/null server | ||||
|         server.setOnConnectionCallback( | ||||
|             [&server, &receivedPingMessages](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                              std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|                                              std::shared_ptr<ConnectionState> connectionState) { | ||||
|                 webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, &server, &receivedPingMessages](ix::WebSocketMessageType messageType, | ||||
|                     [webSocket, connectionState, &server, &receivedPingMessages]( | ||||
|                         ix::WebSocketMessageType messageType, | ||||
|                         const std::string& str, | ||||
|                         size_t wireSize, | ||||
|                         const ix::WebSocketErrorInfo& error, | ||||
|                         const ix::WebSocketOpenInfo& openInfo, | ||||
|                        const ix::WebSocketCloseInfo& closeInfo) | ||||
|                     { | ||||
|                         const ix::WebSocketCloseInfo& closeInfo) { | ||||
|                         if (messageType == ix::WebSocketMessageType::Open) | ||||
|                         { | ||||
|                             Logger() << "New server connection"; | ||||
| @@ -173,10 +166,8 @@ namespace | ||||
|                                 client->sendText("reply"); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|                     }); | ||||
|             }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -188,7 +179,7 @@ namespace | ||||
|         server.start(); | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| TEST_CASE("Websocket_ping_no_data_sent_setPingInterval", "[setPingInterval]") | ||||
| { | ||||
| @@ -282,7 +273,8 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval", "[setPingInterval]") | ||||
|  | ||||
| TEST_CASE("Websocket_ping_data_sent_setPingInterval_half_full", "[setPingInterval]") | ||||
| { | ||||
|     SECTION("Make sure that ping messages are sent, even if other messages are sent continuously during a given time") | ||||
|     SECTION("Make sure that ping messages are sent, even if other messages are sent continuously " | ||||
|             "during a given time") | ||||
|     { | ||||
|         ix::setupWebSocketTrafficTrackerCallback(); | ||||
|  | ||||
| @@ -335,7 +327,8 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval_half_full", "[setPingInterva | ||||
|  | ||||
| TEST_CASE("Websocket_ping_data_sent_setPingInterval_full", "[setPingInterval]") | ||||
| { | ||||
|     SECTION("Make sure that ping messages are sent, even if other messages are sent continuously for longer than ping interval") | ||||
|     SECTION("Make sure that ping messages are sent, even if other messages are sent continuously " | ||||
|             "for longer than ping interval") | ||||
|     { | ||||
|         ix::setupWebSocketTrafficTrackerCallback(); | ||||
|  | ||||
|   | ||||
| @@ -4,15 +4,13 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <queue> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
|  | ||||
| #include "IXTest.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <queue> | ||||
| #include <sstream> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -41,11 +39,11 @@ namespace | ||||
|     }; | ||||
|  | ||||
|     WebSocketClient::WebSocketClient(int port, int pingInterval, int pingTimeout) | ||||
|         : _port(port), | ||||
|          _receivedPongMessages(0), | ||||
|          _closedDueToPingTimeout(false), | ||||
|          _pingInterval(pingInterval), | ||||
|          _pingTimeout(pingTimeout) | ||||
|         : _port(port) | ||||
|         , _receivedPongMessages(0) | ||||
|         , _closedDueToPingTimeout(false) | ||||
|         , _pingInterval(pingInterval) | ||||
|         , _pingTimeout(pingTimeout) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -70,9 +68,7 @@ namespace | ||||
|         std::string url; | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "ws://127.0.0.1:" | ||||
|                << _port | ||||
|                << "/"; | ||||
|             ss << "ws://127.0.0.1:" << _port << "/"; | ||||
|  | ||||
|             url = ss.str(); | ||||
|         } | ||||
| @@ -88,19 +84,16 @@ namespace | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](ix::WebSocketMessageType messageType, | ||||
|         _webSocket.setOnMessageCallback([this](ix::WebSocketMessageType messageType, | ||||
|                                                const std::string& str, | ||||
|                                                size_t wireSize, | ||||
|                                                const ix::WebSocketErrorInfo& error, | ||||
|                                                const ix::WebSocketOpenInfo& openInfo, | ||||
|                    const ix::WebSocketCloseInfo& closeInfo) | ||||
|             { | ||||
|                                                const ix::WebSocketCloseInfo& closeInfo) { | ||||
|             std::stringstream ss; | ||||
|             if (messageType == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
|                 log("client connected"); | ||||
|  | ||||
|             } | ||||
|             else if (messageType == ix::WebSocketMessageType::Close) | ||||
|             { | ||||
| @@ -110,7 +103,6 @@ namespace | ||||
|                 { | ||||
|                     _closedDueToPingTimeout = true; | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|             else if (messageType == ix::WebSocketMessageType::Error) | ||||
|             { | ||||
| @@ -159,21 +151,22 @@ namespace | ||||
|         return _closedDueToPingTimeout; | ||||
|     } | ||||
|  | ||||
|     bool startServer(ix::WebSocketServer& server, std::atomic<int>& receivedPingMessages, bool enablePong) | ||||
|     bool startServer(ix::WebSocketServer& server, | ||||
|                      std::atomic<int>& receivedPingMessages, | ||||
|                      bool enablePong) | ||||
|     { | ||||
|         // A dev/null server | ||||
|         server.setOnConnectionCallback( | ||||
|             [&server, &receivedPingMessages](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                              std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|                                              std::shared_ptr<ConnectionState> connectionState) { | ||||
|                 webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, &server, &receivedPingMessages](ix::WebSocketMessageType messageType, | ||||
|                     [webSocket, connectionState, &server, &receivedPingMessages]( | ||||
|                         ix::WebSocketMessageType messageType, | ||||
|                         const std::string& str, | ||||
|                         size_t wireSize, | ||||
|                         const ix::WebSocketErrorInfo& error, | ||||
|                         const ix::WebSocketOpenInfo& openInfo, | ||||
|                        const ix::WebSocketCloseInfo& closeInfo) | ||||
|                     { | ||||
|                         const ix::WebSocketCloseInfo& closeInfo) { | ||||
|                         if (messageType == ix::WebSocketMessageType::Open) | ||||
|                         { | ||||
|                             Logger() << "New server connection"; | ||||
| @@ -194,10 +187,8 @@ namespace | ||||
|                             log("Server received a ping"); | ||||
|                             receivedPingMessages++; | ||||
|                         } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|                     }); | ||||
|             }); | ||||
|  | ||||
|         if (!enablePong) | ||||
|         { | ||||
| @@ -215,7 +206,7 @@ namespace | ||||
|         server.start(); | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| TEST_CASE("Websocket_ping_timeout_not_checked", "[setPingTimeout]") | ||||
| { | ||||
|   | ||||
| @@ -4,15 +4,13 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "IXTest.h" | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXSocketFactory.h> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
| #include <ixwebsocket/IXSocketFactory.h> | ||||
|  | ||||
| #include "IXTest.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -28,23 +26,18 @@ namespace ix | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     bool startServer(ix::WebSocketServer& server, | ||||
|                      std::string& connectionId) | ||||
|     { | ||||
|         auto factory = []() -> std::shared_ptr<ConnectionState> | ||||
|     bool startServer(ix::WebSocketServer& server, std::string& connectionId) | ||||
|     { | ||||
|         auto factory = []() -> std::shared_ptr<ConnectionState> { | ||||
|             return std::make_shared<ConnectionStateCustom>(); | ||||
|         }; | ||||
|         server.setConnectionStateFactory(factory); | ||||
|  | ||||
|         server.setOnConnectionCallback( | ||||
|             [&server, &connectionId](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                      std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|                 webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, | ||||
|                      &connectionId, &server](const ix::WebSocketMessagePtr& msg) | ||||
|                     { | ||||
|         server.setOnConnectionCallback([&server, &connectionId]( | ||||
|                                            std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                            std::shared_ptr<ConnectionState> connectionState) { | ||||
|             webSocket->setOnMessageCallback([webSocket, connectionState, &connectionId, &server]( | ||||
|                                                 const ix::WebSocketMessagePtr& msg) { | ||||
|                 if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                 { | ||||
|                     Logger() << "New connection"; | ||||
| @@ -73,10 +66,8 @@ namespace ix | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -88,7 +79,7 @@ namespace ix | ||||
|         server.start(); | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|  | ||||
| TEST_CASE("Websocket_server", "[websocket_server]") | ||||
| { | ||||
| @@ -103,10 +94,7 @@ TEST_CASE("Websocket_server", "[websocket_server]") | ||||
|         bool tls = false; | ||||
|         std::shared_ptr<Socket> socket = createSocket(tls, errMsg); | ||||
|         std::string host("127.0.0.1"); | ||||
|         auto isCancellationRequested = []() -> bool | ||||
|         { | ||||
|             return false; | ||||
|         }; | ||||
|         auto isCancellationRequested = []() -> bool { return false; }; | ||||
|         bool success = socket->connect(host, port, errMsg, isCancellationRequested); | ||||
|         REQUIRE(success); | ||||
|  | ||||
| @@ -139,10 +127,7 @@ TEST_CASE("Websocket_server", "[websocket_server]") | ||||
|         bool tls = false; | ||||
|         std::shared_ptr<Socket> socket = createSocket(tls, errMsg); | ||||
|         std::string host("127.0.0.1"); | ||||
|         auto isCancellationRequested = []() -> bool | ||||
|         { | ||||
|             return false; | ||||
|         }; | ||||
|         auto isCancellationRequested = []() -> bool { return false; }; | ||||
|         bool success = socket->connect(host, port, errMsg, isCancellationRequested); | ||||
|         REQUIRE(success); | ||||
|  | ||||
| @@ -178,10 +163,7 @@ TEST_CASE("Websocket_server", "[websocket_server]") | ||||
|         bool tls = false; | ||||
|         std::shared_ptr<Socket> socket = createSocket(tls, errMsg); | ||||
|         std::string host("127.0.0.1"); | ||||
|         auto isCancellationRequested = []() -> bool | ||||
|         { | ||||
|             return false; | ||||
|         }; | ||||
|         auto isCancellationRequested = []() -> bool { return false; }; | ||||
|         bool success = socket->connect(host, port, errMsg, isCancellationRequested); | ||||
|         REQUIRE(success); | ||||
|  | ||||
|   | ||||
| @@ -4,13 +4,12 @@ | ||||
|  *  Copyright (c) 2017 Machine Zone. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <set> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include "IXTest.h" | ||||
|  | ||||
| #include "catch.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <set> | ||||
| #include <sstream> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| @@ -19,7 +18,7 @@ namespace | ||||
|     const std::string WEBSOCKET_DOT_ORG_URL("wss://echo.websocket.org"); | ||||
|     const std::string GOOGLE_URL("wss://google.com"); | ||||
|     const std::string UNKNOWN_URL("wss://asdcasdcaasdcasdcasdcasdcasdcasdcasassdd.com"); | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| namespace | ||||
| { | ||||
| @@ -51,9 +50,7 @@ namespace | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg) { | ||||
|             std::stringstream ss; | ||||
|             if (msg->type == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
| @@ -100,11 +97,12 @@ namespace | ||||
|         // Start the connection | ||||
|         _webSocket.start(); | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| // | ||||
| // We try to connect to different servers, and make sure there are no crashes. | ||||
| // FIXME: We could do more checks (make sure that we were not able to connect to unknown servers, etc...) | ||||
| // FIXME: We could do more checks (make sure that we were not able to connect to unknown servers, | ||||
| // etc...) | ||||
| // | ||||
| TEST_CASE("websocket_connections", "[websocket]") | ||||
| { | ||||
| @@ -121,7 +119,8 @@ TEST_CASE("websocket_connections", "[websocket]") | ||||
|         test.stop(); | ||||
|     } | ||||
|  | ||||
|     SECTION("Try to connect and disconnect with different timing, not enough time to succesfully connect") | ||||
|     SECTION("Try to connect and disconnect with different timing, not enough time to succesfully " | ||||
|             "connect") | ||||
|     { | ||||
|         IXWebSocketTestConnectionDisconnection test; | ||||
|         log(std::string("50 Runs")); | ||||
| @@ -141,7 +140,8 @@ TEST_CASE("websocket_connections", "[websocket]") | ||||
|  | ||||
|     // This test breaks on travis CI - Ubuntu Xenial + gcc + tsan | ||||
|     // We should fix this. | ||||
|     SECTION("Try to connect and disconnect with different timing, from not enough time to successfull connect") | ||||
|     SECTION("Try to connect and disconnect with different timing, from not enough time to " | ||||
|             "successfull connect") | ||||
|     { | ||||
|         IXWebSocketTestConnectionDisconnection test; | ||||
|         log(std::string("20 Runs")); | ||||
|   | ||||
| @@ -6,20 +6,15 @@ | ||||
|  | ||||
| #define CATCH_CONFIG_RUNNER | ||||
| #include "catch.hpp" | ||||
|  | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| #include <ixwebsocket/IXNetSystem.h> | ||||
| #include <ixcore/utils/IXCoreLogger.h> | ||||
| #include <ixwebsocket/IXNetSystem.h> | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| int main(int argc, char* argv[]) | ||||
| { | ||||
|     ix::initNetSystem(); | ||||
|  | ||||
|     ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) | ||||
|     { | ||||
|         spdlog::info(msg); | ||||
|     }; | ||||
|     ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) { spdlog::info(msg); }; | ||||
|     ix::IXCoreLogger::setLogFunction(logFunc); | ||||
|  | ||||
|     int result = Catch::Session().run(argc, argv); | ||||
|   | ||||
| @@ -5,14 +5,14 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXRedisClient.h" | ||||
| #include <ixwebsocket/IXSocketFactory.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <iomanip> | ||||
| #include <vector> | ||||
| #include <cstring> | ||||
| #include <iomanip> | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXSocketFactory.h> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -31,8 +31,7 @@ namespace ix | ||||
|         return _socket->connect(hostname, port, errMsg, nullptr); | ||||
|     } | ||||
|  | ||||
|     bool RedisClient::auth(const std::string& password, | ||||
|                            std::string& response) | ||||
|     bool RedisClient::auth(const std::string& password, std::string& response) | ||||
|     { | ||||
|         response.clear(); | ||||
|  | ||||
| @@ -246,4 +245,4 @@ namespace ix | ||||
|     { | ||||
|         _stop = true; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -6,9 +6,9 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <atomic> | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <atomic> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -20,7 +20,10 @@ namespace ix | ||||
|         using OnRedisSubscribeResponseCallback = std::function<void(const std::string&)>; | ||||
|         using OnRedisSubscribeCallback = std::function<void(const std::string&)>; | ||||
|  | ||||
|         RedisClient() : _stop(false) {} | ||||
|         RedisClient() | ||||
|             : _stop(false) | ||||
|         { | ||||
|         } | ||||
|         ~RedisClient() = default; | ||||
|  | ||||
|         bool connect(const std::string& hostname, int port); | ||||
|   | ||||
| @@ -8,17 +8,16 @@ | ||||
|  | ||||
| #include <chrono> | ||||
| #include <iostream> | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| #include <ixwebsocket/IXWebSocketHttpHeaders.h> | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
|     SentryClient::SentryClient(const std::string& dsn) : | ||||
|         _dsn(dsn), | ||||
|         _validDsn(false), | ||||
|         _luaFrameRegex("\t([^/]+):([0-9]+): in function '([^/]+)'") | ||||
|     SentryClient::SentryClient(const std::string& dsn) | ||||
|         : _dsn(dsn) | ||||
|         , _validDsn(false) | ||||
|         , _luaFrameRegex("\t([^/]+):([0-9]+): in function '([^/]+)'") | ||||
|     { | ||||
|         const std::regex dsnRegex("(http[s]?)://([^:]+):([^@]+)@([^/]+)/([0-9]+)"); | ||||
|         std::smatch group; | ||||
| @@ -168,8 +167,7 @@ namespace ix | ||||
|         return _jsonWriter.write(payload); | ||||
|     } | ||||
|  | ||||
|     std::pair<HttpResponsePtr, std::string> SentryClient::send(const Json::Value& msg, | ||||
|                                                                bool verbose) | ||||
|     std::pair<HttpResponsePtr, std::string> SentryClient::send(const Json::Value& msg, bool verbose) | ||||
|     { | ||||
|         auto args = _httpClient.createRequest(); | ||||
|         args->extraHeaders["X-Sentry-Auth"] = SentryClient::computeAuthHeader(); | ||||
| @@ -177,10 +175,7 @@ namespace ix | ||||
|         args->transferTimeout = 5 * 60; | ||||
|         args->followRedirects = true; | ||||
|         args->verbose = verbose; | ||||
|         args->logger = [](const std::string& msg) | ||||
|         { | ||||
|             spdlog::info("request logger: {}", msg); | ||||
|         }; | ||||
|         args->logger = [](const std::string& msg) { spdlog::info("request logger: {}", msg); }; | ||||
|  | ||||
|         std::string body = computePayload(msg); | ||||
|         HttpResponsePtr response = _httpClient.post(_url, body, args); | ||||
|   | ||||
| @@ -4,24 +4,20 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "IXSnakeProtocol.h" | ||||
| #include "IXAppConfig.h" | ||||
|  | ||||
| #include "IXSnakeProtocol.h" | ||||
| #include <iostream> | ||||
| #include <ixcrypto/IXUuid.h> | ||||
|  | ||||
| namespace snake | ||||
| { | ||||
|     bool isAppKeyValid( | ||||
|         const AppConfig& appConfig, | ||||
|         std::string appkey) | ||||
|     bool isAppKeyValid(const AppConfig& appConfig, std::string appkey) | ||||
|     { | ||||
|         return appConfig.apps.count(appkey) != 0; | ||||
|     } | ||||
|  | ||||
|     std::string getRoleSecret( | ||||
|         const AppConfig& appConfig, | ||||
|         std::string appkey, | ||||
|         std::string role) | ||||
|     std::string getRoleSecret(const AppConfig& appConfig, std::string appkey, std::string role) | ||||
|     { | ||||
|         if (!isAppKeyValid(appConfig, appkey)) | ||||
|         { | ||||
| @@ -49,4 +45,4 @@ namespace snake | ||||
|         std::cout << "redis password: " << appConfig.redisPassword << std::endl; | ||||
|         std::cout << "redis port: " << appConfig.redisPort << std::endl; | ||||
|     } | ||||
| } | ||||
| } // namespace snake | ||||
|   | ||||
| @@ -16,16 +16,37 @@ namespace snake | ||||
|     class SnakeConnectionState : public ix::ConnectionState | ||||
|     { | ||||
|     public: | ||||
|         std::string getNonce() { return _nonce; } | ||||
|         void setNonce(const std::string& nonce) { _nonce = nonce; } | ||||
|         std::string getNonce() | ||||
|         { | ||||
|             return _nonce; | ||||
|         } | ||||
|         void setNonce(const std::string& nonce) | ||||
|         { | ||||
|             _nonce = nonce; | ||||
|         } | ||||
|  | ||||
|         std::string appkey() { return _appkey; } | ||||
|         void setAppkey(const std::string& appkey) { _appkey = appkey; } | ||||
|         std::string appkey() | ||||
|         { | ||||
|             return _appkey; | ||||
|         } | ||||
|         void setAppkey(const std::string& appkey) | ||||
|         { | ||||
|             _appkey = appkey; | ||||
|         } | ||||
|  | ||||
|         std::string role() { return _role; } | ||||
|         void setRole(const std::string& role) { _role = role; } | ||||
|         std::string role() | ||||
|         { | ||||
|             return _role; | ||||
|         } | ||||
|         void setRole(const std::string& role) | ||||
|         { | ||||
|             _role = role; | ||||
|         } | ||||
|  | ||||
|         ix::RedisClient& redisClient() { return _redisClient; } | ||||
|         ix::RedisClient& redisClient() | ||||
|         { | ||||
|             return _redisClient; | ||||
|         } | ||||
|  | ||||
|         std::future<void> fut; | ||||
|  | ||||
|   | ||||
| @@ -6,20 +6,17 @@ | ||||
|  | ||||
| #include "IXSnakeProtocol.h" | ||||
|  | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixcrypto/IXHMac.h> | ||||
|  | ||||
| #include "IXSnakeConnectionState.h" | ||||
| #include "IXAppConfig.h" | ||||
|  | ||||
| #include "IXSnakeConnectionState.h" | ||||
| #include "nlohmann/json.hpp" | ||||
| #include <sstream> | ||||
| #include <iostream> | ||||
| #include <ixcrypto/IXHMac.h> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace snake | ||||
| { | ||||
|     void handleError( | ||||
|         const std::string& action, | ||||
|     void handleError(const std::string& action, | ||||
|                      std::shared_ptr<ix::WebSocket> ws, | ||||
|                      nlohmann::json pdu, | ||||
|                      const std::string& errMsg) | ||||
| @@ -28,17 +25,11 @@ namespace snake | ||||
|         actionError += "/error"; | ||||
|  | ||||
|         nlohmann::json response = { | ||||
|             {"action", actionError}, | ||||
|             {"id", pdu.value("id", 1)}, | ||||
|             {"body", { | ||||
|                 {"reason", errMsg} | ||||
|             }} | ||||
|         }; | ||||
|             {"action", actionError}, {"id", pdu.value("id", 1)}, {"body", {{"reason", errMsg}}}}; | ||||
|         ws->sendText(response.dump()); | ||||
|     } | ||||
|  | ||||
|     void handleHandshake( | ||||
|         std::shared_ptr<SnakeConnectionState> state, | ||||
|     void handleHandshake(std::shared_ptr<SnakeConnectionState> state, | ||||
|                          std::shared_ptr<ix::WebSocket> ws, | ||||
|                          const nlohmann::json& pdu) | ||||
|     { | ||||
| @@ -50,13 +41,10 @@ namespace snake | ||||
|         nlohmann::json response = { | ||||
|             {"action", "auth/handshake/ok"}, | ||||
|             {"id", pdu.value("id", 1)}, | ||||
|             {"body", { | ||||
|                 {"data", { | ||||
|                     {"nonce", state->getNonce()}, | ||||
|                     {"connection_id", state->getId()} | ||||
|                 }}, | ||||
|             }} | ||||
|         }; | ||||
|             {"body", | ||||
|              { | ||||
|                  {"data", {{"nonce", state->getNonce()}, {"connection_id", state->getId()}}}, | ||||
|              }}}; | ||||
|  | ||||
|         auto serializedResponse = response.dump(); | ||||
|         std::cout << "response = " << serializedResponse << std::endl; | ||||
| @@ -64,8 +52,7 @@ namespace snake | ||||
|         ws->sendText(serializedResponse); | ||||
|     } | ||||
|  | ||||
|     void handleAuth( | ||||
|         std::shared_ptr<SnakeConnectionState> state, | ||||
|     void handleAuth(std::shared_ptr<SnakeConnectionState> state, | ||||
|                     std::shared_ptr<ix::WebSocket> ws, | ||||
|                     const AppConfig& appConfig, | ||||
|                     const nlohmann::json& pdu) | ||||
| @@ -78,11 +65,7 @@ namespace snake | ||||
|             nlohmann::json response = { | ||||
|                 {"action", "auth/authenticate/error"}, | ||||
|                 {"id", pdu.value("id", 1)}, | ||||
|                 {"body", { | ||||
|                     {"error", "authentication_failed"}, | ||||
|                     {"reason", "invalid secret"} | ||||
|                 }} | ||||
|             }; | ||||
|                 {"body", {{"error", "authentication_failed"}, {"reason", "invalid secret"}}}}; | ||||
|             ws->sendText(response.dump()); | ||||
|             return; | ||||
|         } | ||||
| @@ -102,26 +85,18 @@ namespace snake | ||||
|             nlohmann::json response = { | ||||
|                 {"action", "auth/authenticate/error"}, | ||||
|                 {"id", pdu.value("id", 1)}, | ||||
|                 {"body", { | ||||
|                     {"error", "authentication_failed"}, | ||||
|                     {"reason", "invalid hash"} | ||||
|                 }} | ||||
|             }; | ||||
|                 {"body", {{"error", "authentication_failed"}, {"reason", "invalid hash"}}}}; | ||||
|             ws->sendText(response.dump()); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         nlohmann::json response = { | ||||
|             {"action", "auth/authenticate/ok"}, | ||||
|             {"id", pdu.value("id", 1)}, | ||||
|             {"body", {}} | ||||
|         }; | ||||
|             {"action", "auth/authenticate/ok"}, {"id", pdu.value("id", 1)}, {"body", {}}}; | ||||
|  | ||||
|         ws->sendText(response.dump()); | ||||
|     } | ||||
|  | ||||
|     void handlePublish( | ||||
|         std::shared_ptr<SnakeConnectionState> state, | ||||
|     void handlePublish(std::shared_ptr<SnakeConnectionState> state, | ||||
|                        std::shared_ptr<ix::WebSocket> ws, | ||||
|                        const nlohmann::json& pdu) | ||||
|     { | ||||
| @@ -150,9 +125,7 @@ namespace snake | ||||
|         for (auto&& channel : channels) | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << state->appkey() | ||||
|                << "::" | ||||
|                << channel; | ||||
|             ss << state->appkey() << "::" << channel; | ||||
|  | ||||
|             std::string errMsg; | ||||
|             if (!state->redisClient().publish(ss.str(), pdu.dump(), errMsg)) | ||||
| @@ -165,10 +138,7 @@ namespace snake | ||||
|         } | ||||
|  | ||||
|         nlohmann::json response = { | ||||
|             {"action", "rtm/publish/ok"}, | ||||
|             {"id", pdu.value("id", 1)}, | ||||
|             {"body", {}} | ||||
|         }; | ||||
|             {"action", "rtm/publish/ok"}, {"id", pdu.value("id", 1)}, {"body", {}}}; | ||||
|  | ||||
|         ws->sendText(response.dump()); | ||||
|     } | ||||
| @@ -176,8 +146,7 @@ namespace snake | ||||
|     // | ||||
|     // FIXME: this is not cancellable. We should be able to cancel the redis subscription | ||||
|     // | ||||
|     void handleRedisSubscription( | ||||
|         std::shared_ptr<SnakeConnectionState> state, | ||||
|     void handleRedisSubscription(std::shared_ptr<SnakeConnectionState> state, | ||||
|                                  std::shared_ptr<ix::WebSocket> ws, | ||||
|                                  const AppConfig& appConfig, | ||||
|                                  const nlohmann::json& pdu) | ||||
| @@ -186,9 +155,7 @@ namespace snake | ||||
|         std::string subscriptionId = channel; | ||||
|  | ||||
|         std::stringstream ss; | ||||
|         ss << state->appkey() | ||||
|            << "::" | ||||
|            << channel; | ||||
|         ss << state->appkey() << "::" << channel; | ||||
|  | ||||
|         std::string appChannel(ss.str()); | ||||
|  | ||||
| @@ -224,8 +191,7 @@ namespace snake | ||||
|         } | ||||
|  | ||||
|         int id = 0; | ||||
|         auto callback = [ws, &id, &subscriptionId](const std::string& messageStr) | ||||
|         { | ||||
|         auto callback = [ws, &id, &subscriptionId](const std::string& messageStr) { | ||||
|             auto msg = nlohmann::json::parse(messageStr); | ||||
|  | ||||
|             msg = msg["body"]["message"]; | ||||
| @@ -233,27 +199,18 @@ namespace snake | ||||
|             nlohmann::json response = { | ||||
|                 {"action", "rtm/subscription/data"}, | ||||
|                 {"id", id++}, | ||||
|                 {"body", { | ||||
|                     {"subscription_id", subscriptionId}, | ||||
|                     {"messages", {msg}} | ||||
|                 }} | ||||
|             }; | ||||
|                 {"body", {{"subscription_id", subscriptionId}, {"messages", {msg}}}}}; | ||||
|  | ||||
|             ws->sendText(response.dump()); | ||||
|         }; | ||||
|  | ||||
|         auto responseCallback = [ws, pdu, &subscriptionId](const std::string& redisResponse) | ||||
|         { | ||||
|         auto responseCallback = [ws, pdu, &subscriptionId](const std::string& redisResponse) { | ||||
|             std::cout << "Redis subscribe response: " << redisResponse << std::endl; | ||||
|  | ||||
|             // Success | ||||
|             nlohmann::json response = { | ||||
|                 {"action", "rtm/subscribe/ok"}, | ||||
|             nlohmann::json response = {{"action", "rtm/subscribe/ok"}, | ||||
|                                        {"id", pdu.value("id", 1)}, | ||||
|                 {"body", { | ||||
|                     {"subscription_id", subscriptionId} | ||||
|                 }} | ||||
|             }; | ||||
|                                        {"body", {{"subscription_id", subscriptionId}}}}; | ||||
|             ws->sendText(response.dump()); | ||||
|         }; | ||||
|  | ||||
| @@ -267,22 +224,16 @@ namespace snake | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void handleSubscribe( | ||||
|         std::shared_ptr<SnakeConnectionState> state, | ||||
|     void handleSubscribe(std::shared_ptr<SnakeConnectionState> state, | ||||
|                          std::shared_ptr<ix::WebSocket> ws, | ||||
|                          const AppConfig& appConfig, | ||||
|                          const nlohmann::json& pdu) | ||||
|     { | ||||
|         state->fut = std::async(std::launch::async, | ||||
|                                 handleRedisSubscription, | ||||
|                                 state, | ||||
|                                 ws, | ||||
|                                 appConfig, | ||||
|                                 pdu); | ||||
|         state->fut = | ||||
|             std::async(std::launch::async, handleRedisSubscription, state, ws, appConfig, pdu); | ||||
|     } | ||||
|  | ||||
|     void handleUnSubscribe( | ||||
|         std::shared_ptr<SnakeConnectionState> state, | ||||
|     void handleUnSubscribe(std::shared_ptr<SnakeConnectionState> state, | ||||
|                            std::shared_ptr<ix::WebSocket> ws, | ||||
|                            const nlohmann::json& pdu) | ||||
|     { | ||||
| @@ -292,18 +243,13 @@ namespace snake | ||||
|  | ||||
|         state->redisClient().stop(); | ||||
|  | ||||
|         nlohmann::json response = { | ||||
|             {"action", "rtm/unsubscribe/ok"}, | ||||
|         nlohmann::json response = {{"action", "rtm/unsubscribe/ok"}, | ||||
|                                    {"id", pdu.value("id", 1)}, | ||||
|             {"body", { | ||||
|                 {"subscription_id", subscriptionId} | ||||
|             }} | ||||
|         }; | ||||
|                                    {"body", {{"subscription_id", subscriptionId}}}}; | ||||
|         ws->sendText(response.dump()); | ||||
|     } | ||||
|  | ||||
|     void processCobraMessage( | ||||
|         std::shared_ptr<SnakeConnectionState> state, | ||||
|     void processCobraMessage(std::shared_ptr<SnakeConnectionState> state, | ||||
|                              std::shared_ptr<ix::WebSocket> ws, | ||||
|                              const AppConfig& appConfig, | ||||
|                              const std::string& str) | ||||
| @@ -339,4 +285,4 @@ namespace snake | ||||
|             std::cerr << "Unhandled action: " << action << std::endl; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } // namespace snake | ||||
|   | ||||
| @@ -5,18 +5,18 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXSnakeServer.h" | ||||
| #include "IXSnakeProtocol.h" | ||||
| #include "IXSnakeConnectionState.h" | ||||
| #include "IXAppConfig.h" | ||||
|  | ||||
| #include "IXAppConfig.h" | ||||
| #include "IXSnakeConnectionState.h" | ||||
| #include "IXSnakeProtocol.h" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace snake | ||||
| { | ||||
|     SnakeServer::SnakeServer(const AppConfig& appConfig) : | ||||
|         _appConfig(appConfig), | ||||
|         _server(appConfig.port, appConfig.hostname) | ||||
|     SnakeServer::SnakeServer(const AppConfig& appConfig) | ||||
|         : _appConfig(appConfig) | ||||
|         , _server(appConfig.port, appConfig.hostname) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -45,21 +45,18 @@ namespace snake | ||||
|     { | ||||
|         std::cout << "Listening on " << _appConfig.hostname << ":" << _appConfig.port << std::endl; | ||||
|  | ||||
|         auto factory = []() -> std::shared_ptr<ix::ConnectionState> | ||||
|         { | ||||
|         auto factory = []() -> std::shared_ptr<ix::ConnectionState> { | ||||
|             return std::make_shared<SnakeConnectionState>(); | ||||
|         }; | ||||
|         _server.setConnectionStateFactory(factory); | ||||
|  | ||||
|         _server.setOnConnectionCallback( | ||||
|             [this](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                    std::shared_ptr<ix::ConnectionState> connectionState) | ||||
|             { | ||||
|                    std::shared_ptr<ix::ConnectionState> connectionState) { | ||||
|                 auto state = std::dynamic_pointer_cast<SnakeConnectionState>(connectionState); | ||||
|  | ||||
|                 webSocket->setOnMessageCallback( | ||||
|                     [this, webSocket, state](const ix::WebSocketMessagePtr& msg) | ||||
|                     { | ||||
|                     [this, webSocket, state](const ix::WebSocketMessagePtr& msg) { | ||||
|                         if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                         { | ||||
|                             std::cerr << "New connection" << std::endl; | ||||
| @@ -84,8 +81,8 @@ namespace snake | ||||
|                         else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|                         { | ||||
|                             std::cerr << "Closed connection" | ||||
|                                       << " code " << msg->closeInfo.code | ||||
|                                       << " reason " << msg->closeInfo.reason << std::endl; | ||||
|                                       << " code " << msg->closeInfo.code << " reason " | ||||
|                                       << msg->closeInfo.reason << std::endl; | ||||
|                         } | ||||
|                         else if (msg->type == ix::WebSocketMessageType::Error) | ||||
|                         { | ||||
| @@ -105,10 +102,8 @@ namespace snake | ||||
|                             std::cerr << "Received " << msg->wireSize << " bytes" << std::endl; | ||||
|                             processCobraMessage(state, webSocket, _appConfig, msg->str); | ||||
|                         } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|                     }); | ||||
|             }); | ||||
|  | ||||
|         auto res = _server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -133,4 +128,4 @@ namespace snake | ||||
|     { | ||||
|         _server.stop(); | ||||
|     } | ||||
| } | ||||
| } // namespace snake | ||||
|   | ||||
							
								
								
									
										108
									
								
								ws/ws.cpp
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								ws/ws.cpp
									
									
									
									
									
								
							| @@ -9,27 +9,22 @@ | ||||
| // | ||||
| #include "ws.h" | ||||
|  | ||||
| #include <string> | ||||
| #include <sstream> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
|  | ||||
| #include <cli11/CLI11.hpp> | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXNetSystem.h> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <ixcore/utils/IXCoreLogger.h> | ||||
| #include <ixwebsocket/IXNetSystem.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
| #include <string> | ||||
|  | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     ix::initNetSystem(); | ||||
|  | ||||
|     ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) | ||||
|     { | ||||
|         spdlog::info(msg); | ||||
|     }; | ||||
|     ix::IXCoreLogger::LogFunc logFunc = [](const char* msg) { spdlog::info(msg); }; | ||||
|     ix::IXCoreLogger::setLogFunction(logFunc); | ||||
|  | ||||
|     // Display command. | ||||
| @@ -94,12 +89,15 @@ int main(int argc, char** argv) | ||||
|     CLI::App* sendApp = app.add_subcommand("send", "Send a file"); | ||||
|     sendApp->add_option("url", url, "Connection url")->required(); | ||||
|     sendApp->add_option("path", path, "Path to the file to send") | ||||
|         ->required()->check(CLI::ExistingPath); | ||||
|         ->required() | ||||
|         ->check(CLI::ExistingPath); | ||||
|     sendApp->add_option("--pidfile", pidfile, "Pid file"); | ||||
|  | ||||
|     CLI::App* receiveApp = app.add_subcommand("receive", "Receive a file"); | ||||
|     receiveApp->add_option("url", url, "Connection url")->required(); | ||||
|     receiveApp->add_option("--delay", delayMs, "Delay (ms) to wait after receiving a fragment" | ||||
|     receiveApp->add_option("--delay", | ||||
|                            delayMs, | ||||
|                            "Delay (ms) to wait after receiving a fragment" | ||||
|                            " to artificially slow down the receiver"); | ||||
|     receiveApp->add_option("--pidfile", pidfile, "Pid file"); | ||||
|  | ||||
| @@ -114,7 +112,9 @@ int main(int argc, char** argv) | ||||
|     connectApp->add_flag("-d", disableAutomaticReconnection, "Disable Automatic Reconnection"); | ||||
|     connectApp->add_flag("-x", disablePerMessageDeflate, "Disable per message deflate"); | ||||
|     connectApp->add_flag("-b", binaryMode, "Send in binary mode"); | ||||
|     connectApp->add_option("--max_wait", maxWaitBetweenReconnectionRetries, "Max Wait Time between reconnection retries"); | ||||
|     connectApp->add_option("--max_wait", | ||||
|                            maxWaitBetweenReconnectionRetries, | ||||
|                            "Max Wait Time between reconnection retries"); | ||||
|  | ||||
|     CLI::App* chatApp = app.add_subcommand("chat", "Group chat"); | ||||
|     chatApp->add_option("url", url, "Connection url")->required(); | ||||
| @@ -181,9 +181,11 @@ int main(int argc, char** argv) | ||||
|     cobraPublish->add_option("channel", channel, "Channel")->required(); | ||||
|     cobraPublish->add_option("--pidfile", pidfile, "Pid file"); | ||||
|     cobraPublish->add_option("path", path, "Path to the file to send") | ||||
|         ->required()->check(CLI::ExistingPath); | ||||
|         ->required() | ||||
|         ->check(CLI::ExistingPath); | ||||
|  | ||||
|     CLI::App* cobraMetricsPublish = app.add_subcommand("cobra_metrics_publish", "Cobra metrics publisher"); | ||||
|     CLI::App* cobraMetricsPublish = | ||||
|         app.add_subcommand("cobra_metrics_publish", "Cobra metrics publisher"); | ||||
|     cobraMetricsPublish->add_option("--appkey", appkey, "Appkey"); | ||||
|     cobraMetricsPublish->add_option("--endpoint", endpoint, "Endpoint"); | ||||
|     cobraMetricsPublish->add_option("--rolename", rolename, "Role name"); | ||||
| @@ -191,7 +193,8 @@ int main(int argc, char** argv) | ||||
|     cobraMetricsPublish->add_option("channel", channel, "Channel")->required(); | ||||
|     cobraMetricsPublish->add_option("--pidfile", pidfile, "Pid file"); | ||||
|     cobraMetricsPublish->add_option("path", path, "Path to the file to send") | ||||
|         ->required()->check(CLI::ExistingPath); | ||||
|         ->required() | ||||
|         ->check(CLI::ExistingPath); | ||||
|     cobraMetricsPublish->add_flag("--stress", stress, "Stress mode"); | ||||
|  | ||||
|     CLI::App* cobra2statsd = app.add_subcommand("cobra_to_statsd", "Cobra to statsd"); | ||||
| @@ -269,8 +272,11 @@ int main(int argc, char** argv) | ||||
|     } | ||||
|     else if (app.got_subcommand("connect")) | ||||
|     { | ||||
|         ret = ix::ws_connect_main(url, headers, disableAutomaticReconnection, | ||||
|                                   disablePerMessageDeflate, binaryMode, | ||||
|         ret = ix::ws_connect_main(url, | ||||
|                                   headers, | ||||
|                                   disableAutomaticReconnection, | ||||
|                                   disablePerMessageDeflate, | ||||
|                                   binaryMode, | ||||
|                                   maxWaitBetweenReconnectionRetries); | ||||
|     } | ||||
|     else if (app.got_subcommand("chat")) | ||||
| @@ -291,15 +297,22 @@ int main(int argc, char** argv) | ||||
|     } | ||||
|     else if (app.got_subcommand("curl")) | ||||
|     { | ||||
|         ret = ix::ws_http_client_main(url, headers, data, headersOnly, | ||||
|                                       connectTimeOut, transferTimeout, | ||||
|                                       followRedirects, maxRedirects, verbose, | ||||
|                                       save, output, compress); | ||||
|         ret = ix::ws_http_client_main(url, | ||||
|                                       headers, | ||||
|                                       data, | ||||
|                                       headersOnly, | ||||
|                                       connectTimeOut, | ||||
|                                       transferTimeout, | ||||
|                                       followRedirects, | ||||
|                                       maxRedirects, | ||||
|                                       verbose, | ||||
|                                       save, | ||||
|                                       output, | ||||
|                                       compress); | ||||
|     } | ||||
|     else if (app.got_subcommand("redis_publish")) | ||||
|     { | ||||
|         ret = ix::ws_redis_publish_main(hostname, redisPort, password, | ||||
|                                         channel, message, count); | ||||
|         ret = ix::ws_redis_publish_main(hostname, redisPort, password, channel, message, count); | ||||
|     } | ||||
|     else if (app.got_subcommand("redis_subscribe")) | ||||
|     { | ||||
| @@ -307,42 +320,41 @@ int main(int argc, char** argv) | ||||
|     } | ||||
|     else if (app.got_subcommand("cobra_subscribe")) | ||||
|     { | ||||
|         ret = ix::ws_cobra_subscribe_main(appkey, endpoint, | ||||
|                                           rolename, rolesecret, | ||||
|                                           channel, filter, quiet); | ||||
|         ret = ix::ws_cobra_subscribe_main( | ||||
|             appkey, endpoint, rolename, rolesecret, channel, filter, quiet); | ||||
|     } | ||||
|     else if (app.got_subcommand("cobra_publish")) | ||||
|     { | ||||
|         ret = ix::ws_cobra_publish_main(appkey, endpoint, | ||||
|                                         rolename, rolesecret, | ||||
|                                         channel, path); | ||||
|         ret = ix::ws_cobra_publish_main(appkey, endpoint, rolename, rolesecret, channel, path); | ||||
|     } | ||||
|     else if (app.got_subcommand("cobra_metrics_publish")) | ||||
|     { | ||||
|         ret = ix::ws_cobra_metrics_publish_main(appkey, endpoint, | ||||
|                                                 rolename, rolesecret, | ||||
|                                                 channel, path, stress); | ||||
|         ret = ix::ws_cobra_metrics_publish_main( | ||||
|             appkey, endpoint, rolename, rolesecret, channel, path, stress); | ||||
|     } | ||||
|     else if (app.got_subcommand("cobra_to_statsd")) | ||||
|     { | ||||
|         ret = ix::ws_cobra_to_statsd_main(appkey, endpoint, | ||||
|                                           rolename, rolesecret, | ||||
|                                           channel, filter, hostname, statsdPort, | ||||
|                                           prefix, fields, verbose); | ||||
|         ret = ix::ws_cobra_to_statsd_main(appkey, | ||||
|                                           endpoint, | ||||
|                                           rolename, | ||||
|                                           rolesecret, | ||||
|                                           channel, | ||||
|                                           filter, | ||||
|                                           hostname, | ||||
|                                           statsdPort, | ||||
|                                           prefix, | ||||
|                                           fields, | ||||
|                                           verbose); | ||||
|     } | ||||
|     else if (app.got_subcommand("cobra_to_sentry")) | ||||
|     { | ||||
|         ret = ix::ws_cobra_to_sentry_main(appkey, endpoint, | ||||
|                                           rolename, rolesecret, | ||||
|                                           channel, filter, dsn, | ||||
|                                           verbose, strict, jobs); | ||||
|         ret = ix::ws_cobra_to_sentry_main( | ||||
|             appkey, endpoint, rolename, rolesecret, channel, filter, dsn, verbose, strict, jobs); | ||||
|     } | ||||
|     else if (app.got_subcommand("snake")) | ||||
|     { | ||||
|         ret = ix::ws_snake_main(port, hostname, | ||||
|                                 redisHosts, redisPort, | ||||
|                                 redisPassword, verbose, | ||||
|                                 appsConfigPath); | ||||
|         ret = ix::ws_snake_main( | ||||
|             port, hostname, redisHosts, redisPort, redisPassword, verbose, appsConfigPath); | ||||
|     } | ||||
|     else if (app.got_subcommand("httpd")) | ||||
|     { | ||||
|   | ||||
| @@ -21,7 +21,8 @@ | ||||
| // | ||||
| // | ||||
| // 2 Run the test server (using docker) | ||||
| // docker run -it --rm -v "${PWD}/config:/config" -v "${PWD}/reports:/reports" -p 9001:9001 --name fuzzingserver crossbario/autobahn-testsuite | ||||
| // docker run -it --rm -v "${PWD}/config:/config" -v "${PWD}/reports:/reports" -p 9001:9001 --name | ||||
| // fuzzingserver crossbario/autobahn-testsuite | ||||
| // | ||||
| // 3. Run this command | ||||
| //    ws autobahn -q --url ws://localhost:9001 | ||||
| @@ -29,15 +30,14 @@ | ||||
| // 4. A HTML report will be generated, you can inspect it to see if you are compliant or not | ||||
| // | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <atomic> | ||||
| #include <mutex> | ||||
| #include <condition_variable> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
|  | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <mutex> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
|  | ||||
|  | ||||
| namespace | ||||
| @@ -53,7 +53,7 @@ namespace | ||||
|             return str.substr(0, n) + "..."; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -75,9 +75,9 @@ namespace ix | ||||
|         std::condition_variable _condition; | ||||
|     }; | ||||
|  | ||||
|     AutobahnTestCase::AutobahnTestCase(const std::string& url, bool quiet) : | ||||
|         _url(url), | ||||
|         _quiet(quiet) | ||||
|     AutobahnTestCase::AutobahnTestCase(const std::string& url, bool quiet) | ||||
|         : _url(url) | ||||
|         , _quiet(quiet) | ||||
|     { | ||||
|         _webSocket.disableAutomaticReconnection(); | ||||
|  | ||||
| @@ -102,9 +102,7 @@ namespace ix | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + _url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) { | ||||
|             std::stringstream ss; | ||||
|             if (msg->type == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
| @@ -128,9 +126,7 @@ namespace ix | ||||
|             { | ||||
|                 ss << "Received " << msg->wireSize << " bytes" << std::endl; | ||||
|  | ||||
|                     ss << "autobahn: received message: " | ||||
|                        << truncate(msg->str, 40) | ||||
|                        << std::endl; | ||||
|                 ss << "autobahn: received message: " << truncate(msg->str, 40) << std::endl; | ||||
|  | ||||
|                 _webSocket.send(msg->str, msg->binary); | ||||
|             } | ||||
| @@ -184,9 +180,7 @@ namespace ix | ||||
|         std::atomic<bool> success(true); | ||||
|         std::condition_variable condition; | ||||
|  | ||||
|         webSocket.setOnMessageCallback( | ||||
|             [&condition, &success](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         webSocket.setOnMessageCallback([&condition, &success](const ix::WebSocketMessagePtr& msg) { | ||||
|             if (msg->type == ix::WebSocketMessageType::Close) | ||||
|             { | ||||
|                 std::cerr << "Report generated" << std::endl; | ||||
| @@ -203,8 +197,7 @@ namespace ix | ||||
|  | ||||
|                 success = false; | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|  | ||||
|         webSocket.start(); | ||||
|         std::mutex mutex; | ||||
| @@ -231,9 +224,7 @@ namespace ix | ||||
|         int count = -1; | ||||
|         std::condition_variable condition; | ||||
|  | ||||
|         webSocket.setOnMessageCallback( | ||||
|             [&condition, &count](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         webSocket.setOnMessageCallback([&condition, &count](const ix::WebSocketMessagePtr& msg) { | ||||
|             if (msg->type == ix::WebSocketMessageType::Close) | ||||
|             { | ||||
|                 condition.notify_one(); | ||||
| @@ -256,8 +247,7 @@ namespace ix | ||||
|                 ss << msg->str; | ||||
|                 ss >> count; | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|  | ||||
|         webSocket.start(); | ||||
|         std::mutex mutex; | ||||
| @@ -296,10 +286,7 @@ namespace ix | ||||
|             int caseNumber = i; | ||||
|  | ||||
|             std::stringstream ss; | ||||
|             ss << url | ||||
|                << "/runCase?case=" | ||||
|                << caseNumber | ||||
|                << "&agent=ixwebsocket"; | ||||
|             ss << url << "/runCase?case=" << caseNumber << "&agent=ixwebsocket"; | ||||
|  | ||||
|             std::string url(ss.str()); | ||||
|  | ||||
| @@ -309,4 +296,4 @@ namespace ix | ||||
|  | ||||
|         return generateReport(url) ? 0 : 1; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,8 +5,8 @@ | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -16,13 +16,10 @@ namespace ix | ||||
|  | ||||
|         ix::WebSocketServer server(port, hostname); | ||||
|  | ||||
|         server.setOnConnectionCallback( | ||||
|             [&server](std::shared_ptr<WebSocket> webSocket, | ||||
|                       std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|                 webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, &server](const WebSocketMessagePtr& msg) | ||||
|                     { | ||||
|         server.setOnConnectionCallback([&server](std::shared_ptr<WebSocket> webSocket, | ||||
|                                                  std::shared_ptr<ConnectionState> connectionState) { | ||||
|             webSocket->setOnMessageCallback([webSocket, connectionState, &server]( | ||||
|                                                 const WebSocketMessagePtr& msg) { | ||||
|                 if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                 { | ||||
|                     std::cerr << "New connection" << std::endl; | ||||
| @@ -37,8 +34,8 @@ namespace ix | ||||
|                 else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|                 { | ||||
|                     std::cerr << "Closed connection" | ||||
|                                       << " code " << msg->closeInfo.code | ||||
|                                       << " reason " << msg->closeInfo.reason << std::endl; | ||||
|                               << " code " << msg->closeInfo.code << " reason " | ||||
|                               << msg->closeInfo.reason << std::endl; | ||||
|                 } | ||||
|                 else if (msg->type == ix::WebSocketMessageType::Error) | ||||
|                 { | ||||
| @@ -61,19 +58,16 @@ namespace ix | ||||
|                     { | ||||
|                         if (client != webSocket) | ||||
|                         { | ||||
|                                     client->send(msg->str, | ||||
|                                                  msg->binary, | ||||
|                                                  [](int current, int total) -> bool | ||||
|                                     { | ||||
|                                         std::cerr << "Step " << current | ||||
|                                                   << " out of " << total << std::endl; | ||||
|                             client->send(msg->str, msg->binary, [](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::cerr << bufferedAmount << " bytes left to be sent" | ||||
|                                           << std::endl; | ||||
|  | ||||
|                                 std::chrono::duration<double, std::milli> duration(10); | ||||
|                                 std::this_thread::sleep_for(duration); | ||||
| @@ -81,10 +75,8 @@ namespace ix | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -98,4 +90,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -9,13 +9,12 @@ | ||||
| // Broadcast server can be ran with `ws broadcast_server` | ||||
| // | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <queue> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
|  | ||||
| #include "nlohmann/json.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <queue> | ||||
| #include <sstream> | ||||
|  | ||||
| // for convenience | ||||
| using json = nlohmann::json; | ||||
| @@ -25,8 +24,7 @@ namespace ix | ||||
|     class WebSocketChat | ||||
|     { | ||||
|     public: | ||||
|             WebSocketChat(const std::string& url, | ||||
|                           const std::string& user); | ||||
|         WebSocketChat(const std::string& url, const std::string& user); | ||||
|  | ||||
|         void subscribe(const std::string& channel); | ||||
|         void start(); | ||||
| @@ -48,10 +46,9 @@ namespace ix | ||||
|         void log(const std::string& msg); | ||||
|     }; | ||||
|  | ||||
|     WebSocketChat::WebSocketChat(const std::string& url, | ||||
|                                  const std::string& user) : | ||||
|         _url(url), | ||||
|         _user(user) | ||||
|     WebSocketChat::WebSocketChat(const std::string& url, const std::string& user) | ||||
|         : _url(url) | ||||
|         , _user(user) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -83,9 +80,7 @@ namespace ix | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + _url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](const WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([this](const WebSocketMessagePtr& msg) { | ||||
|             std::stringstream ss; | ||||
|             if (msg->type == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
| @@ -97,18 +92,13 @@ namespace ix | ||||
|                     std::cout << it.first << ": " << it.second << std::endl; | ||||
|                 } | ||||
|  | ||||
|                     ss << "ws chat: user " | ||||
|                        << _user | ||||
|                        << " Connected !"; | ||||
|                 ss << "ws chat: user " << _user << " Connected !"; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|             { | ||||
|                     ss << "ws chat: user " | ||||
|                        << _user | ||||
|                        << " disconnected !" | ||||
|                        << " code " << msg->closeInfo.code | ||||
|                        << " reason " << msg->closeInfo.reason; | ||||
|                 ss << "ws chat: user " << _user << " disconnected !" | ||||
|                    << " code " << msg->closeInfo.code << " reason " << msg->closeInfo.reason; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Message) | ||||
| @@ -122,8 +112,8 @@ namespace ix | ||||
|                 _receivedQueue.push(result.second); | ||||
|  | ||||
|                 ss << std::endl | ||||
|                        << result.first << "(" << msg->wireSize << " bytes)" << " > " << result.second | ||||
|                        << std::endl | ||||
|                    << result.first << "(" << msg->wireSize << " bytes)" | ||||
|                    << " > " << result.second << std::endl | ||||
|                    << _user << " > "; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
| @@ -170,8 +160,7 @@ namespace ix | ||||
|         _webSocket.sendText(encodeMessage(text)); | ||||
|     } | ||||
|  | ||||
|     int ws_chat_main(const std::string& url, | ||||
|                      const std::string& user) | ||||
|     int ws_chat_main(const std::string& url, const std::string& user) | ||||
|     { | ||||
|         std::cout << "Type Ctrl-D to exit prompt..." << std::endl; | ||||
|         WebSocketChat webSocketChat(url, user); | ||||
| @@ -196,4 +185,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,15 +4,15 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
| #include <thread> | ||||
| #include <atomic> | ||||
| #include <jsoncpp/json/json.h> | ||||
| #include <chrono> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <ixcobra/IXCobraMetricsPublisher.h> | ||||
| #include <jsoncpp/json/json.h> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
| #include <thread> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -27,25 +27,23 @@ namespace ix | ||||
|         std::atomic<int> sentMessages(0); | ||||
|         std::atomic<int> ackedMessages(0); | ||||
|         CobraConnection::setPublishTrackerCallback( | ||||
|             [&sentMessages, &ackedMessages](bool sent, bool acked) | ||||
|             { | ||||
|             [&sentMessages, &ackedMessages](bool sent, bool acked) { | ||||
|                 if (sent) sentMessages++; | ||||
|                 if (acked) ackedMessages++; | ||||
|             } | ||||
|         ); | ||||
|             }); | ||||
|  | ||||
|         CobraMetricsPublisher cobraMetricsPublisher; | ||||
|         cobraMetricsPublisher.enable(true); | ||||
|  | ||||
|         bool enablePerMessageDeflate = true; | ||||
|         cobraMetricsPublisher.configure(appkey, endpoint, channel, | ||||
|                                         rolename, rolesecret, enablePerMessageDeflate); | ||||
|         cobraMetricsPublisher.configure( | ||||
|             appkey, endpoint, channel, rolename, rolesecret, enablePerMessageDeflate); | ||||
|  | ||||
|         while (!cobraMetricsPublisher.isAuthenticated()) ; | ||||
|         while (!cobraMetricsPublisher.isAuthenticated()) | ||||
|             ; | ||||
|  | ||||
|         std::ifstream f(path); | ||||
|         std::string str((std::istreambuf_iterator<char>(f)), | ||||
|                          std::istreambuf_iterator<char>()); | ||||
|         std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); | ||||
|  | ||||
|         Json::Value data; | ||||
|         Json::Reader reader; | ||||
| @@ -70,7 +68,8 @@ namespace ix | ||||
|                 cobraMetricsPublisher.resume(); | ||||
|  | ||||
|                 // FIXME: investigate why without this check we trigger a lock | ||||
|                 while (!cobraMetricsPublisher.isAuthenticated()) ; | ||||
|                 while (!cobraMetricsPublisher.isAuthenticated()) | ||||
|                     ; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -83,5 +82,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,17 +4,17 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
| #include <thread> | ||||
| #include <atomic> | ||||
| #include <mutex> | ||||
| #include <chrono> | ||||
| #include <condition_variable> | ||||
| #include <jsoncpp/json/json.h> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <ixcobra/IXCobraMetricsPublisher.h> | ||||
| #include <jsoncpp/json/json.h> | ||||
| #include <mutex> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
| #include <thread> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -26,8 +26,7 @@ namespace ix | ||||
|                               const std::string& path) | ||||
|     { | ||||
|         std::ifstream f(path); | ||||
|         std::string str((std::istreambuf_iterator<char>(f)), | ||||
|                          std::istreambuf_iterator<char>()); | ||||
|         std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); | ||||
|  | ||||
|         Json::Value data; | ||||
|         Json::Reader reader; | ||||
| @@ -38,9 +37,8 @@ namespace ix | ||||
|         } | ||||
|  | ||||
|         ix::CobraConnection conn; | ||||
|         conn.configure(appkey, endpoint, | ||||
|                        rolename, rolesecret, | ||||
|                        ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.configure( | ||||
|             appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.connect(); | ||||
|  | ||||
|         // Display incoming messages | ||||
| @@ -48,14 +46,12 @@ namespace ix | ||||
|         std::atomic<bool> messageAcked(false); | ||||
|         std::condition_variable condition; | ||||
|  | ||||
|         conn.setEventCallback( | ||||
|             [&conn, &channel, &data, &authenticated, &messageAcked, &condition] | ||||
|             (ix::CobraConnectionEventType eventType, | ||||
|         conn.setEventCallback([&conn, &channel, &data, &authenticated, &messageAcked, &condition]( | ||||
|                                   ix::CobraConnectionEventType eventType, | ||||
|                                   const std::string& errMsg, | ||||
|                                   const ix::WebSocketHttpHeaders& headers, | ||||
|                                   const std::string& subscriptionId, | ||||
|              CobraConnection::MsgId msgId) | ||||
|             { | ||||
|                                   CobraConnection::MsgId msgId) { | ||||
|             if (eventType == ix::CobraConnection_EventType_Open) | ||||
|             { | ||||
|                 spdlog::info("Publisher connected"); | ||||
| @@ -95,12 +91,13 @@ namespace ix | ||||
|                 messageAcked = true; | ||||
|                 condition.notify_one(); | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|  | ||||
|         while (!authenticated) ; | ||||
|         while (!messageAcked) ; | ||||
|         while (!authenticated) | ||||
|             ; | ||||
|         while (!messageAcked) | ||||
|             ; | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,14 +4,13 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
| #include <thread> | ||||
| #include <atomic> | ||||
| #include <chrono> | ||||
| #include <iostream> | ||||
| #include <ixcobra/IXCobraConnection.h> | ||||
|  | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
| #include <thread> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -24,9 +23,8 @@ namespace ix | ||||
|                                 bool quiet) | ||||
|     { | ||||
|         ix::CobraConnection conn; | ||||
|         conn.configure(appkey, endpoint, | ||||
|                        rolename, rolesecret, | ||||
|                        ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.configure( | ||||
|             appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.connect(); | ||||
|  | ||||
|         Json::FastWriter jsonWriter; | ||||
| @@ -35,13 +33,11 @@ namespace ix | ||||
|         std::atomic<int> msgPerSeconds(0); | ||||
|         std::atomic<int> msgCount(0); | ||||
|  | ||||
|         auto timer = [&msgPerSeconds, &msgCount] | ||||
|         { | ||||
|         auto timer = [&msgPerSeconds, &msgCount] { | ||||
|             while (true) | ||||
|             { | ||||
|                 std::cout << "#messages " << msgCount << " " | ||||
|                           << "msg/s " << msgPerSeconds | ||||
|                           << std::endl; | ||||
|                           << "msg/s " << msgPerSeconds << std::endl; | ||||
|  | ||||
|                 msgPerSeconds = 0; | ||||
|                 auto duration = std::chrono::seconds(1); | ||||
| @@ -52,13 +48,12 @@ namespace ix | ||||
|         std::thread t(timer); | ||||
|  | ||||
|         conn.setEventCallback( | ||||
|             [&conn, &channel, &jsonWriter, &filter, &msgCount, &msgPerSeconds, &quiet] | ||||
|             (ix::CobraConnectionEventType eventType, | ||||
|             [&conn, &channel, &jsonWriter, &filter, &msgCount, &msgPerSeconds, &quiet]( | ||||
|                 ix::CobraConnectionEventType eventType, | ||||
|                 const std::string& errMsg, | ||||
|                 const ix::WebSocketHttpHeaders& headers, | ||||
|                 const std::string& subscriptionId, | ||||
|              CobraConnection::MsgId msgId) | ||||
|             { | ||||
|                 CobraConnection::MsgId msgId) { | ||||
|                 if (eventType == ix::CobraConnection_EventType_Open) | ||||
|                 { | ||||
|                     spdlog::info("Subscriber connected"); | ||||
| @@ -71,10 +66,10 @@ namespace ix | ||||
|                 else if (eventType == ix::CobraConnection_EventType_Authenticated) | ||||
|                 { | ||||
|                     spdlog::info("Subscriber authenticated"); | ||||
|                     conn.subscribe(channel, filter, | ||||
|                                    [&jsonWriter, &quiet, | ||||
|                                     &msgPerSeconds, &msgCount](const Json::Value& msg) | ||||
|                                    { | ||||
|                     conn.subscribe( | ||||
|                         channel, | ||||
|                         filter, | ||||
|                         [&jsonWriter, &quiet, &msgPerSeconds, &msgCount](const Json::Value& msg) { | ||||
|                             if (!quiet) | ||||
|                             { | ||||
|                                 std::cout << jsonWriter.write(msg) << std::endl; | ||||
| @@ -100,8 +95,7 @@ namespace ix | ||||
|                 { | ||||
|                     spdlog::error("Published message hacked: {}", msgId); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|             }); | ||||
|  | ||||
|         while (true) | ||||
|         { | ||||
| @@ -111,4 +105,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,19 +4,18 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
| #include <thread> | ||||
| #include <atomic> | ||||
| #include <vector> | ||||
| #include <queue> | ||||
| #include <mutex> | ||||
| #include <condition_variable> | ||||
| #include <ixcobra/IXCobraConnection.h> | ||||
| #include <spdlog/spdlog.h> | ||||
|  | ||||
| #include "IXSentryClient.h" | ||||
| #include <atomic> | ||||
| #include <chrono> | ||||
| #include <condition_variable> | ||||
| #include <iostream> | ||||
| #include <ixcobra/IXCobraConnection.h> | ||||
| #include <mutex> | ||||
| #include <queue> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
| #include <thread> | ||||
| #include <vector> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -32,9 +31,8 @@ namespace ix | ||||
|                                 int jobs) | ||||
|     { | ||||
|         ix::CobraConnection conn; | ||||
|         conn.configure(appkey, endpoint, | ||||
|                        rolename, rolesecret, | ||||
|                        ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.configure( | ||||
|             appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.connect(); | ||||
|  | ||||
|         Json::FastWriter jsonWriter; | ||||
| @@ -48,10 +46,15 @@ namespace ix | ||||
|         std::condition_variable progressCondition; | ||||
|         std::queue<Json::Value> queue; | ||||
|  | ||||
|         auto sentrySender = [&condition, &progressCondition, &conditionVariableMutex, | ||||
|                              &queue, verbose, &errorSending, &sentCount, | ||||
|                              &stop, &dsn] | ||||
|         { | ||||
|         auto sentrySender = [&condition, | ||||
|                              &progressCondition, | ||||
|                              &conditionVariableMutex, | ||||
|                              &queue, | ||||
|                              verbose, | ||||
|                              &errorSending, | ||||
|                              &sentCount, | ||||
|                              &stop, | ||||
|                              &dsn] { | ||||
|             SentryClient sentryClient(dsn); | ||||
|  | ||||
|             while (true) | ||||
| @@ -94,17 +97,21 @@ namespace ix | ||||
|             pool.push_back(std::thread(sentrySender)); | ||||
|         } | ||||
|  | ||||
|         conn.setEventCallback( | ||||
|             [&conn, &channel, &filter, &jsonWriter, | ||||
|              verbose, &receivedCount, &sentCount, | ||||
|              &condition, &conditionVariableMutex, | ||||
|              &progressCondition, &queue] | ||||
|             (ix::CobraConnectionEventType eventType, | ||||
|         conn.setEventCallback([&conn, | ||||
|                                &channel, | ||||
|                                &filter, | ||||
|                                &jsonWriter, | ||||
|                                verbose, | ||||
|                                &receivedCount, | ||||
|                                &sentCount, | ||||
|                                &condition, | ||||
|                                &conditionVariableMutex, | ||||
|                                &progressCondition, | ||||
|                                &queue](ix::CobraConnectionEventType eventType, | ||||
|                                        const std::string& errMsg, | ||||
|                                        const ix::WebSocketHttpHeaders& headers, | ||||
|                                        const std::string& subscriptionId, | ||||
|              CobraConnection::MsgId msgId) | ||||
|             { | ||||
|                                        CobraConnection::MsgId msgId) { | ||||
|             if (eventType == ix::CobraConnection_EventType_Open) | ||||
|             { | ||||
|                 spdlog::info("Subscriber connected"); | ||||
| @@ -121,13 +128,16 @@ namespace ix | ||||
|             else if (eventType == ix::CobraConnection_EventType_Authenticated) | ||||
|             { | ||||
|                 std::cerr << "Subscriber authenticated" << std::endl; | ||||
|                     conn.subscribe(channel, filter, | ||||
|                                    [&jsonWriter, verbose, | ||||
|                                     &sentCount, &receivedCount, | ||||
|                                     &condition, &conditionVariableMutex, | ||||
|                                     &progressCondition, &queue] | ||||
|                                    (const Json::Value& msg) | ||||
|                                    { | ||||
|                 conn.subscribe(channel, | ||||
|                                filter, | ||||
|                                [&jsonWriter, | ||||
|                                 verbose, | ||||
|                                 &sentCount, | ||||
|                                 &receivedCount, | ||||
|                                 &condition, | ||||
|                                 &conditionVariableMutex, | ||||
|                                 &progressCondition, | ||||
|                                 &queue](const Json::Value& msg) { | ||||
|                                    if (verbose) | ||||
|                                    { | ||||
|                                        spdlog::info(jsonWriter.write(msg)); | ||||
| @@ -136,8 +146,7 @@ namespace ix | ||||
|                                    // If we cannot send to sentry fast enough, drop the message | ||||
|                                    const uint64_t scaleFactor = 2; | ||||
|  | ||||
|                                        if (sentCount != 0 && | ||||
|                                            receivedCount != 0 && | ||||
|                                    if (sentCount != 0 && receivedCount != 0 && | ||||
|                                        (sentCount * scaleFactor < receivedCount)) | ||||
|                                    { | ||||
|                                        spdlog::warn("message dropped: sending is backlogged !"); | ||||
| @@ -174,8 +183,7 @@ namespace ix | ||||
|             { | ||||
|                 spdlog::error("Published message hacked: {}", msgId); | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|  | ||||
|         std::mutex progressConditionVariableMutex; | ||||
|         while (true) | ||||
| @@ -200,4 +208,4 @@ namespace ix | ||||
|  | ||||
|         return (strict && errorSending) ? 1 : 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,15 +4,14 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
| #include <thread> | ||||
| #include <atomic> | ||||
| #include <vector> | ||||
| #include <chrono> | ||||
| #include <iostream> | ||||
| #include <ixcobra/IXCobraConnection.h> | ||||
|  | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
| #include <thread> | ||||
| #include <vector> | ||||
|  | ||||
| #ifndef _WIN32 | ||||
| #include <statsd_client.h> | ||||
| @@ -41,8 +40,7 @@ namespace ix | ||||
|     // Extract an attribute from a Json Value. | ||||
|     // extractAttr("foo.bar", {"foo": {"bar": "baz"}}) => baz | ||||
|     // | ||||
|     std::string extractAttr(const std::string& attr, | ||||
|                             const Json::Value& jsonValue) | ||||
|     std::string extractAttr(const std::string& attr, const Json::Value& jsonValue) | ||||
|     { | ||||
|         // Split by . | ||||
|         std::string token; | ||||
| @@ -71,9 +69,8 @@ namespace ix | ||||
|                                 bool verbose) | ||||
|     { | ||||
|         ix::CobraConnection conn; | ||||
|         conn.configure(appkey, endpoint, | ||||
|                        rolename, rolesecret, | ||||
|                        ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.configure( | ||||
|             appkey, endpoint, rolename, rolesecret, ix::WebSocketPerMessageDeflateOptions(true)); | ||||
|         conn.connect(); | ||||
|  | ||||
|         auto tokens = parseFields(fields); | ||||
| @@ -90,14 +87,19 @@ namespace ix | ||||
|         Json::FastWriter jsonWriter; | ||||
|         uint64_t msgCount = 0; | ||||
|  | ||||
|         conn.setEventCallback( | ||||
|             [&conn, &channel, &filter, &jsonWriter, &statsdClient, verbose, &tokens, &prefix, &msgCount] | ||||
|             (ix::CobraConnectionEventType eventType, | ||||
|         conn.setEventCallback([&conn, | ||||
|                                &channel, | ||||
|                                &filter, | ||||
|                                &jsonWriter, | ||||
|                                &statsdClient, | ||||
|                                verbose, | ||||
|                                &tokens, | ||||
|                                &prefix, | ||||
|                                &msgCount](ix::CobraConnectionEventType eventType, | ||||
|                                           const std::string& errMsg, | ||||
|                                           const ix::WebSocketHttpHeaders& headers, | ||||
|                                           const std::string& subscriptionId, | ||||
|              CobraConnection::MsgId msgId) | ||||
|             { | ||||
|                                           CobraConnection::MsgId msgId) { | ||||
|             if (eventType == ix::CobraConnection_EventType_Open) | ||||
|             { | ||||
|                 spdlog::info("Subscriber connected"); | ||||
| @@ -114,11 +116,10 @@ namespace ix | ||||
|             else if (eventType == ix::CobraConnection_EventType_Authenticated) | ||||
|             { | ||||
|                 spdlog::info("Subscriber authenticated"); | ||||
|                     conn.subscribe(channel, filter, | ||||
|                                    [&jsonWriter, &statsdClient, | ||||
|                                     verbose, &tokens, &prefix, &msgCount] | ||||
|                                    (const Json::Value& msg) | ||||
|                                    { | ||||
|                 conn.subscribe(channel, | ||||
|                                filter, | ||||
|                                [&jsonWriter, &statsdClient, verbose, &tokens, &prefix, &msgCount]( | ||||
|                                    const Json::Value& msg) { | ||||
|                                    if (verbose) | ||||
|                                    { | ||||
|                                        spdlog::info(jsonWriter.write(msg)); | ||||
| @@ -154,8 +155,7 @@ namespace ix | ||||
|             { | ||||
|                 spdlog::error("Published message hacked: {}", msgId); | ||||
|             } | ||||
|             } | ||||
|         ); | ||||
|         }); | ||||
|  | ||||
|         while (true) | ||||
|         { | ||||
| @@ -165,4 +165,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,12 +4,11 @@ | ||||
|  *  Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
|  | ||||
| #include "linenoise.hpp" | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <sstream> | ||||
|  | ||||
|  | ||||
| namespace ix | ||||
| @@ -46,10 +45,10 @@ namespace ix | ||||
|                                        bool disableAutomaticReconnection, | ||||
|                                        bool disablePerMessageDeflate, | ||||
|                                        bool binaryMode, | ||||
|                                        uint32_t maxWaitBetweenReconnectionRetries) : | ||||
|         _url(url), | ||||
|         _disablePerMessageDeflate(disablePerMessageDeflate), | ||||
|         _binaryMode(binaryMode) | ||||
|                                        uint32_t maxWaitBetweenReconnectionRetries) | ||||
|         : _url(url) | ||||
|         , _disablePerMessageDeflate(disablePerMessageDeflate) | ||||
|         , _binaryMode(binaryMode) | ||||
|     { | ||||
|         if (disableAutomaticReconnection) | ||||
|         { | ||||
| @@ -114,9 +113,7 @@ namespace ix | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + _url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) { | ||||
|             std::stringstream ss; | ||||
|             if (msg->type == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
| @@ -139,8 +136,7 @@ namespace ix | ||||
|             { | ||||
|                 std::cerr << "Received " << msg->wireSize << " bytes" << std::endl; | ||||
|  | ||||
|                     ss << "ws_connect: received message: " | ||||
|                        << msg->str; | ||||
|                 ss << "ws_connect: received message: " << msg->str; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Error) | ||||
| @@ -237,5 +233,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,8 +5,8 @@ | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -18,11 +18,9 @@ namespace ix | ||||
|  | ||||
|         server.setOnConnectionCallback( | ||||
|             [greetings](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                         std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|                         std::shared_ptr<ConnectionState> connectionState) { | ||||
|                 webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, greetings](const WebSocketMessagePtr& msg) | ||||
|                     { | ||||
|                     [webSocket, connectionState, greetings](const WebSocketMessagePtr& msg) { | ||||
|                         if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                         { | ||||
|                             std::cerr << "New connection" << std::endl; | ||||
| @@ -42,8 +40,8 @@ namespace ix | ||||
|                         else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|                         { | ||||
|                             std::cerr << "Closed connection" | ||||
|                                       << " code " << msg->closeInfo.code | ||||
|                                       << " reason " << msg->closeInfo.reason << std::endl; | ||||
|                                       << " code " << msg->closeInfo.code << " reason " | ||||
|                                       << msg->closeInfo.reason << std::endl; | ||||
|                         } | ||||
|                         else if (msg->type == ix::WebSocketMessageType::Error) | ||||
|                         { | ||||
| @@ -56,15 +54,11 @@ namespace ix | ||||
|                         } | ||||
|                         else if (msg->type == ix::WebSocketMessageType::Message) | ||||
|                         { | ||||
|                             std::cerr << "Received " | ||||
|                                       << msg->wireSize << " bytes" | ||||
|                                       << std::endl; | ||||
|                             std::cerr << "Received " << msg->wireSize << " bytes" << std::endl; | ||||
|                             webSocket->send(msg->str, msg->binary); | ||||
|                         } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|                     }); | ||||
|             }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -78,4 +72,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,11 +4,11 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXHttpClient.h> | ||||
| #include <ixwebsocket/IXWebSocketHttpHeaders.h> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -104,14 +104,10 @@ namespace ix | ||||
|         args->maxRedirects = maxRedirects; | ||||
|         args->verbose = verbose; | ||||
|         args->compress = compress; | ||||
|         args->logger = [](const std::string& msg) | ||||
|         { | ||||
|             std::cout << msg; | ||||
|         }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool | ||||
|         { | ||||
|             std::cerr << "\r" << "Downloaded " | ||||
|                       << current << " bytes out of " << total; | ||||
|         args->logger = [](const std::string& msg) { std::cout << msg; }; | ||||
|         args->onProgressCallback = [](int current, int total) -> bool { | ||||
|             std::cerr << "\r" | ||||
|                       << "Downloaded " << current << " bytes out of " << total; | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
| @@ -173,11 +169,12 @@ namespace ix | ||||
|                 { | ||||
|                     std::cerr << "Binary output can mess up your terminal." << std::endl; | ||||
|                     std::cerr << "Use the -O flag to save the file to disk." << std::endl; | ||||
|                     std::cerr << "You can also use the --output option to specify a filename." << std::endl; | ||||
|                     std::cerr << "You can also use the --output option to specify a filename." | ||||
|                               << std::endl; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,12 +4,12 @@ | ||||
|  *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <iostream> | ||||
| #include <ixwebsocket/IXHttpServer.h> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -31,4 +31,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,9 +5,9 @@ | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -30,8 +30,8 @@ namespace ix | ||||
|         void log(const std::string& msg); | ||||
|     }; | ||||
|  | ||||
|     WebSocketPingPong::WebSocketPingPong(const std::string& url) : | ||||
|         _url(url) | ||||
|     WebSocketPingPong::WebSocketPingPong(const std::string& url) | ||||
|         : _url(url) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -53,9 +53,7 @@ namespace ix | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + _url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) { | ||||
|             std::cerr << "Received " << msg->wireSize << " bytes" << std::endl; | ||||
|  | ||||
|             std::stringstream ss; | ||||
| @@ -73,27 +71,23 @@ namespace ix | ||||
|             else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|             { | ||||
|                 ss << "ping_pong: disconnected:" | ||||
|                        << " code " << msg->closeInfo.code | ||||
|                        << " reason " << msg->closeInfo.reason | ||||
|                    << " code " << msg->closeInfo.code << " reason " << msg->closeInfo.reason | ||||
|                    << msg->str; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Message) | ||||
|             { | ||||
|                     ss << "ping_pong: received message: " | ||||
|                        << msg->str; | ||||
|                 ss << "ping_pong: received message: " << msg->str; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Ping) | ||||
|             { | ||||
|                     ss << "ping_pong: received ping message: " | ||||
|                        << msg->str; | ||||
|                 ss << "ping_pong: received ping message: " << msg->str; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Pong) | ||||
|             { | ||||
|                     ss << "ping_pong: received pong message: " | ||||
|                        << msg->str; | ||||
|                 ss << "ping_pong: received pong message: " << msg->str; | ||||
|                 log(ss.str()); | ||||
|             } | ||||
|             else if (msg->type == ix::WebSocketMessageType::Error) | ||||
| @@ -118,7 +112,8 @@ namespace ix | ||||
|     { | ||||
|         if (!_webSocket.ping(text).success) | ||||
|         { | ||||
|             std::cerr << "Failed to send ping message. Message too long (> 125 bytes) or endpoint is disconnected" | ||||
|             std::cerr << "Failed to send ping message. Message too long (> 125 bytes) or endpoint " | ||||
|                          "is disconnected" | ||||
|                       << std::endl; | ||||
|         } | ||||
|     } | ||||
| @@ -160,4 +155,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,19 +4,19 @@ | ||||
|  *  Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
| #include <condition_variable> | ||||
| #include <mutex> | ||||
| #include <chrono> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixcrypto/IXUuid.h> | ||||
| #include <condition_variable> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <ixcrypto/IXBase64.h> | ||||
| #include <ixcrypto/IXHash.h> | ||||
| #include <ixcrypto/IXUuid.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <msgpack11/msgpack11.hpp> | ||||
| #include <mutex> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| using msgpack11::MsgPack; | ||||
|  | ||||
| @@ -25,9 +25,7 @@ namespace ix | ||||
|     class WebSocketReceiver | ||||
|     { | ||||
|     public: | ||||
|             WebSocketReceiver(const std::string& _url, | ||||
|                               bool enablePerMessageDeflate, | ||||
|                               int delayMs); | ||||
|         WebSocketReceiver(const std::string& _url, bool enablePerMessageDeflate, int delayMs); | ||||
|  | ||||
|         void subscribe(const std::string& channel); | ||||
|         void start(); | ||||
| @@ -55,11 +53,11 @@ namespace ix | ||||
|  | ||||
|     WebSocketReceiver::WebSocketReceiver(const std::string& url, | ||||
|                                          bool enablePerMessageDeflate, | ||||
|                                          int delayMs) : | ||||
|         _url(url), | ||||
|         _enablePerMessageDeflate(enablePerMessageDeflate), | ||||
|         _delayMs(delayMs), | ||||
|         _receivedFragmentCounter(0) | ||||
|                                          int delayMs) | ||||
|         : _url(url) | ||||
|         , _enablePerMessageDeflate(enablePerMessageDeflate) | ||||
|         , _delayMs(delayMs) | ||||
|         , _receivedFragmentCounter(0) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -107,8 +105,7 @@ namespace ix | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void WebSocketReceiver::handleError(const std::string& errMsg, | ||||
|                                         const std::string& id) | ||||
|     void WebSocketReceiver::handleError(const std::string& errMsg, const std::string& id) | ||||
|     { | ||||
|         std::map<MsgPack, MsgPack> pdu; | ||||
|         pdu["kind"] = "error"; | ||||
| @@ -182,9 +179,7 @@ namespace ix | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + _url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](const ix::WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) { | ||||
|             std::stringstream ss; | ||||
|             if (msg->type == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
| @@ -243,9 +238,7 @@ namespace ix | ||||
|         _webSocket.start(); | ||||
|     } | ||||
|  | ||||
|     void wsReceive(const std::string& url, | ||||
|                    bool enablePerMessageDeflate, | ||||
|                    int delayMs) | ||||
|     void wsReceive(const std::string& url, bool enablePerMessageDeflate, int delayMs) | ||||
|     { | ||||
|         WebSocketReceiver webSocketReceiver(url, enablePerMessageDeflate, delayMs); | ||||
|         webSocketReceiver.start(); | ||||
| @@ -261,11 +254,9 @@ namespace ix | ||||
|         webSocketReceiver.stop(); | ||||
|     } | ||||
|  | ||||
|     int ws_receive_main(const std::string& url, | ||||
|                         bool enablePerMessageDeflate, | ||||
|                         int delayMs) | ||||
|     int ws_receive_main(const std::string& url, bool enablePerMessageDeflate, int delayMs) | ||||
|     { | ||||
|         wsReceive(url, enablePerMessageDeflate, delayMs); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,9 +4,9 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "IXRedisClient.h" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include "IXRedisClient.h" | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -41,8 +41,7 @@ namespace ix | ||||
|         { | ||||
|             if (!redisClient.publish(channel, message, errMsg)) | ||||
|             { | ||||
|                 std::cerr << "Error publishing to channel " << channel | ||||
|                           << "error: " << errMsg | ||||
|                 std::cerr << "Error publishing to channel " << channel << "error: " << errMsg | ||||
|                           << std::endl; | ||||
|                 return 1; | ||||
|             } | ||||
| @@ -50,4 +49,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,12 +4,12 @@ | ||||
|  *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include "IXRedisClient.h" | ||||
| #include <atomic> | ||||
| #include <chrono> | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <chrono> | ||||
| #include <thread> | ||||
| #include <atomic> | ||||
| #include "IXRedisClient.h" | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -41,9 +41,7 @@ namespace ix | ||||
|         std::atomic<int> msgPerSeconds(0); | ||||
|         std::atomic<int> msgCount(0); | ||||
|  | ||||
|         auto callback = [&msgPerSeconds, &msgCount, verbose] | ||||
|                          (const std::string& message) | ||||
|         { | ||||
|         auto callback = [&msgPerSeconds, &msgCount, verbose](const std::string& message) { | ||||
|             if (verbose) | ||||
|             { | ||||
|                 std::cout << "received: " << message << std::endl; | ||||
| @@ -53,18 +51,15 @@ namespace ix | ||||
|             msgCount++; | ||||
|         }; | ||||
|  | ||||
|         auto responseCallback = [](const std::string& redisResponse) | ||||
|         { | ||||
|         auto responseCallback = [](const std::string& redisResponse) { | ||||
|             std::cout << "Redis subscribe response: " << redisResponse << std::endl; | ||||
|         }; | ||||
|  | ||||
|         auto timer = [&msgPerSeconds, &msgCount] | ||||
|         { | ||||
|         auto timer = [&msgPerSeconds, &msgCount] { | ||||
|             while (true) | ||||
|             { | ||||
|                 std::cout << "#messages " << msgCount << " " | ||||
|                           << "msg/s " << msgPerSeconds | ||||
|                           << std::endl; | ||||
|                           << "msg/s " << msgPerSeconds << std::endl; | ||||
|  | ||||
|                 msgPerSeconds = 0; | ||||
|                 auto duration = std::chrono::seconds(1); | ||||
| @@ -83,4 +78,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -4,19 +4,19 @@ | ||||
|  *  Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
| #include <condition_variable> | ||||
| #include <mutex> | ||||
| #include <chrono> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixcrypto/IXUuid.h> | ||||
| #include <condition_variable> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <ixcrypto/IXBase64.h> | ||||
| #include <ixcrypto/IXHash.h> | ||||
| #include <ixcrypto/IXUuid.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <msgpack11/msgpack11.hpp> | ||||
| #include <mutex> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| using msgpack11::MsgPack; | ||||
|  | ||||
| @@ -25,8 +25,7 @@ namespace ix | ||||
|     class WebSocketSender | ||||
|     { | ||||
|     public: | ||||
|             WebSocketSender(const std::string& _url, | ||||
|                             bool enablePerMessageDeflate); | ||||
|         WebSocketSender(const std::string& _url, bool enablePerMessageDeflate); | ||||
|  | ||||
|         void subscribe(const std::string& channel); | ||||
|         void start(); | ||||
| @@ -49,10 +48,9 @@ namespace ix | ||||
|         void log(const std::string& msg); | ||||
|     }; | ||||
|  | ||||
|     WebSocketSender::WebSocketSender(const std::string& url, | ||||
|                                      bool enablePerMessageDeflate) : | ||||
|         _url(url), | ||||
|         _enablePerMessageDeflate(enablePerMessageDeflate) | ||||
|     WebSocketSender::WebSocketSender(const std::string& url, bool enablePerMessageDeflate) | ||||
|         : _url(url) | ||||
|         , _enablePerMessageDeflate(enablePerMessageDeflate) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| @@ -111,9 +109,7 @@ namespace ix | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + _url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](const WebSocketMessagePtr& msg) | ||||
|             { | ||||
|         _webSocket.setOnMessageCallback([this](const WebSocketMessagePtr& msg) { | ||||
|             std::stringstream ss; | ||||
|             if (msg->type == ix::WebSocketMessageType::Open) | ||||
|             { | ||||
| @@ -177,10 +173,10 @@ namespace ix | ||||
|     class Bench | ||||
|     { | ||||
|     public: | ||||
|             Bench(const std::string& description) : | ||||
|                 _description(description), | ||||
|                 _start(std::chrono::system_clock::now()), | ||||
|                 _reported(false) | ||||
|         Bench(const std::string& description) | ||||
|             : _description(description) | ||||
|             , _start(std::chrono::system_clock::now()) | ||||
|             , _reported(false) | ||||
|         { | ||||
|             ; | ||||
|         } | ||||
| @@ -199,8 +195,7 @@ namespace ix | ||||
|             auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start); | ||||
|  | ||||
|             _ms = milliseconds.count(); | ||||
|                 std::cout << _description << " completed in " | ||||
|                           << _ms << "ms" << std::endl; | ||||
|             std::cout << _description << " completed in " << _ms << "ms" << std::endl; | ||||
|  | ||||
|             _reported = true; | ||||
|         } | ||||
| @@ -217,8 +212,7 @@ namespace ix | ||||
|         bool _reported; | ||||
|     }; | ||||
|  | ||||
|     void WebSocketSender::sendMessage(const std::string& filename, | ||||
|                                       bool throttle) | ||||
|     void WebSocketSender::sendMessage(const std::string& filename, bool throttle) | ||||
|     { | ||||
|         std::vector<uint8_t> content; | ||||
|         { | ||||
| @@ -239,9 +233,7 @@ namespace ix | ||||
|         MsgPack msg(pdu); | ||||
|  | ||||
|         Bench bench("Sending file through websocket"); | ||||
|         _webSocket.sendBinary(msg.dump(), | ||||
|                               [throttle](int current, int total) -> bool | ||||
|         { | ||||
|         _webSocket.sendBinary(msg.dump(), [throttle](int current, int total) -> bool { | ||||
|             std::cout << "ws_send: Step " << current << " out of " << total << std::endl; | ||||
|  | ||||
|             if (throttle) | ||||
| @@ -256,8 +248,7 @@ namespace ix | ||||
|         do | ||||
|         { | ||||
|             size_t bufferedAmount = _webSocket.bufferedAmount(); | ||||
|             std::cout << "ws_send: " << bufferedAmount | ||||
|                       << " bytes left to be sent" << std::endl; | ||||
|             std::cout << "ws_send: " << bufferedAmount << " bytes left to be sent" << std::endl; | ||||
|  | ||||
|             std::chrono::duration<double, std::milli> duration(10); | ||||
|             std::this_thread::sleep_for(duration); | ||||
| @@ -289,8 +280,7 @@ namespace ix | ||||
|         webSocketSender.stop(); | ||||
|     } | ||||
|  | ||||
|     int ws_send_main(const std::string& url, | ||||
|                      const std::string& path) | ||||
|     int ws_send_main(const std::string& url, const std::string& path) | ||||
|     { | ||||
|         bool throttle = false; | ||||
|         bool enablePerMessageDeflate = false; | ||||
| @@ -298,4 +288,4 @@ namespace ix | ||||
|         wsSend(url, path, enablePerMessageDeflate, throttle); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,10 +5,9 @@ | ||||
|  */ | ||||
|  | ||||
| #include "IXSnakeServer.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <fstream> | ||||
|  | ||||
| namespace | ||||
| { | ||||
| @@ -34,7 +33,7 @@ namespace | ||||
|         auto vec = load(path); | ||||
|         return std::string(vec.begin(), vec.end()); | ||||
|     } | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -80,4 +79,4 @@ namespace ix | ||||
|  | ||||
|         return 0; // should never reach this | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -5,8 +5,8 @@ | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <ixwebsocket/IXWebSocketServer.h> | ||||
| #include <sstream> | ||||
|  | ||||
| namespace ix | ||||
| { | ||||
| @@ -16,13 +16,10 @@ namespace ix | ||||
|  | ||||
|         ix::WebSocketServer server(port, hostname); | ||||
|  | ||||
|         server.setOnConnectionCallback( | ||||
|             [&server](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                       std::shared_ptr<ConnectionState> connectionState) | ||||
|             { | ||||
|                 webSocket->setOnMessageCallback( | ||||
|                     [webSocket, connectionState, &server](const WebSocketMessagePtr& msg) | ||||
|                     { | ||||
|         server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket, | ||||
|                                                  std::shared_ptr<ConnectionState> connectionState) { | ||||
|             webSocket->setOnMessageCallback([webSocket, connectionState, &server]( | ||||
|                                                 const WebSocketMessagePtr& msg) { | ||||
|                 if (msg->type == ix::WebSocketMessageType::Open) | ||||
|                 { | ||||
|                     std::cerr << "New connection" << std::endl; | ||||
| @@ -37,8 +34,8 @@ namespace ix | ||||
|                 else if (msg->type == ix::WebSocketMessageType::Close) | ||||
|                 { | ||||
|                     std::cerr << "Closed connection" | ||||
|                                       << " code " << msg->closeInfo.code | ||||
|                                       << " reason " << msg->closeInfo.reason << std::endl; | ||||
|                               << " code " << msg->closeInfo.code << " reason " | ||||
|                               << msg->closeInfo.reason << std::endl; | ||||
|                 } | ||||
|                 else if (msg->type == ix::WebSocketMessageType::Error) | ||||
|                 { | ||||
| @@ -51,8 +48,7 @@ namespace ix | ||||
|                 } | ||||
|                 else if (msg->type == ix::WebSocketMessageType::Fragment) | ||||
|                 { | ||||
|                             std::cerr << "Received message fragment " | ||||
|                                       << std::endl; | ||||
|                     std::cerr << "Received message fragment " << std::endl; | ||||
|                 } | ||||
|                 else if (msg->type == ix::WebSocketMessageType::Message) | ||||
|                 { | ||||
| @@ -61,12 +57,9 @@ namespace ix | ||||
|                     { | ||||
|                         if (client != webSocket) | ||||
|                         { | ||||
|                                     client->send(msg->str, | ||||
|                                                  msg->binary, | ||||
|                                                  [](int current, int total) -> bool | ||||
|                                     { | ||||
|                                         std::cerr << "ws_transfer: Step " << current | ||||
|                                                   << " out of " << total << std::endl; | ||||
|                             client->send(msg->str, msg->binary, [](int current, int total) -> bool { | ||||
|                                 std::cerr << "ws_transfer: Step " << current << " out of " << total | ||||
|                                           << std::endl; | ||||
|                                 return true; | ||||
|                             }); | ||||
|  | ||||
| @@ -82,10 +75,8 @@ namespace ix | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         auto res = server.listen(); | ||||
|         if (!res.first) | ||||
| @@ -99,4 +90,4 @@ namespace ix | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| } // namespace ix | ||||
|   | ||||
		Reference in New Issue
	
	Block a user