@@ -34,6 +34,10 @@ class AccountingServer extends EventEmitter implements ServerInterface
34
34
private $ server ;
35
35
private $ limit ;
36
36
37
+ private $ pauseOnLimit = false ;
38
+ private $ autoPaused = false ;
39
+ private $ manuPaused = false ;
40
+
37
41
/**
38
42
* Instantiates a new AccountingServer.
39
43
*
@@ -42,13 +46,48 @@ class AccountingServer extends EventEmitter implements ServerInterface
42
46
* is exceeded. In this case, it will emit an `error` event to inform about
43
47
* this and no `connection` event will be emitted.
44
48
*
49
+ * ```php
50
+ * $server = new AccountingServer($server, 50);
51
+ * $server->on('connection', function (ConnectionInterface $connection) {
52
+ * $connection->write('hello there!' . PHP_EOL);
53
+ * …
54
+ * });
55
+ * ```
56
+ *
57
+ * You can optionally configure the server to pause accepting new
58
+ * connections once the connection limit is reached. In this case, it will
59
+ * pause the underlying server and no longer process any new connections at
60
+ * all, thus also no longer closing any excessive connections.
61
+ * The underlying operating system is responsible for keeping a backlog of
62
+ * pending connections until its limit is reached, at which point it will
63
+ * start rejecting further connections.
64
+ * Once the server is below the connection limit, it will continue consuming
65
+ * connections from the backlog and will process any outstanding data on
66
+ * each connection.
67
+ * This mode may be useful for some protocols that are designed to wait for
68
+ * a response message (such as HTTP), but may be less useful for other
69
+ * protocols that demand immediate responses (such as a "welcome" message in
70
+ * an interactive chat).
71
+ *
72
+ * ```php
73
+ * $server = new AccountingServer($server, 50, true);
74
+ * $server->on('connection', function (ConnectionInterface $connection) {
75
+ * $connection->write('hello there!' . PHP_EOL);
76
+ * …
77
+ * });
78
+ * ```
79
+ *
45
80
* @param ServerInterface $server
46
81
* @param null|int $connectionLimit
82
+ * @param bool $pauseOnLimit
47
83
*/
48
- public function __construct (ServerInterface $ server , $ connectionLimit = null )
84
+ public function __construct (ServerInterface $ server , $ connectionLimit = null , $ pauseOnLimit = false )
49
85
{
50
86
$ this ->server = $ server ;
51
87
$ this ->limit = $ connectionLimit ;
88
+ if ($ connectionLimit !== null ) {
89
+ $ this ->pauseOnLimit = $ pauseOnLimit ;
90
+ }
52
91
53
92
$ this ->server ->on ('connection ' , array ($ this , 'handleConnection ' ));
54
93
$ this ->server ->on ('error ' , array ($ this , 'handleError ' ));
@@ -77,12 +116,24 @@ public function getAddress()
77
116
78
117
public function pause ()
79
118
{
80
- $ this ->server ->pause ();
119
+ if (!$ this ->manuPaused ) {
120
+ $ this ->manuPaused = true ;
121
+
122
+ if (!$ this ->autoPaused ) {
123
+ $ this ->server ->pause ();
124
+ }
125
+ }
81
126
}
82
127
83
128
public function resume ()
84
129
{
85
- $ this ->server ->resume ();
130
+ if ($ this ->manuPaused ) {
131
+ $ this ->manuPaused = false ;
132
+
133
+ if (!$ this ->autoPaused ) {
134
+ $ this ->server ->resume ();
135
+ }
136
+ }
86
137
}
87
138
88
139
public function close ()
@@ -93,7 +144,7 @@ public function close()
93
144
/** @internal */
94
145
public function handleConnection (ConnectionInterface $ connection )
95
146
{
96
- // close connection is limit exceeded
147
+ // close connection if limit exceeded
97
148
if ($ this ->limit !== null && count ($ this ->connections ) >= $ this ->limit ) {
98
149
$ this ->handleError (new \OverflowException ('Connection closed because server reached connection limit ' ));
99
150
$ connection ->close ();
@@ -106,13 +157,31 @@ public function handleConnection(ConnectionInterface $connection)
106
157
$ that ->handleDisconnection ($ connection );
107
158
});
108
159
160
+ // pause accepting new connections if limit exceeded
161
+ if ($ this ->pauseOnLimit && !$ this ->autoPaused && count ($ this ->connections ) >= $ this ->limit ) {
162
+ $ this ->autoPaused = true ;
163
+
164
+ if (!$ this ->manuPaused ) {
165
+ $ this ->server ->pause ();
166
+ }
167
+ }
168
+
109
169
$ this ->emit ('connection ' , array ($ connection ));
110
170
}
111
171
112
172
/** @internal */
113
173
public function handleDisconnection (ConnectionInterface $ connection )
114
174
{
115
175
unset($ this ->connections [array_search ($ connection , $ this ->connections )]);
176
+
177
+ // continue accepting new connection if below limit
178
+ if ($ this ->autoPaused && count ($ this ->connections ) < $ this ->limit ) {
179
+ $ this ->autoPaused = false ;
180
+
181
+ if (!$ this ->manuPaused ) {
182
+ $ this ->server ->resume ();
183
+ }
184
+ }
116
185
}
117
186
118
187
/** @internal */
0 commit comments