<?php
declare(strict_types=1);
namespace Monitoring\Metric\Clients\Connection;
abstract class InetSocket implements ConnectionInterface
{
private const LINE_DELIMITER = "\n";
private const IP_HEADER_SIZE = 60;
protected string $host;
protected int $port;
private int $timeout;
private bool $isPersistent;
private int $maxPayloadSize;
public function __construct(
string $host,
int $port,
?int $timeout = null,
bool $persistent = false,
int $mtu = 1500
) {
$this->host = $host;
$this->port = $port;
$this->isPersistent = $persistent;
$this->maxPayloadSize = $mtu - self::IP_HEADER_SIZE - $this->getProtocolHeaderSize() - strlen(self::LINE_DELIMITER);
$this->timeout = $timeout ?? (int)ini_get('default_socket_timeout');
}
public function getHost(): string
{
return $this->host;
}
public function getPort(): int
{
return $this->port;
}
public function getTimeout(): int
{
return $this->timeout;
}
public function isPersistent(): bool
{
return $this->isPersistent;
}
public function send(string $message): void
{
if (empty($message)) {
return;
}
}
public function sendMessages(array $messages): void
{
if (count($messages) === 0) {
return;
}
if (!$this->isConnected()) {
$this->connect($this->host, $this->port, $this->timeout, $this->isPersistent);
}
foreach ($this->cutIntoMtuSizedPackets($messages) as $packet) {
$this->writeToSocket($packet);
}
}
private function cutIntoMtuSizedPackets(array $messages): array
{
if ($this->allowFragmentation()) {
$message = implode(self::LINE_DELIMITER, $messages) . self::LINE_DELIMITER;
return str_split($message, $this->maxPayloadSize) ?: [];
}
$delimiterLen = strlen(self::LINE_DELIMITER);
$packets = [];
$packet = '';
foreach ($messages as $message) {
if (strlen($packet) + strlen($message) + $delimiterLen > $this->maxPayloadSize) {
$packets[] = $packet;
$packet = '';
}
$packet .= $message . self::LINE_DELIMITER;
}
if ($packet !== '') {
$packets[] = $packet;
}
return $packets;
}
abstract protected function connect(string $host, int $port, int $timeout, bool $persistent): void;
abstract protected function isConnected(): bool;
abstract protected function writeToSocket(string $message): void;
abstract protected function getProtocolHeaderSize(): int;
abstract protected function allowFragmentation(): bool;
}