Page MenuHomeDevCentral

D3230.diff
No OneTemporary

D3230.diff

diff --git a/omnitools/src/Network/IP.php b/omnitools/src/Network/IP.php
--- a/omnitools/src/Network/IP.php
+++ b/omnitools/src/Network/IP.php
@@ -3,7 +3,13 @@
namespace Keruald\OmniTools\Network;
-class IP {
+use InvalidArgumentException;
+
+abstract class IP {
+
+ ///
+ /// Helper methods
+ ///
public static function isIP (string $ip) : bool {
return self::isIPv4($ip) || self::isIPv6($ip);
@@ -28,4 +34,26 @@
return false;
}
+ ///
+ /// Constructor
+ ///
+
+ public static function from (string $ip) : IP {
+ if (self::isIPv4($ip)) {
+ return new IPv4($ip);
+ }
+
+ if (self::isIPv6($ip)) {
+ $ipv6 = new IPv6($ip);
+ $ipv6->normalize();
+ return $ipv6;
+ }
+
+ throw new InvalidArgumentException;
+ }
+
+ public abstract function __toString () : string;
+
+ public abstract function getDomain () : int;
+
}
diff --git a/omnitools/src/Network/IPv4.php b/omnitools/src/Network/IPv4.php
new file mode 100644
--- /dev/null
+++ b/omnitools/src/Network/IPv4.php
@@ -0,0 +1,56 @@
+<?php
+declare(strict_types=1);
+
+namespace Keruald\OmniTools\Network;
+
+use InvalidArgumentException;
+
+class IPv4 extends IP {
+
+ ///
+ /// Constants
+ ///
+
+ const DOMAIN = 2; // AF_INET
+
+ ///
+ /// Properties
+ ///
+
+ private string $ip;
+
+ ///
+ /// Constructors
+ ///
+
+ public function __construct (string $ip) {
+ $this->ip = $ip;
+ }
+
+ public static function from (string $ip) : self {
+ $ipv4 = new self($ip);
+
+ if (!$ipv4->isValid()) {
+ throw new InvalidArgumentException("Address is not a valid IPv4.");
+ }
+
+ return $ipv4;
+ }
+
+ public function isValid () : bool {
+ return IP::isIPv4($this->ip);
+ }
+
+ public function getDomain () : int {
+ return self::DOMAIN; // AF_INET
+ }
+
+ ///
+ /// Magic methods
+ ///
+
+ public function __toString () : string {
+ return $this->ip;
+ }
+
+}
diff --git a/omnitools/src/Network/IPv6.php b/omnitools/src/Network/IPv6.php
--- a/omnitools/src/Network/IPv6.php
+++ b/omnitools/src/Network/IPv6.php
@@ -6,6 +6,16 @@
class IPv6 extends IP {
+ ///
+ /// Constants
+ ///
+
+ const DOMAIN = 10; // AF_INET6
+
+ ///
+ /// Properties
+ ///
+
/**
* @var string
*/
@@ -52,6 +62,10 @@
return IP::isIPv6($this->ip);
}
+ public function getDomain () : int {
+ return self::DOMAIN; // AF_INET6
+ }
+
public function increment (int $increment = 1) : self {
if ($increment === 0) {
return $this;
diff --git a/omnitools/src/Network/Port.php b/omnitools/src/Network/Port.php
new file mode 100644
--- /dev/null
+++ b/omnitools/src/Network/Port.php
@@ -0,0 +1,25 @@
+<?php
+declare(strict_types=1);
+
+namespace Keruald\OmniTools\Network;
+
+class Port {
+
+ ///
+ /// Properties
+ ///
+
+ public Protocol $protocol;
+
+ public int $number;
+
+ ///
+ /// Constructor
+ ///
+
+ public function __construct (int $number, Protocol $protocol = Protocol::TCP) {
+ $this->number = $number;
+ $this->protocol = $protocol;
+ }
+
+}
diff --git a/omnitools/src/Network/Protocol.php b/omnitools/src/Network/Protocol.php
new file mode 100644
--- /dev/null
+++ b/omnitools/src/Network/Protocol.php
@@ -0,0 +1,11 @@
+<?php
+declare(strict_types=1);
+
+namespace Keruald\OmniTools\Network;
+
+enum Protocol {
+ case TCP;
+ case UDP;
+ case SCTP;
+ case DCCP;
+}
diff --git a/omnitools/src/Network/SocketAddress.php b/omnitools/src/Network/SocketAddress.php
new file mode 100644
--- /dev/null
+++ b/omnitools/src/Network/SocketAddress.php
@@ -0,0 +1,93 @@
+<?php
+declare(strict_types=1);
+
+namespace Keruald\OmniTools\Network;
+
+use RuntimeException;
+
+class SocketAddress {
+
+ ///
+ /// Constants
+ ///
+
+ const DEFAULT_TIMEOUT = 10;
+
+ const PROTOCOL_TCP = 6; // getprotobyname("tcp")
+
+ ///
+ /// Properties
+ ///
+
+ public IP $address;
+
+ public Port $port;
+
+ ///
+ /// Constructors
+ ///
+
+ public function __construct (IP $address, Port $port) {
+ $this->address = $address;
+ $this->port = $port;
+ }
+
+ /**
+ * Gets new socket address from specified IP, port and protocol information.
+ *
+ * This method takes care to creates the underlying IP and Port object.
+ */
+ public static function from (
+ string $ip,
+ int $port, Protocol $protocol = Protocol::TCP
+ ) : self {
+ return new self(
+ IP::from($ip),
+ new Port($port, $protocol),
+ );
+ }
+
+ ///
+ /// Interact with socket
+ ///
+
+ /**
+ * Determines if a TCP socket is open
+ *
+ * @throws RuntimeException if the protocol isn't TCP
+ * @return bool if the TCP socket accepts a connection
+ */
+ public function isOpen() : bool {
+ if ($this->port->protocol !== Protocol::TCP) {
+ throw new RuntimeException("Check if a port is open is only implemented for TCP.");
+ }
+
+ if (!function_exists("socket_create")) {
+ return $this->isOpenLegacy();
+ }
+
+ $socket = socket_create($this->address->getDomain(), SOCK_STREAM, self::PROTOCOL_TCP);
+ $result = socket_connect($socket, $this->address->__toString(), $this->port->number);
+ socket_close($socket);
+
+ return $result;
+ }
+
+ private function isOpenLegacy () : bool {
+ $fp = @fsockopen(
+ $this->address->__toString(),
+ $this->port->number,
+ $errorCode, $errorMessage,
+ self::DEFAULT_TIMEOUT
+ );
+
+ if ($fp) {
+ fclose($fp);
+
+ return true;
+ }
+
+ return false;
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 23, 22:55 (15 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2259097
Default Alt Text
D3230.diff (5 KB)

Event Timeline