Network discovery, probing, and device management for Phalanx

Maintainers

Package info

github.com/phalanx-php/phalanx-argos

pkg:composer/phalanx-php/argos

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main / 0.5.x-dev 2026-04-27 10:14 UTC

This package is not auto-updated.

Last update: 2026-04-28 08:47:58 UTC


README

Phalanx

Phalanx Argos

Part of the Phalanx async PHP framework.

Network discovery, probing, and device management as Phalanx tasks. Scan subnets, probe ports, wake machines, and discover services--all through the same scope-driven concurrency model as the rest of Phalanx.

Table of Contents

Installation

composer require phalanx/argos

Note

Requires PHP 8.4 or later.

Dependencies: phalanx/aegis, mlocati/ip-lib, react/datagram, react/socket, react/dns, and react/child-process.

Optional: clue/multicast-react, clue/mdns-react, clue/ssdp-react for mDNS and SSDP discovery.

Quick Start

<?php

use Phalanx\Application;
use Phalanx\Argos\NetworkServiceBundle;
use Phalanx\Argos\Task\ScanSubnet;
use Phalanx\Argos\Subnet;

[$app, $scope] = Application::starting()
    ->providers(new NetworkServiceBundle())
    ->compile()
    ->boot();

$hosts = $scope->execute(new ScanSubnet(
    Subnet::from('192.168.1.0/24'),
));

foreach ($hosts as $result) {
    if ($result->reachable) {
        echo "{$result->ip} is up ({$result->latencyMs}ms)\n";
    }
}

$scope->dispose();
$app->shutdown();

Subnet Addressing

Subnet wraps mlocati/ip-lib for CIDR range handling. It supports both IPv4 and IPv6 and exposes addresses as a lazy generator--iterating a /16 doesn't allocate 65,536 strings upfront.

<?php

use Phalanx\Argos\Subnet;

$net = Subnet::from('10.0.0.0/24');     // 256 addresses
$net = Subnet::from('fd00::/64');        // IPv6 works the same way

foreach ($net->addresses() as $ip) {
    // lazy -- yields one address at a time
}

Probe Strategies

ProbeStrategy is a factory that produces the right probe task for a given method. Swap scan strategies without changing calling code:

<?php

use Phalanx\Argos\ProbeStrategy;

// TCP connect probe on port 443 with 2s timeout
$probe = ProbeStrategy::tcp(port: 443, timeout: 2.0);

// UDP probe with a custom payload
$probe = ProbeStrategy::udp(port: 53, payload: "\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00");

// ICMP ping with 1s timeout
$probe = ProbeStrategy::ping(timeout: 1.0);

Pass a strategy to ScanSubnet to control how each host is probed:

<?php

use Phalanx\Argos\ProbeStrategy;
use Phalanx\Argos\Subnet;
use Phalanx\Argos\Task\ScanSubnet;

// Scan for web servers instead of pinging
$hosts = $scope->execute(new ScanSubnet(
    Subnet::from('192.168.1.0/24'),
    probe: ProbeStrategy::tcp(port: 80, timeout: 1.0),
    concurrency: 50,
));

Task Reference

All tasks live in the Phalanx\Argos\Task namespace. Each is an invokable class with serializable constructor args.

PingHost

ICMP ping via child process. Implements HasTimeout and Retryable.

<?php

use Phalanx\Argos\Task\PingHost;

$result = $scope->execute(new PingHost('192.168.1.1'));
// ProbeResult { ip: '192.168.1.1', reachable: true, latencyMs: 1.2, method: 'ping' }

ProbePort

TCP connect probe. Implements HasTimeout.

<?php

use Phalanx\Argos\Task\ProbePort;

$result = $scope->execute(new ProbePort('192.168.1.1', port: 22));
// ProbeResult { ip: '192.168.1.1', reachable: true, latencyMs: 3.4, method: 'tcp', port: 22 }

ProbeUdp

UDP probe with payload. Implements HasTimeout.

<?php

use Phalanx\Argos\Task\ProbeUdp;

$result = $scope->execute(new ProbeUdp('192.168.1.1', port: 53, payload: $dnsQuery));

WakeHost

Send a Wake-on-LAN magic packet via UDP broadcast.

<?php

use Phalanx\Argos\Task\WakeHost;

$scope->execute(new WakeHost(mac: '00:11:22:33:44:55'));

ScanSubnet

Scan a CIDR range with bounded concurrency via $scope->map().

<?php

use Phalanx\Argos\Subnet;
use Phalanx\Argos\Task\ScanSubnet;

$results = $scope->execute(new ScanSubnet(
    Subnet::from('10.0.0.0/24'),
    concurrency: 100,
));

ScanPorts

Scan multiple ports on a single host.

<?php

use Phalanx\Argos\Task\ScanPorts;

$results = $scope->execute(new ScanPorts(
    ip: '192.168.1.1',
    ports: [22, 80, 443, 3306, 5432, 8080],
));

WakeAndWait

Send a WOL packet, then retry-probe until the host comes up.

<?php

use Phalanx\Argos\Task\WakeAndWait;

$result = $scope->execute(new WakeAndWait(
    mac: '00:11:22:33:44:55',
    ip: '192.168.1.50',
));

IdentifyDevice

Concurrent ping + port scan to fingerprint a device.

<?php

use Phalanx\Argos\Task\IdentifyDevice;

$host = $scope->execute(new IdentifyDevice('192.168.1.1'));
// Host { ip, mac, hostname, services, metadata }

ResolveHostname

Async DNS resolution via react/dns.

<?php

use Phalanx\Argos\Task\ResolveHostname;

$ip = $scope->execute(new ResolveHostname('example.com'));

Discovery

Discovery tasks require optional dependencies. Install them as needed.

SSDP/UPnP Discovery

Requires clue/ssdp-react.

<?php

use Phalanx\Argos\Discovery\DiscoverSsdp;

$devices = $scope->execute(new DiscoverSsdp(timeout: 5.0));

mDNS/Zeroconf Discovery

Requires clue/mdns-react.

<?php

use Phalanx\Argos\Discovery\DiscoverMdns;

$services = $scope->execute(new DiscoverMdns(serviceType: '_http._tcp.local', timeout: 3.0));

Value Objects

ProbeResult -- readonly result from any probe task:

Property Type Description
ip string Target IP address
reachable bool Whether the host responded
latencyMs ?float Round-trip time in milliseconds
method string Probe method used (ping, tcp, udp)
port ?int Port probed (null for ICMP)
responseData ?string Raw response data (UDP probes)

Host -- readonly device identity:

Property Type Description
ip string IP address
mac ?string MAC address if resolved
hostname ?string Hostname if resolved
services array Open ports / detected services
metadata array Additional discovery data

Configuration

NetworkConfig controls defaults for all network tasks:

<?php

use Phalanx\Argos\NetworkConfig;
use Phalanx\Argos\NetworkServiceBundle;

$bundle = new NetworkServiceBundle(new NetworkConfig(
    defaultTimeout: 3.0,
    defaultConcurrency: 50,
    pingBinary: '/usr/bin/ping',
    broadcastAddress: '192.168.1.255',
    wolPort: 9,
));

NetworkServiceBundle registers DatagramFactory, Connector, and NetworkConfig into the service graph.