Skip to content
This repository has been archived by the owner on Oct 14, 2022. It is now read-only.

Commit

Permalink
Fix issues with heavy socket payloads containing non-ASCII characters
Browse files Browse the repository at this point in the history
  • Loading branch information
nesk committed Apr 9, 2018
1 parent 5ed4548 commit b66241a
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 8 deletions.
4 changes: 3 additions & 1 deletion src/ProcessSupervisor.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,9 @@ protected function readNextProcessValue()

try {
$startTimestamp = microtime(true);
$this->client->selectRead($readTimeout);

do {
$this->client->selectRead($readTimeout);
$packet = $this->client->read(static::SOCKET_PACKET_SIZE);

$chunksLeft = (int) substr($packet, 0, static::SOCKET_HEADER_SIZE);
Expand All @@ -332,6 +332,8 @@ protected function readNextProcessValue()
throw $exception;
}

$output = base64_decode($output);

$this->log(LogLevel::DEBUG, ["PORT {$this->serverPort()}", "receiving"], $output);

$data = json_decode($output, true);
Expand Down
12 changes: 5 additions & 7 deletions src/node-process/Connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,21 +103,19 @@ class Connection extends EventEmitter
*/
writeToSocket(str)
{
const bodySize = Connection.SOCKET_PACKET_SIZE - Connection.SOCKET_HEADER_SIZE,
chunkCount = Math.ceil(str.length / bodySize);
const payload = Buffer.from(str).toString('base64');

const packets = [];
const bodySize = Connection.SOCKET_PACKET_SIZE - Connection.SOCKET_HEADER_SIZE,
chunkCount = Math.ceil(payload.length / bodySize);

for (let i = 0 ; i < chunkCount ; i++) {
const chunk = str.substr(i * bodySize, bodySize);
const chunk = payload.substr(i * bodySize, bodySize);

let chunksLeft = String(chunkCount - 1 - i);
chunksLeft = chunksLeft.padStart(Connection.SOCKET_HEADER_SIZE - 1, '0');

packets.push(`${chunksLeft}:${chunk}`);
this.socket.write(`${chunksLeft}:${chunk}`);
}

this.socket.write(packets.join(''));
}

/**
Expand Down
10 changes: 10 additions & 0 deletions tests/Implementation/FsConnectionDelegate.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ class FsConnectionDelegate extends ConnectionDelegate

fs.multipleResourcesIsFile = resources => resources.map(resource => resource.isFile());

fs.getHeavyPayloadWithNonAsciiChars = () => {
let payload = '';

for (let i = 0 ; i < 1024 ; i++) {
payload += 'a';
}

return `😘${payload}😘`;
};

fs.wait = ms => new Promise(resolve => setTimeout(resolve, ms));

fs.runCallback = cb => cb(fs);
Expand Down
9 changes: 9 additions & 0 deletions tests/ImplementationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ public function can_create_and_pass_js_functions()
$this->assertEquals('Callback using scope and arguments: Hello world!', $value);
}

/** @test */
public function can_receive_heavy_payloads_with_non_ascii_chars()
{
$payload = $this->fs->getHeavyPayloadWithNonAsciiChars();

$this->assertStringStartsWith('😘', $payload);
$this->assertStringEndsWith('😘', $payload);
}

/**
* @test
* @expectedException \ExtractrIo\Rialto\Exceptions\Node\FatalException
Expand Down

0 comments on commit b66241a

Please sign in to comment.