UdpConnection.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <?php
  2. /**
  3. * This file is part of workerman.
  4. *
  5. * Licensed under The MIT License
  6. * For full copyright and license information, please see the MIT-LICENSE.txt
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @author walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Workerman\Connection;
  15. use JetBrains\PhpStorm\ArrayShape;
  16. use JsonSerializable;
  17. use Workerman\Protocols\ProtocolInterface;
  18. use function stream_socket_get_name;
  19. use function stream_socket_sendto;
  20. use function strlen;
  21. use function strrchr;
  22. use function strrpos;
  23. use function substr;
  24. use function trim;
  25. /**
  26. * UdpConnection.
  27. */
  28. class UdpConnection extends ConnectionInterface implements JsonSerializable
  29. {
  30. /**
  31. * Transport layer protocol.
  32. *
  33. * @var string
  34. */
  35. public string $transport = 'udp';
  36. /**
  37. * Udp socket.
  38. *
  39. * @var resource
  40. */
  41. protected $socket;
  42. /**
  43. * Remote address.
  44. *
  45. * @var string
  46. */
  47. protected string $remoteAddress = '';
  48. /**
  49. * Construct.
  50. *
  51. * @param resource $socket
  52. * @param string $remoteAddress
  53. */
  54. public function __construct($socket, string $remoteAddress)
  55. {
  56. $this->socket = $socket;
  57. $this->remoteAddress = $remoteAddress;
  58. }
  59. /**
  60. * Sends data on the connection.
  61. *
  62. * @param mixed $sendBuffer
  63. * @param bool $raw
  64. * @return void|boolean
  65. */
  66. public function send(mixed $sendBuffer, bool $raw = false)
  67. {
  68. if (false === $raw && $this->protocol) {
  69. /** @var ProtocolInterface $parser */
  70. $parser = $this->protocol;
  71. $sendBuffer = $parser::encode($sendBuffer, $this);
  72. if ($sendBuffer === '') {
  73. return;
  74. }
  75. }
  76. return strlen($sendBuffer) === stream_socket_sendto($this->socket, $sendBuffer, 0, $this->isIpV6() ? '[' . $this->getRemoteIp() . ']:' . $this->getRemotePort() : $this->remoteAddress);
  77. }
  78. /**
  79. * Get remote IP.
  80. *
  81. * @return string
  82. */
  83. public function getRemoteIp(): string
  84. {
  85. $pos = strrpos($this->remoteAddress, ':');
  86. if ($pos) {
  87. return trim(substr($this->remoteAddress, 0, $pos), '[]');
  88. }
  89. return '';
  90. }
  91. /**
  92. * Get remote port.
  93. *
  94. * @return int
  95. */
  96. public function getRemotePort(): int
  97. {
  98. if ($this->remoteAddress) {
  99. return (int)substr(strrchr($this->remoteAddress, ':'), 1);
  100. }
  101. return 0;
  102. }
  103. /**
  104. * Get remote address.
  105. *
  106. * @return string
  107. */
  108. public function getRemoteAddress(): string
  109. {
  110. return $this->remoteAddress;
  111. }
  112. /**
  113. * Get local IP.
  114. *
  115. * @return string
  116. */
  117. public function getLocalIp(): string
  118. {
  119. $address = $this->getLocalAddress();
  120. $pos = strrpos($address, ':');
  121. if (!$pos) {
  122. return '';
  123. }
  124. return substr($address, 0, $pos);
  125. }
  126. /**
  127. * Get local port.
  128. *
  129. * @return int
  130. */
  131. public function getLocalPort(): int
  132. {
  133. $address = $this->getLocalAddress();
  134. $pos = strrpos($address, ':');
  135. if (!$pos) {
  136. return 0;
  137. }
  138. return (int)substr(strrchr($address, ':'), 1);
  139. }
  140. /**
  141. * Get local address.
  142. *
  143. * @return string
  144. */
  145. public function getLocalAddress(): string
  146. {
  147. return (string)@stream_socket_get_name($this->socket, false);
  148. }
  149. /**
  150. * Close connection.
  151. *
  152. * @param mixed|null $data
  153. * @return void
  154. */
  155. public function close(mixed $data = null, bool $raw = false)
  156. {
  157. if ($data !== null) {
  158. $this->send($data, $raw);
  159. }
  160. $this->eventLoop = $this->errorHandler = null;
  161. }
  162. /**
  163. * Get the real socket.
  164. *
  165. * @return resource
  166. */
  167. public function getSocket()
  168. {
  169. return $this->socket;
  170. }
  171. /**
  172. * Get the json_encode information.
  173. *
  174. * @return array
  175. */
  176. #[ArrayShape(['transport' => "string", 'getRemoteIp' => "string", 'remotePort' => "int", 'getRemoteAddress' => "string", 'getLocalIp' => "string", 'getLocalPort' => "int", 'getLocalAddress' => "string", 'isIpV4' => "bool", 'isIpV6' => "bool"])] public function jsonSerialize(): array
  177. {
  178. return [
  179. 'transport' => $this->transport,
  180. 'getRemoteIp' => $this->getRemoteIp(),
  181. 'remotePort' => $this->getRemotePort(),
  182. 'getRemoteAddress' => $this->getRemoteAddress(),
  183. 'getLocalIp' => $this->getLocalIp(),
  184. 'getLocalPort' => $this->getLocalPort(),
  185. 'getLocalAddress' => $this->getLocalAddress(),
  186. 'isIpV4' => $this->isIpV4(),
  187. 'isIpV6' => $this->isIpV6(),
  188. ];
  189. }
  190. }