Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/FreeDSx/Socket/SocketServerOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ final class SocketServerOptions implements SocketOptionsInterface

private ?int $backlog = null;

private bool $tcpNoDelay = false;

public function __construct()
{
$this->setSslValidateCert(false);
Expand Down Expand Up @@ -112,6 +114,21 @@ public function getBacklog(): ?int
return $this->backlog;
}

/**
* Disable Nagle's algorithm on accepted TCP connections.
*/
public function setTcpNoDelay(bool $tcpNoDelay): self
{
$this->tcpNoDelay = $tcpNoDelay;

return $this;
}

public function isTcpNoDelay(): bool
{
return $this->tcpNoDelay;
}

/**
* The socket-level stream context options, omitting anything left at its default so the kernel decides.
*
Expand All @@ -130,6 +147,9 @@ public function toStreamContextSocketOptions(): array
if ($this->backlog !== null) {
$opts['backlog'] = $this->backlog;
}
if ($this->tcpNoDelay) {
$opts['tcp_nodelay'] = true;
}

return $opts;
}
Expand Down
19 changes: 17 additions & 2 deletions tests/unit/SocketServerOptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function test_it_defaults_the_socket_options_to_off(): void
self::assertFalse($this->subject->isReusePort());
self::assertFalse($this->subject->isReuseAddress());
self::assertNull($this->subject->getBacklog());
self::assertFalse($this->subject->isTcpNoDelay());
}

public function test_it_emits_the_port_reuse_option(): void
Expand Down Expand Up @@ -70,18 +71,30 @@ public function test_it_emits_the_backlog_option(): void
);
}

public function test_it_emits_the_tcp_no_delay_option(): void
{
$this->subject->setTcpNoDelay(true);

self::assertSame(
['tcp_nodelay' => true],
$this->subject->toStreamContextSocketOptions(),
);
}

public function test_it_emits_every_option_that_was_set(): void
{
$this->subject
->setReusePort(true)
->setReuseAddress(true)
->setBacklog(128);
->setBacklog(128)
->setTcpNoDelay(true);

self::assertSame(
[
'so_reuseport' => true,
'so_reuseaddr' => true,
'backlog' => 128,
'tcp_nodelay' => true,
],
$this->subject->toStreamContextSocketOptions(),
);
Expand All @@ -93,7 +106,9 @@ public function test_it_omits_an_option_that_was_switched_back_off(): void
->setReusePort(true)
->setReusePort(false)
->setBacklog(64)
->setBacklog(null);
->setBacklog(null)
->setTcpNoDelay(true)
->setTcpNoDelay(false);

self::assertSame(
[],
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/SocketServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,31 @@ public function test_it_should_construct_a_unix_based_socket_server(): void
self::assertFalse($this->subject->isConnected());
}

public function test_it_should_still_serve_a_unix_client_when_tcp_no_delay_is_set(): void
{
$this->requireUnixTransport();

$this->subject = SocketServer::bindUnix(
$this->testSocket,
(new SocketServerOptions())->setTcpNoDelay(true),
);
$client = Socket::unix($this->testSocket);

try {
$accepted = $this->subject->accept(1.0);
self::assertNotNull($accepted);

$client->write('foo');

self::assertSame(
'foo',
$accepted->read(),
);
} finally {
$client->close();
}
}

public function test_it_should_receive_data(): void
{
$this->subject = SocketServer::bindUdp('0.0.0.0', 33389);
Expand Down
Loading