Skip to content

Commit eb75097

Browse files
author
ace411
committed
feat: modify extension internals
- instate operation error checks in php_mrloop_writev_cb and php_mrloop_readv_cb callbacks - register global TCP connection data buffer size - add connection data size and connection count parameters to tcpServer() function - duplicate client connection file descriptor in php_mrloop_tcp_server_recv callback - add vector count and offset parameters to addReadStream() function - add vector count parameter to addWriteStream() function - change DEFAULT_STREAM_BUFF_LEN and DEFAULT_CONN_BUFF_LEN values - define DEFAULT_VECTOR_COUNT, DEFAULT_READV_OFFSET and PHP_MRLOOP_MAX_TCP_CONNECTIONS
1 parent 12ed780 commit eb75097

File tree

7 files changed

+116
-26
lines changed

7 files changed

+116
-26
lines changed

README.md

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,21 @@ class Mrloop
4747
public addReadStream(
4848
resource $stream,
4949
?int $nbytes,
50+
?int $vcount,
51+
?int $offset,
5052
callable $callback,
5153
): void
5254
public addWriteStream(
5355
resource $stream,
5456
string $contents,
5557
callable $callback,
5658
): void
57-
public tcpServer(int $port, callable $callback): void
59+
public tcpServer(
60+
int $port,
61+
?int $connections,
62+
?int $nbytes,
63+
callable $callback,
64+
): void
5865
public writev(int|resource $fd, string $message): void
5966
public static parseHttpRequest(string $request, int $headerlimit = 100): iterable
6067
public static parseHttpResponse(string $response, int $headerlimit = 100): iterable
@@ -133,6 +140,8 @@ Hello, user
133140
public Mrloop::addReadStream(
134141
resource $stream,
135142
?int $nbytes,
143+
?int $vcount,
144+
?int $offset,
136145
callable $callback,
137146
): void
138147
```
@@ -144,7 +153,12 @@ Funnels file descriptor in readable stream into event loop and thence executes a
144153
- **stream** (resource) - A userspace-defined readable stream.
145154
> The file descriptor in the stream is internally given a non-blocking disposition.
146155
- **nbytes** (int|null) - The number of bytes to read.
147-
> Specifying `null` will condition the use of an 8KB buffer.
156+
> Specifying `null` will condition the use of a 1KB buffer.
157+
- **vcount** (int|null) - The number of read vectors to use.
158+
> Specifying `null` will condition the use of 2 vectors.
159+
> Any value north of `8` will likely result in an inefficient read.
160+
- **offset** (int|null) - The point at which to start the read operation.
161+
> Specifying `null` will condition the use of an offset of `0`.
148162
- **callback** (callable) - The binary function through which the file's contents and read result code are propagated.
149163

150164
**Return value(s)**
@@ -158,13 +172,15 @@ $loop = Mrloop::init();
158172

159173
$loop->addReadStream(
160174
$fd = \fopen('/path/to/file', 'r'),
161-
null,
175+
null, // 1024
176+
null, // 2
177+
null, // 0
162178
function (string $contents, int $res) use ($fd) {
163179
if ($res === 0) {
164180
echo \sprintf("%s\n", $contents);
165-
166-
\fclose($fd);
167181
}
182+
183+
\fclose($fd);
168184
},
169185
);
170186

@@ -184,6 +200,7 @@ File contents...
184200
public Mrloop::addWriteStream(
185201
resource $stream,
186202
string $contents,
203+
?int $vcount,
187204
callable $callback,
188205
): void
189206
```
@@ -195,6 +212,9 @@ Funnels file descriptor in writable stream into event loop and thence executes a
195212
- **stream** (resource) - A userspace-defined writable stream.
196213
> The file descriptor in the stream is internally given a non-blocking disposition.
197214
- **contents** (string) - The contents to write to the file descriptor.
215+
- **vcount** (int|null) - The number of write vectors to use.
216+
> Specifying `null` will condition the use of 2 vectors.
217+
> Any value north of `8` will likely result in an inefficient write.
198218
- **callback** (callable) - The unary function through which the number of written bytes is propagated.
199219

