create a blocking + cancellable Socket::readBytes method

This commit is contained in:
Benjamin Sergeant 2019-03-02 11:01:51 -08:00
parent 0f4e9af172
commit 86cc76388e
5 changed files with 73 additions and 26 deletions

View File

@ -178,6 +178,13 @@ CMakefiles for the library and the examples are available. This library has few
There is a Dockerfile for running some code on Linux, and a unittest which can be executed by typing `make test`. There is a Dockerfile for running some code on Linux, and a unittest which can be executed by typing `make test`.
You can build and install the ws command line tool with Homebrew.
```
brew create --cmake https://github.com/machinezone/IXWebSocket/archive/v1.1.0.tar.gz
brew install IXWebSocket
```
## Implementation details ## Implementation details
### Per Message Deflate compression. ### Per Message Deflate compression.

View File

@ -231,19 +231,15 @@ namespace ix
payload.reserve(contentLength); payload.reserve(contentLength);
// FIXME: very inefficient way to read bytes, but it works... auto chunkResult = _socket->readBytes(contentLength, isCancellationRequested);
for (int i = 0; i < contentLength; ++i) if (!chunkResult.first)
{ {
char c; errorMsg = "Cannot read chunk";
if (!_socket->readByte(&c, isCancellationRequested)) return std::make_tuple(code, HttpErrorCode_ChunkReadError,
{ headers, payload, errorMsg,
return std::make_tuple(code, HttpErrorCode_ReadError,
headers, payload, "Cannot read byte",
uploadSize, downloadSize); uploadSize, downloadSize);
} }
payload += chunkResult.second;
payload += c;
}
} }
else if (headers.find("Transfer-Encoding") != headers.end() && else if (headers.find("Transfer-Encoding") != headers.end() &&
headers["Transfer-Encoding"] == "chunked") headers["Transfer-Encoding"] == "chunked")
@ -277,22 +273,18 @@ namespace ix
payload.reserve(payload.size() + chunkSize); payload.reserve(payload.size() + chunkSize);
// Read another line // Read a chunk
auto chunkResult = _socket->readBytes(chunkSize, isCancellationRequested);
for (uint64_t i = 0; i < chunkSize; ++i) if (!chunkResult.first)
{ {
char c; errorMsg = "Cannot read chunk";
if (!_socket->readByte(&c, isCancellationRequested))
{
errorMsg = "Cannot read byte";
return std::make_tuple(code, HttpErrorCode_ChunkReadError, return std::make_tuple(code, HttpErrorCode_ChunkReadError,
headers, payload, errorMsg, headers, payload, errorMsg,
uploadSize, downloadSize); uploadSize, downloadSize);
} }
payload += chunkResult.second;
payload += c; // Read the line that terminates the chunk (\r\n)
}
lineResult = _socket->readLine(isCancellationRequested); lineResult = _socket->readLine(isCancellationRequested);
if (!lineResult.first) if (!lineResult.first)

View File

@ -251,7 +251,8 @@ namespace ix
{ {
if (!readByte(&c, isCancellationRequested)) if (!readByte(&c, isCancellationRequested))
{ {
return std::make_pair(false, std::string()); // Return what we were able to read
return std::make_pair(false, line);
} }
line += c; line += c;
@ -259,4 +260,26 @@ namespace ix
return std::make_pair(true, line); return std::make_pair(true, line);
} }
std::pair<bool, std::string> Socket::readBytes(
size_t length,
const CancellationRequest& isCancellationRequested)
{
char c;
std::string buffer;
buffer.reserve(length);
for (size_t i = 0; i < length; ++i)
{
if (!readByte(&c, isCancellationRequested))
{
// Return what we were able to read
return std::make_pair(false, buffer);
}
buffer += c;
}
return std::make_pair(true, buffer);
}
} }

View File

@ -58,7 +58,12 @@ namespace ix
const CancellationRequest& isCancellationRequested); const CancellationRequest& isCancellationRequested);
bool writeBytes(const std::string& str, bool writeBytes(const std::string& str,
const CancellationRequest& isCancellationRequested); const CancellationRequest& isCancellationRequested);
std::pair<bool, std::string> readLine(const CancellationRequest& isCancellationRequested);
std::pair<bool, std::string> readLine(
const CancellationRequest& isCancellationRequested);
std::pair<bool, std::string> readBytes(
size_t length,
const CancellationRequest& isCancellationRequested);
static int getErrno(); static int getErrno();
static bool init(); // Required on Windows to initialize WinSocket static bool init(); // Required on Windows to initialize WinSocket

20
third_party/homebrew_formula.rb vendored Normal file
View File

@ -0,0 +1,20 @@
class Ixwebsocket < Formula
desc "WebSocket client and server, and HTTP client command-line tool"
homepage "https://github.com/machinezone/IXWebSocket"
url "https://github.com/machinezone/IXWebSocket/archive/v1.1.0.tar.gz"
sha256 "52592ce3d0a67ad0f90ac9e8a458f61724175d95a01a38d1bad3fcdc5c7b6666"
depends_on "cmake" => :build
def install
system "cmake", ".", *std_cmake_args
system "make", "install"
end
test do
system "#{bin}/ws", "--help"
system "#{bin}/ws", "send", "--help"
system "#{bin}/ws", "receive", "--help"
system "#{bin}/ws", "transfer", "--help"
system "#{bin}/ws", "curl", "--help"
end
end