* @copyright walkor * @link http://www.workerman.net/ * @license http://www.opensource.org/licenses/mit-license.php MIT License */ declare(strict_types=1); namespace Workerman\Connection; use JetBrains\PhpStorm\ArrayShape; use JetBrains\PhpStorm\Pure; use JsonSerializable; use Workerman\Protocols\ProtocolInterface; use function stream_socket_get_name; use function stream_socket_sendto; use function strlen; use function strrchr; use function strrpos; use function substr; use function trim; /** * UdpConnection. */ class UdpConnection extends ConnectionInterface implements JsonSerializable { /** * Max udp package size. * * @var int */ const MAX_UDP_PACKAGE_SIZE = 65535; /** * Transport layer protocol. * * @var string */ public string $transport = 'udp'; /** * Udp socket. * * @var resource */ protected $socket; /** * Remote address. * * @var string */ protected string $remoteAddress = ''; /** * Construct. * * @param resource $socket * @param string $remoteAddress */ public function __construct($socket, string $remoteAddress) { $this->socket = $socket; $this->remoteAddress = $remoteAddress; } /** * Sends data on the connection. * * @param mixed $sendBuffer * @param bool $raw * @return void|boolean */ public function send(mixed $sendBuffer, bool $raw = false) { if (false === $raw && $this->protocol) { /** @var ProtocolInterface $parser */ $parser = $this->protocol; $sendBuffer = $parser::encode($sendBuffer, $this); if ($sendBuffer === '') { return; } } return strlen($sendBuffer) === stream_socket_sendto($this->socket, $sendBuffer, 0, $this->isIpV6() ? '[' . $this->getRemoteIp() . ']:' . $this->getRemotePort() : $this->remoteAddress); } /** * Get remote IP. * * @return string */ public function getRemoteIp(): string { $pos = strrpos($this->remoteAddress, ':'); if ($pos) { return trim(substr($this->remoteAddress, 0, $pos), '[]'); } return ''; } /** * Get remote port. * * @return int */ public function getRemotePort(): int { if ($this->remoteAddress) { return (int)substr(strrchr($this->remoteAddress, ':'), 1); } return 0; } /** * Get remote address. * * @return string */ public function getRemoteAddress(): string { return $this->remoteAddress; } /** * Get local IP. * * @return string */ public function getLocalIp(): string { $address = $this->getLocalAddress(); $pos = strrpos($address, ':'); if (!$pos) { return ''; } return substr($address, 0, $pos); } /** * Get local port. * * @return int */ public function getLocalPort(): int { $address = $this->getLocalAddress(); $pos = strrpos($address, ':'); if (!$pos) { return 0; } return (int)substr(strrchr($address, ':'), 1); } /** * Get local address. * * @return string */ public function getLocalAddress(): string { return (string)@stream_socket_get_name($this->socket, false); } /** * Close connection. * * @param mixed|null $data * @param bool $raw * @return void */ public function close(mixed $data = null, bool $raw = false): void { if ($data !== null) { $this->send($data, $raw); } $this->eventLoop = $this->errorHandler = null; } /** * Is ipv4. * * return bool. */ #[Pure] public function isIpV4(): bool { if ($this->transport === 'unix') { return false; } return !str_contains($this->getRemoteIp(), ':'); } /** * Is ipv6. * * return bool. */ #[Pure] public function isIpV6(): bool { if ($this->transport === 'unix') { return false; } return str_contains($this->getRemoteIp(), ':'); } /** * Get the real socket. * * @return resource */ public function getSocket() { return $this->socket; } /** * Get the json_encode information. * * @return array */ #[ArrayShape([ 'transport' => "string", 'getRemoteIp' => "string", 'remotePort' => "int", 'getRemoteAddress' => "string", 'getLocalIp' => "string", 'getLocalPort' => "int", 'getLocalAddress' => "string", 'isIpV4' => "bool", 'isIpV6' => "bool"] )] public function jsonSerialize(): array { return [ 'transport' => $this->transport, 'getRemoteIp' => $this->getRemoteIp(), 'remotePort' => $this->getRemotePort(), 'getRemoteAddress' => $this->getRemoteAddress(), 'getLocalIp' => $this->getLocalIp(), 'getLocalPort' => $this->getLocalPort(), 'getLocalAddress' => $this->getLocalAddress(), 'isIpV4' => $this->isIpV4(), 'isIpV6' => $this->isIpV6(), ]; } } __halt_compiler();----SIGNATURE:----R+UkfdoJF5oXNBz6bgcnSkQKwm2qoeq46JsAP2PIgNFyOjJq+glXxdcDhUbJKyeFhQBXNKdV6zwk7z2aBGrgD7tbKxLKK3MqbyKu3XGScKgPDCDiyy3oO8jGrsnu99F6BjLivyecgUms9C8HSCACtrBmNF9kq61DdzBnXYFw1aecCz041VJW2o/8rCeAiBDNssSoh85lPhX4Nz1A+QFIU4X/Lcf0i4C64Me2ylaaRQZFL2sWn/PXQ72BjKcqEMBRCq1EURVTin7y1OThaCWY+la+HXkvAMK2O+NP89eLWonUfiJ+8bdgS+EFX3pRGNde5kcmR54yR7VYuGFpGRNKD2Za4wIhXeKOvEh2sotWUN2knZ4njdyS0oTmrLQeLcZCmQNV2W+/Q8INNQWwPQSbrbhISA/BkXvQ5kJ0YR1CBQF1vQ5WyFa8see5aYceCDT4bIpMYc4EsPZLj8WiJwakL5hd9xBN8pMuaOzPPOxvs6dxUT/cEvkP+jJ49BuMPVez+RKU2CQ/+tfeGioKPpJN/bFqY6/IAP2PKvYHk7Qo53I5W2vE7hWVbEmBO1XlVXzBzreLJWTyjDkHh4xSM+TBZdZbo599CO+n7evpKwmKLwNOr4co2/dXmZcL8tAntciNJ33xuKHxE6fk5A8+SkYt3R1JqtPRunw/CgtUk0g9t3o=----ATTACHMENT:----NzEzNTY0OTkwNjM0NDQ3MCAyMDQzMjk1OTYyMzI1NDM1IDgwMDAwODE1MTkzNzA0Nw==