forked from reactphp/socket
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSocketServer.php
More file actions
133 lines (114 loc) · 4.26 KB
/
SocketServer.php
File metadata and controls
133 lines (114 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
namespace React\Socket;
use Evenement\EventEmitter;
use React\EventLoop\LoopInterface;
final class SocketServer extends EventEmitter implements ServerInterface
{
private $server;
/**
* The `SocketServer` class is the main class in this package that implements the `ServerInterface` and
* allows you to accept incoming streaming connections, such as plaintext TCP/IP or secure TLS connection streams.
*
* ```php
* $socket = new React\Socket\SocketServer('127.0.0.1:0');
* $socket = new React\Socket\SocketServer('127.0.0.1:8000');
* $socket = new React\Socket\SocketServer('127.0.0.1:8000', $context);
* ```
*
* This class takes an optional `LoopInterface|null $loop` parameter that can be used to
* pass the event loop instance to use for this object. You can use a `null` value
* here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
* This value SHOULD NOT be given unless you're sure you want to explicitly use a
* given event loop instance.
*
* @param string $uri
* @param array $context
* @param ?LoopInterface $loop
* @throws \InvalidArgumentException if the listening address is invalid
* @throws \RuntimeException if listening on this address fails (already in use etc.)
*/
public function __construct($uri, array $context = array(), LoopInterface $loop = null)
{
// apply default options if not explicitly given
$context += array(
'tcp' => array(),
'tls' => array(),
'unix' => array()
);
$scheme = 'tcp';
$pos = \strpos($uri, '://');
if ($pos !== false) {
$scheme = \substr($uri, 0, $pos);
}
if ($scheme === 'unix') {
$server = new UnixServer($uri, $loop, $context['unix']);
} else {
if (preg_match('#^(?:\w+://)?\d+$#', $uri)) {
throw new \InvalidArgumentException('Invalid URI given');
}
$server = new TcpServer(str_replace('tls://', '', $uri), $loop, $context['tcp']);
if ($scheme === 'tls') {
$server = new SecureServer($server, $loop, $context['tls']);
}
}
$this->server = $server;
$that = $this;
$server->on('connection', function (ConnectionInterface $conn) use ($that) {
$that->emit('connection', array($conn));
});
$server->on('error', function (\Exception $error) use ($that) {
$that->emit('error', array($error));
});
}
public function getAddress()
{
return $this->server->getAddress();
}
public function pause()
{
$this->server->pause();
}
public function resume()
{
$this->server->resume();
}
public function close()
{
$this->server->close();
}
/**
* [internal] Internal helper method to accept new connection from given server socket
*
* @param resource $socket server socket to accept connection from
* @return resource new client socket if any
* @throws \RuntimeException if accepting fails
* @internal
*/
public static function accept($socket)
{
$newSocket = @\stream_socket_accept($socket, 0);
if (false === $newSocket) {
// Match errstr from PHP's warning message.
// stream_socket_accept(): accept failed: Connection timed out
$error = \error_get_last();
$errstr = \preg_replace('#.*: #', '', $error['message']);
// Go through list of possible error constants to find matching errno.
// @codeCoverageIgnoreStart
$errno = 0;
if (\function_exists('socket_strerror')) {
foreach (\get_defined_constants(false) as $name => $value) {
if (\strpos($name, 'SOCKET_E') === 0 && \socket_strerror($value) === $errstr) {
$errno = $value;
break;
}
}
}
// @codeCoverageIgnoreEnd
throw new \RuntimeException(
'Unable to accept new connection: ' . $errstr,
$errno
);
}
return $newSocket;
}
}