Skip to content
Closed
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
6 changes: 3 additions & 3 deletions LibreNMS/Data/Source/Net/AddrInfoResolver.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* AddrInfoResolver.php
*
Expand Down Expand Up @@ -46,8 +47,8 @@ public function query(Query $query): PromiseInterface
try {
$cacheKey = $query->describe();

if (!array_key_exists($cacheKey, $this->cache)) {
$hints = match($query->type) {
if (! array_key_exists($cacheKey, $this->cache)) {
$hints = match ($query->type) {
Message::TYPE_A => ['ai_family' => AF_INET, 'ai_socktype' => SOCK_DGRAM],
Message::TYPE_AAAA => ['ai_family' => AF_INET6, 'ai_socktype' => SOCK_DGRAM],
default => ['ai_socktype' => SOCK_DGRAM],
Expand All @@ -69,7 +70,6 @@ public function query(Query $query): PromiseInterface

// Call $resolve with the result
$resolve($message);

} catch (\Throwable $e) {
// Call $reject if there's an error
$reject($e);
Expand Down
1 change: 1 addition & 0 deletions LibreNMS/Data/Source/Net/Connection.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* Connection.php
*
Expand Down
32 changes: 18 additions & 14 deletions LibreNMS/Data/Source/Net/ConnectionFinder.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* ConnectionFinder.php
*
Expand Down Expand Up @@ -32,7 +33,8 @@
use Socket;
use Throwable;

class ConnectionFinder {
class ConnectionFinder
{
private const TIMEOUT_SECONDS = 3;
private const TIMEOUT_MS = 0;

Expand All @@ -48,10 +50,12 @@ class ConnectionFinder {
* @param class-string<ServiceConnector> $connectorClass
* @param UdpCodec $codec
* @return string|null The first successfully connected IP address, or null if all fail.
*
* @throws Throwable
*/
public function connect(array $ips, int $port, string $connectorClass, UdpCodec $codec): ?string {
Log::info("Starting Happy Eyeballs connection attempt to " . count($ips) . " IPs.");
public function connect(array $ips, int $port, string $connectorClass, UdpCodec $codec): ?string
{
Log::info('Starting Happy Eyeballs connection attempt to ' . count($ips) . ' IPs.');
$startTime = microtime(true);

// initiate fibers and connectors for each IP
Expand All @@ -63,12 +67,12 @@ public function connect(array $ips, int $port, string $connectorClass, UdpCodec
}

// The Event Loop
while (!empty($this->connections) && $this->connectedIp === null) {
/** @var Socket[] $read **/
while (! empty($this->connections) && $this->connectedIp === null) {
/** @var Socket[] $read * */
$read = [];
/** @var Socket[] $write **/
/** @var Socket[] $write * */
$write = [];
/** @var Socket[] $except **/
/** @var Socket[] $except * */
$except = [];

foreach ($this->connections as $connection) {
Expand All @@ -83,7 +87,7 @@ public function connect(array $ips, int $port, string $connectorClass, UdpCodec
}

if ($numChanged === false) {
Log::error("Socket select error: " . socket_strerror(socket_last_error()));
Log::error('Socket select error: ' . socket_strerror(socket_last_error()));
break;
} elseif ($numChanged > 0) {
Log::debug("Socket select returned $numChanged sockets ready.");
Expand All @@ -96,21 +100,21 @@ public function connect(array $ips, int $port, string $connectorClass, UdpCodec
try {
Log::debug("Resuming fiber for $readyConnection->connector");
$result = $readyConnection->fiber->resume(true);
Log::debug("Fiber resume result: " . var_export($result, true));
Log::debug('Fiber resume result: ' . var_export($result, true));
if ($result) {
$this->connectedIp ??= $readyConnection->ip;
$this->forgetConnection($readyConnection);
}
} catch (Throwable $e) {
Log::error("Exception in fiber resume: " . $e->getMessage());
Log::error('Exception in fiber resume: ' . $e->getMessage());
$this->forgetConnection($readyConnection);
}
}
}
}
// Check for overall time limit
if ((microtime(true) - $startTime) * 1000 >= self::TIMEOUT_MS) {
Log::debug("Global timeout reached. Terminating connection attempts.");
Log::debug('Global timeout reached. Terminating connection attempts.');
break;
}
}
Expand All @@ -119,14 +123,14 @@ public function connect(array $ips, int $port, string $connectorClass, UdpCodec
foreach ($this->connections as $connection) {
if ($connection->fiber->isSuspended()) {
$result = $connection->fiber->resume(false);
Log::debug("Fiber resume result: " . var_export($result, true));
Log::debug('Fiber resume result: ' . var_export($result, true));
}
}

return $this->connectedIp;
}

protected function getConnection(string|Socket $search): Connection|null
protected function getConnection(string|Socket $search): ?Connection
{
if (is_string($search)) {
return $this->connections[$search] ?? null;
Expand Down Expand Up @@ -161,11 +165,11 @@ protected function fiberWorker(ServiceConnector $connector): void
if ($connector->isServiceAvailable()) {
Log::info("Successfully connected to the first available IP: $ip");
Fiber::suspend($ip); // return IP to the caller

return;
}
}
} while ($ready === true);

} catch (Throwable $e) {
throw $e;
} finally {
Expand Down
10 changes: 5 additions & 5 deletions LibreNMS/Data/Source/Net/Service/BaseConnector.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* BaseConnector.php
*
Expand Down Expand Up @@ -38,15 +39,14 @@
/**
* @var true
*/
private bool $wait_read = false;

Check failure on line 42 in LibreNMS/Data/Source/Net/Service/BaseConnector.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Property LibreNMS\Data\Source\Net\Service\BaseConnector::$wait_read (true) does not accept default value of type false.
private bool $wait_write = false;

public function __construct(
public readonly string $ip,
public readonly int $port,
)
{
$this->fiber = new Fiber(fn() => $this->fiberWorker());
) {
$this->fiber = new Fiber(fn () => $this->fiberWorker());
}

final protected function createSocket(int $type, int $protocol): void
Expand All @@ -55,7 +55,7 @@
$socket = socket_create($domain, $type, $protocol);

if ($socket === false) {
throw new \RuntimeException("Failed to create socket for $this->ip:$this->port ".socket_strerror(socket_last_error()));
throw new \RuntimeException("Failed to create socket for $this->ip:$this->port " . socket_strerror(socket_last_error()));
}

$this->socket = $socket;
Expand Down Expand Up @@ -123,11 +123,11 @@
if ($this->isServiceAvailable()) {
Log::info("Successfully connected to the first available IP: $this->ip");
Fiber::suspend($this->ip);

return;
}
}
} while ($ready === true);

} catch (Throwable $e) {
throw $e;
} finally {
Expand Down
2 changes: 2 additions & 0 deletions LibreNMS/Data/Source/Net/Service/DnsCodec.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* DnsCodec.php
*
Expand Down Expand Up @@ -74,6 +75,7 @@ public function validateResponse(string $payload): bool

// Check QR bit (should be 1 for response)
$flags = unpack('n', substr($payload, 2, 2))[1];

return ($flags & 0x8000) !== 0;
}
}
4 changes: 3 additions & 1 deletion LibreNMS/Data/Source/Net/Service/NtpCodec.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* NtpCodec.php
*
Expand Down Expand Up @@ -31,8 +32,9 @@ public function getPayload(): string
{
// NTP packet format (48 bytes)
// LI = 0, VN = 3, Mode = 3 (client)
$packet = chr(0x1b); // 00011011 in binary
$packet = chr(0x1B); // 00011011 in binary
$packet .= str_repeat(chr(0), 47);

return $packet;
}

Expand Down
7 changes: 5 additions & 2 deletions LibreNMS/Data/Source/Net/Service/ServiceConnector.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* ServiceConnector.php
*
Expand Down Expand Up @@ -29,15 +30,17 @@

interface ServiceConnector extends \Stringable
{

public function connect(): bool;
public function close(): void;

public function close(): void;

public function getIp(): string;

public function hasSocket(Socket $socket): bool;

public function isServiceAvailable(): bool;

public function prepSocketSelect(array &$read, array &$write, array &$except): void;

public function getFiber(): \Fiber;
}
8 changes: 6 additions & 2 deletions LibreNMS/Data/Source/Net/Service/SnmpCodec.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* SnmpCodec.php
*
Expand Down Expand Up @@ -43,10 +44,10 @@
*/
public function setEngineParameters(string $engineId, int $engineBoots, int $engineTime): void
{
$this->engineId = $engineId;

Check failure on line 47 in LibreNMS/Data/Source/Net/Service/SnmpCodec.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Access to an undefined property LibreNMS\Data\Source\Net\Service\SnmpCodec::$engineId.
$this->engineBoots = $engineBoots;

Check failure on line 48 in LibreNMS/Data/Source/Net/Service/SnmpCodec.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Access to an undefined property LibreNMS\Data\Source\Net\Service\SnmpCodec::$engineBoots.
$this->engineTime = $engineTime;

Check failure on line 49 in LibreNMS/Data/Source/Net/Service/SnmpCodec.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Access to an undefined property LibreNMS\Data\Source\Net\Service\SnmpCodec::$engineTime.
$this->engineDiscovered = true;

Check failure on line 50 in LibreNMS/Data/Source/Net/Service/SnmpCodec.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Access to an undefined property LibreNMS\Data\Source\Net\Service\SnmpCodec::$engineDiscovered.
}

public function getPayload(): string
Expand Down Expand Up @@ -84,6 +85,7 @@
$pdu = $this->buildGetRequestPdu();

$message = $version . $community . $pdu;

return $this->encodeSequence($message);
}

Expand All @@ -97,6 +99,7 @@
$pdu = $this->buildGetRequestPdu();

$message = $version . $community . $pdu;

return $this->encodeSequence($message);
}

Expand Down Expand Up @@ -135,6 +138,7 @@
$scopedPdu = $this->encodeSequence($contextEngineId . $contextName . $pdu);

$message = $version . $headerData . $msgSecurityParameters . $scopedPdu;

return $this->encodeSequence($message);
}

Expand All @@ -156,7 +160,7 @@
$pduContent = $requestId . $errorStatus . $errorIndex . $varbindList;

// PDU type: GetRequest (0xa0)
return chr(0xa0) . $this->encodeLength(strlen($pduContent)) . $pduContent;
return chr(0xA0) . $this->encodeLength(strlen($pduContent)) . $pduContent;
}

/**
Expand All @@ -175,7 +179,7 @@
$pduContent = $requestId . $errorStatus . $errorIndex . $varbindList;

// PDU type: GetRequest (0xa0)
return chr(0xa0) . $this->encodeLength(strlen($pduContent)) . $pduContent;
return chr(0xA0) . $this->encodeLength(strlen($pduContent)) . $pduContent;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion LibreNMS/Data/Source/Net/Service/TcpConnector.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* TcpConnector.php
*
Expand Down Expand Up @@ -56,7 +57,7 @@ public function isServiceAvailable(): bool
$soError = socket_get_option($this->socket, SOL_SOCKET, SO_ERROR);

$peerIp = null;
if($soError === 0 && socket_getpeername($this->socket, $peerIp) && $peerIp === $this->ip) {
if ($soError === 0 && socket_getpeername($this->socket, $peerIp) && $peerIp === $this->ip) {
return true;
}

Expand Down
1 change: 1 addition & 0 deletions LibreNMS/Data/Source/Net/Service/UdpCodec.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* UdpCodec.php
*
Expand Down
2 changes: 2 additions & 0 deletions LibreNMS/Data/Source/Net/Service/UdpConnector.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* UdpConnector.php
*
Expand Down Expand Up @@ -62,6 +63,7 @@ public function isServiceAvailable(): bool
// Basic validation: check if response is valid SNMP
if ($this->requestMessage->validateResponse($response)) {
Log::info("Received valid UDP response from $this->ip");

return true;
}
}
Expand Down
Loading
Loading