200220
**Return value(s)**
@@ -211,6 +231,7 @@ $file = '/path/to/file';
211231
$loop->addWriteStream(
212232
$fd = \fopen($file, 'w'),
213233
"file contents...\n",
234+
null,
214235
function (int $nbytes) use ($fd, $file) {
215236
echo \sprintf("Wrote %d bytes to %s\n", $nbytes, $file);
216237

@@ -231,14 +252,25 @@ Wrote 18 bytes to /path/to/file
231252
### `Mrloop::tcpServer`
232253

233254
```php
234-
public Mrloop::tcpServer(int $port, callable $callback): void
255+
public Mrloop::tcpServer(
256+
int $port,
257+
?int $connections,
258+
?int $nbytes,
259+
callable $callback,
260+
): void
235261
```
236262

237263
Instantiates a simple TCP server.
238264

239265
**Parameter(s)**
240266

241267
- **port** (int) - The port on which to listen for incoming connections.
268+
- **connections** (int|null) - The maximum number of connections to accept.
269+
> This parameter does not have any effect when a version of mrloop in which the `mr_tcp_server` function lacks the `max_conn` parameter is included in the compilation process.
270+
> Specifying `null` will condition the use of a `1024` connection threshold.
271+
- **nbytes** (int|null) - The maximum number of readable bytes for each connection.
272+
> This setting is akin to the `client_max_body_size` option in NGINX.
273+
> Specifying null will condition the use of an `8192` byte threshold.
242274
- **callback** (callable) - The binary function with which to define a response to a client.
243275
> Refer to the segment to follow for more information on the callback.
244276
- **Callback parameters**
@@ -259,6 +291,8 @@ $loop = Mrloop::init();
259291

260292
$loop->tcpServer(
261293
8080,
294+
null,
295+
null,
262296
function (string $message, iterable $client) {
263297
// print access log
264298
echo \sprintf(
@@ -311,6 +345,7 @@ $loop = Mrloop::init();
311345

312346
$loop->tcpServer(
313347
8080,
348+
null,
314349
function (string $message, iterable $client) use ($loop) {
315350
[
316351
'client_addr' => $addr,

mrloop_arginfo.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ ZEND_ARG_TYPE_INFO(0, interval, IS_DOUBLE, 0)
1818
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
1919
ZEND_END_ARG_INFO()
2020

21-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_tcpServer, 0, 0, 2)
21+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_tcpServer, 0, 0, 4)
2222
ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 0)
23+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, connections, IS_LONG, 0, "null")
24+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nbytes, IS_LONG, 0, "null")
2325
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
2426
ZEND_END_ARG_INFO()
2527

@@ -38,15 +40,18 @@ ZEND_ARG_TYPE_INFO(0, signal, IS_LONG, 0)
3840
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
3941
ZEND_END_ARG_INFO()
4042

41-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_addReadStream, 0, 0, 3)
43+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_addReadStream, 0, 0, 5)
4244
ZEND_ARG_TYPE_INFO(0, stream, IS_RESOURCE, 0)
4345
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nbytes, IS_LONG, 0, "null")
46+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, vcount, IS_LONG, 0, "null")
47+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "null")
4448
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
4549
ZEND_END_ARG_INFO()
4650

47-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_addWriteStream, 0, 0, 3)
51+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_addWriteStream, 0, 0, 4)
4852
ZEND_ARG_TYPE_INFO(0, stream, IS_RESOURCE, 0)
4953
ZEND_ARG_TYPE_INFO(0, contents, IS_STRING, 0)
54+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, vcount, IS_LONG, 0, "null")
5055
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
5156
ZEND_END_ARG_INFO()
5257

src/loop.c

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ static void php_mrloop_add_future_tick(INTERNAL_FUNCTION_PARAMETERS)
192192

