Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3767189
D3230.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
D3230.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D3230: Determine if a TCP port is open
Attached
Detach File
Event Timeline
Log In to Comment