193193
static void php_mrloop_readv_cb(void *data, int res)
194194
{
195+
if (res < 0)
196+
{
197+
PHP_MRLOOP_THROW(strerror(-res));
198+
}
199+
195200
php_mrloop_cb_t *cb;
196201
php_iovec_t *iov;
197202
zval args[2], result;
@@ -222,6 +227,11 @@ static void php_mrloop_readv_cb(void *data, int res)
222227
}
223228
static void php_mrloop_writev_cb(void *data, int res)
224229
{
230+
if (res < 0)
231+
{
232+
PHP_MRLOOP_THROW(strerror(-res));
233+
}
234+
225235
php_mrloop_cb_t *cb = (php_mrloop_cb_t *)data;
226236
zval args[1], result;
227237
ZVAL_LONG(&args[0], res);
@@ -251,8 +261,10 @@ static void *php_mrloop_tcp_client_setup(int fd, char **buffer, int *bsize)
251261

252262
conn = emalloc(sizeof(php_mrloop_conn_t));
253263
conn->fd = fd;
264+
conn->buffer = emalloc(MRLOOP_G(tcp_buff_size));
254265
*buffer = conn->buffer;
255-
*bsize = DEFAULT_CONN_BUFF_LEN;
266+
// *bsize = DEFAULT_CONN_BUFF_LEN;
267+
*bsize = MRLOOP_G(tcp_buff_size);
256268

257269
socklen = sizeof(php_sockaddr_t);
258270

@@ -277,6 +289,7 @@ static int php_mrloop_tcp_server_recv(void *conn, int fd, ssize_t nbytes, char *
277289
{
278290
mr_close(loop, client->fd);
279291
efree(client->addr);
292+
efree(client->buffer);
280293
efree(client);
281294

282295
return 1;
@@ -288,7 +301,7 @@ static int php_mrloop_tcp_server_recv(void *conn, int fd, ssize_t nbytes, char *
288301
array_init(&args[1]);
289302
add_assoc_string(&args[1], "client_addr", (char *)client->addr);
290303
add_assoc_long(&args[1], "client_port", client->port);
291-
add_assoc_long(&args[1], "client_fd", client->fd);
304+
add_assoc_long(&args[1], "client_fd", dup(client->fd));
292305

293306
MRLOOP_G(tcp_cb)->fci.retval = &result;
294307
MRLOOP_G(tcp_cb)->fci.param_count = 2;
@@ -321,24 +334,40 @@ static void php_mrloop_tcp_server_listen(INTERNAL_FUNCTION_PARAMETERS)
321334
php_mrloop_t *this;
322335
zend_fcall_info fci;
323336
zend_fcall_info_cache fci_cache;
324-
zend_long port;
337+
zend_long port, max_conn, nbytes;
338+
bool max_conn_null, nbytes_null;
339+
size_t nconn, fnbytes;
325340

326341
obj = getThis();
327342
fci = empty_fcall_info;
328343
fci_cache = empty_fcall_info_cache;
344+
max_conn_null = true;
345+
nbytes_null = true;
329346

330-
ZEND_PARSE_PARAMETERS_START(2, 2)
347+
ZEND_PARSE_PARAMETERS_START(4, 4)
331348
Z_PARAM_LONG(port)
349+
Z_PARAM_LONG_OR_NULL(max_conn, max_conn_null)
350+
Z_PARAM_LONG_OR_NULL(nbytes, nbytes_null)
332351
Z_PARAM_FUNC(fci, fci_cache)
333352
ZEND_PARSE_PARAMETERS_END();
334353

335354
this = PHP_MRLOOP_OBJ(obj);
336355

356+
fnbytes = (size_t)(nbytes_null == true ? DEFAULT_CONN_BUFF_LEN : nbytes);
357+
MRLOOP_G(tcp_buff_size) = fnbytes;
358+
337359
MRLOOP_G(tcp_cb) = emalloc(sizeof(php_mrloop_cb_t));
338360
PHP_CB_TO_MRLOOP_CB(MRLOOP_G(tcp_cb), fci, fci_cache);
339361
MRLOOP_G(tcp_cb)->data = this->loop;
340362

363+
// LISTEN_EV
364+
nconn = (size_t)(max_conn_null == true ? PHP_MRLOOP_MAX_TCP_CONNECTIONS : (max_conn == 0 ? PHP_MRLOOP_MAX_TCP_CONNECTIONS : max_conn));
365+
366+
#ifdef MRLOOP_H
367+
mr_tcp_server(this->loop, (int)port, nconn, php_mrloop_tcp_client_setup, php_mrloop_tcp_server_recv);
368+
#else
341369
mr_tcp_server(this->loop, (int)port, php_mrloop_tcp_client_setup, php_mrloop_tcp_server_recv);
370+
#endif
342371

343372
return;
344373
}
@@ -528,21 +557,25 @@ static void php_mrloop_add_read_stream(INTERNAL_FUNCTION_PARAMETERS)
528557
php_iovec_t *iov;
529558
zend_fcall_info fci;
530559
zend_fcall_info_cache fci_cache;
531-
zend_long nbytes;
532-
bool nbytes_null;
560+
zend_long nbytes, vcount, offset;
561+
bool nbytes_null, vcount_null, offset_null;
533562
int fd; // php_socket_t fd;
534563
php_stream *stream;
535-
size_t fnbytes;
564+
size_t fnbytes, fvcount, foffset;
536565

537566
obj = getThis();
538567
nbytes_null = true;
568+
vcount_null = true;
569+
offset_null = true;
539570
fci = empty_fcall_info;
540571
fci_cache = empty_fcall_info_cache;
541572
fd = -1;
542573

543-
ZEND_PARSE_PARAMETERS_START(3, 3)
574+
ZEND_PARSE_PARAMETERS_START(5, 5)
544575
Z_PARAM_RESOURCE(res)
545576
Z_PARAM_LONG_OR_NULL(nbytes, nbytes_null)
577+
Z_PARAM_LONG_OR_NULL(vcount, vcount_null)
578+
Z_PARAM_LONG_OR_NULL(offset, offset_null)
546579
Z_PARAM_FUNC(fci, fci_cache)
547580
ZEND_PARSE_PARAMETERS_END();
548581

@@ -552,6 +585,8 @@ static void php_mrloop_add_read_stream(INTERNAL_FUNCTION_PARAMETERS)
552585
PHP_STREAM_TO_FD(stream, res, fd);
553586

554587
fnbytes = (size_t)(nbytes_null == true ? DEFAULT_STREAM_BUFF_LEN : nbytes);
588+
fvcount = (size_t)(vcount_null == true ? DEFAULT_VECTOR_COUNT : vcount);
589+
foffset = (size_t)(offset_null == true ? DEFAULT_READV_OFFSET : offset);
555590

556591
iov = emalloc(sizeof(php_iovec_t));
557592
iov->iov_base = emalloc(fnbytes);
@@ -562,7 +597,7 @@ static void php_mrloop_add_read_stream(INTERNAL_FUNCTION_PARAMETERS)
562597

563598
cb->data = iov;
564599

565-
mr_readvcb(this->loop, fd, iov, 1, 0, cb, php_mrloop_readv_cb);
600+
mr_readvcb(this->loop, fd, iov, fvcount, foffset, cb, php_mrloop_readv_cb);
566601
mr_flush(this->loop);
567602

568603
return;
@@ -576,18 +611,22 @@ static void php_mrloop_add_write_stream(INTERNAL_FUNCTION_PARAMETERS)
576611
php_iovec_t *iov;
577612
zend_fcall_info fci;
578613
zend_fcall_info_cache fci_cache;
614+
zend_long vcount;
615+
bool vcount_null;
579616
int fd;
580617
php_stream *stream;
581-
size_t nbytes;
618+
size_t nbytes, fvcount;
582619

583620
obj = getThis();
584621
fci = empty_fcall_info;
585622
fci_cache = empty_fcall_info_cache;
586623
fd = -1;
624+
vcount_null = true;
587625

588-
ZEND_PARSE_PARAMETERS_START(3, 3)
626+
ZEND_PARSE_PARAMETERS_START(4, 4)
589627
Z_PARAM_RESOURCE(res)
590628
Z_PARAM_STR(contents)
629+
Z_PARAM_LONG_OR_NULL(vcount, vcount_null)
591630
Z_PARAM_FUNC(fci, fci_cache)
592631
ZEND_PARSE_PARAMETERS_END();
593632

@@ -607,7 +646,9 @@ static void php_mrloop_add_write_stream(INTERNAL_FUNCTION_PARAMETERS)
607646

608647
cb->data = iov;
609648

610-
mr_writevcb(this->loop, fd, iov, 1, cb, php_mrloop_writev_cb);
649+
fvcount = (size_t)(vcount_null == true ? DEFAULT_VECTOR_COUNT : vcount);
650+
651+
mr_writevcb(this->loop, fd, iov, fvcount, cb, php_mrloop_writev_cb);
611652
mr_flush(this->loop);
612653

613654
return;
@@ -642,7 +683,7 @@ static void php_mrloop_writev(INTERNAL_FUNCTION_PARAMETERS)
642683

643684
if (fcntl(fd, F_GETFD) < 0)
644685
{
645-
PHP_MRLOOP_THROW("Detected invalid file descriptor");
686+
PHP_MRLOOP_THROW(strerror(errno));
646687
mr_stop(this->loop);
647688

648689
return;

src/loop.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@
2323
ZEND_PARSE_PARAMETERS_END()
2424
#endif
2525

26-
#define DEFAULT_STREAM_BUFF_LEN 8192
27-
#define DEFAULT_CONN_BUFF_LEN 65536
26+
#define DEFAULT_STREAM_BUFF_LEN 1024
27+
#define DEFAULT_CONN_BUFF_LEN 8132
2828
#define DEFAULT_HTTP_HEADER_LIMIT 100
29+
#define DEFAULT_VECTOR_COUNT 2
30+
#define DEFAULT_READV_OFFSET 0
2931
#define PHP_MRLOOP_TIMER 1
3032
#define PHP_MRLOOP_PERIODIC_TIMER 2
3133
#define PHP_MRLOOP_FUTURE_TICK 3
34+
#define PHP_MRLOOP_MAX_TCP_CONNECTIONS 1024
3235

3336
struct php_mrloop_t;
3437
struct php_mrloop_cb_t;
@@ -60,7 +63,8 @@ struct php_mrloop_conn_t
6063
/* client socket address */
6164
char *addr;
6265
/* data sent over client socket */
63-
char buffer[DEFAULT_CONN_BUFF_LEN];
66+
char *buffer;
67+
// char buffer[DEFAULT_CONN_BUFF_LEN];
6468
/* client socket port */
6569
size_t port;
6670
/* scatter-gather I/O primitives */
@@ -97,6 +101,8 @@ php_mrloop_cb_t *tcp_cb;
97101
php_mrloop_cb_t *sig_cb[3];
98102
/* signal callback count */
99103
size_t sigc;
104+
/* TCP buffer size */
105+
size_t tcp_buff_size;
100106
ZEND_END_MODULE_GLOBALS(mrloop)
101107
/* }}} */
102108

0 commit comments

Comments
 (0)