Skip to content

Commit bf3ac27

Browse files
committed
feat: modify extension internals
- remove parseHttpRequest() and parseHttpResponse() functions - add php_strncpy() function - replace sprintf() with php_strncpy() - modify CI configuration
1 parent 8b3a6dc commit bf3ac27

File tree

11 files changed

+45
-508
lines changed

11 files changed

+45
-508
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,5 @@ jobs:
2424
run: |
2525
git clone https://github.com/markreedz/mrloop.git mrloop && \
2626
git clone https://github.com/axboe/liburing.git liburing && cd liburing && make && sudo make install && \
27-
cd ../ && git clone https://github.com/h2o/picohttpparser.git picohttp && \
28-
phpize && ./configure --with-mrloop="$(pwd)/mrloop" --with-picohttp="$(pwd)/picohttp" && \
29-
make && make test && cat $(ls | grep "php_test_results_" | head -1)
27+
cd ../ && phpize && ./configure --with-mrloop="$(pwd)/mrloop" && \
28+
make && make test

README.md

Lines changed: 1 addition & 227 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,16 @@ PHP has, in recent years, seen an emergence of eventware built atop potent multi
1212
- Linux Kernel 5.4.1 or newer
1313
- [mrloop](https://github.com/markreedz/mrloop)
1414
- [liburing](https://github.com/axboe/liburing)
15-
- [picohttpparser](https://github.com/h2o/picohttpparser)
1615

1716
## Installation
1817

1918
It is important to have all the aforelisted requirements at the ready before attempting to install `ext-mrloop`. The directives in the snippet to follow should allow you to build the extension's shared object file (`mrloop.so`).
2019

2120
```sh
2221
$ git clone https://github.com/ace411/mrloop.git <mrloop-dir>
23-
$ git clone https://github.com/h2o/picohttpparser.git <picohttp-dir>
2422
$ git clone https://github.com/ringphp/php-mrloop.git <dir>
2523
$ cd <dir>
26-
$ ./configure --with-mrloop=<mrloop-dir> --with-picohttp=<picohttp-dir>
24+
$ phpize && ./configure --with-mrloop=<mrloop-dir>
2725
$ make && sudo make install
2826
```
2927

@@ -64,8 +62,6 @@ class Mrloop
6462
callable $callback,
6563
): void
6664
public writev(int|resource $fd, string $message): void
67-
public static parseHttpRequest(string $request, int $headerlimit = 100): iterable
68-
public static parseHttpResponse(string $response, int $headerlimit = 100): iterable
6965
public addTimer(float $interval, callable $callback): void
7066
public addPeriodicTimer(float $interval, callable $callback): void
7167
public futureTick(callable $callback): void
@@ -80,8 +76,6 @@ class Mrloop
8076
- [`Mrloop::addWriteStream`](#mrloopaddwritestream)
8177
- [`Mrloop::tcpServer`](#mrlooptcpserver)
8278
- [`Mrloop::writev`](#mrloopwritev)
83-
- [`Mrloop::parseHttpRequest`](#mrloopparsehttprequest)
84-
- [`Mrloop::parseHttpResponse`](#mrloopparsehttpresponse)
8579
- [`Mrloop::addTimer`](#mrloopaddtimer)
8680
- [`Mrloop::addPeriodicTimer`](#mrloopaddperiodictimer)
8781
- [`Mrloop::futureTick`](#mrloopfuturetick)
@@ -378,226 +372,6 @@ Listening on port 8080
378372
379373
```
380374

381-
### `Mrloop::parseHttpRequest`
382-
383-
```php
384-
public static Mrloop::parseHttpRequest(
385-
string $request,
386-
int $headerlimit = 100,
387-
): iterable
388-
```
389-
390-
Parses an HTTP request.
391-
392-
> This is a function that utilizes the `picohttpparser` API.
393-
394-
**Parameter(s)**
395-
396-
- **request** (string) - The HTTP request to parse.
397-
- **headerlimit** (int) - The number of headers to parse.
398-
> The default limit is `100`.
399-
400-
**Return value(s)**
401-
402-
The parser will throw an exception in the event that an invalid HTTP request is encountered and will output a hashtable with the contents enumerated below otherwise.
403-
404-
- **body** (string) - The request body.
405-
- **headers** (iterable) - An associative array containing request headers.
406-
- **method** (string) - The request method.
407-
- **path** (string) - The request path.
408-
409-
```php
410-
use ringphp\Mrloop;
411-
412-
$loop = Mrloop::init();
413-
414-
$loop->tcpServer(
415-
8080,
416-
null,
417-
null,
418-
function (mixed ...$args) {
419-
[$message,] = $args;
420-
$response = static fn (
421-
string $message,
422-
int $code = 200,
423-
string $mime = 'text/plain',
424-
) =>
425-
\sprintf(
426-
"HTTP/1.1 %d %s\r\ncontent-type: %s\r\ncontent-length: %d\r\n\r\n%s\r\n",
427-
$code,
428-
($code === 200 ? 'OK' : 'Internal Server Error'),
429-
$mime,
430-
\strlen($message),
431-
$message,
432-
);
433-
434-
try {
435-
$request = Mrloop::parseHttpRequest($message);
436-
437-
return $response('Hello, user');
438-
} catch (\Throwable $err) {
439-
return $response(
440-
'HTTP parser error',
441-
500,
442-
);
443-
}
444-
},
445-
);
446-
447-
$loop->run();
448-
```
449-
450-
The example above will produce output similar to that in the snippet to follow.
451-
452-
```
453-
Listening on port 8080
454-
455-
```
456-
457-
### `Mrloop::parseHttpResponse`
458-
459-
```php
460-
public static Mrloop::parseHttpResponse(
461-
string $response,
462-
int $headerlimit = 100,
463-
): iterable
464-
```
465-
466-
Parses an HTTP response.
467-
468-
> This function also utilizes the `picohttpparser` API.
469-
470-
**Parameter(s)**
471-
472-
- **response** (string) - The HTTP response to parse.
473-
- **headerlimit** (int) - The number of headers to parse.
474-
> The default limit is `100`.
475-
476-
**Return value(s)**
477-
478-
The parser will throw an exception in the event that an invalid HTTP response is encountered and will output a hashtable with the contents enumerated below otherwise.
479-
480-
- **body** (string) - The response body.
481-
- **headers** (iterable) - An associative array containing response headers.
482-
- **status** (int) - The response status code.
483-
- **reason** (string) - The response reason phrase.
484-
485-
```php
486-
use ringphp\Mrloop;
487-
488-
$loop = Mrloop::init();
489-
490-
$loop->addWriteStream(
491-
$sock = \stream_socket_client('tcp://www.example.com:80'),
492-
"GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n",
493-
null,
494-
function ($nbytes) use ($loop, $sock) {
495-
$loop->addReadStream(
496-
$sock,
497-
null,
498-
null,
499-
null,
500-
function ($data, $res) use ($sock, $loop) {
501-
var_dump(Mrloop::parseHttpResponse($data));
502-
503-
\fclose($sock);
504-
},
505-
);
506-
},
507-
);
508-
509-
$loop->run();
510-
```
511-
512-
The example above will produce output similar to that in the snippet to follow.
513-
514-
```
515-
array(4) {
516-
["reason"]=>
517-
string(2) "OK"
518-
["status"]=>
519-
int(200)
520-
["body"]=>
521-
string(1256) "<!doctype html>
522-
<html>
523-
<head>
524-
<title>Example Domain</title>
525-
526-
<meta charset="utf-8" />
527-
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
528-
<meta name="viewport" content="width=device-width, initial-scale=1" />
529-
<style type="text/css">
530-
body {
531-
background-color: #f0f0f2;
532-
margin: 0;
533-
padding: 0;
534-
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
535-
536-
}
537-
div {
538-
width: 600px;
539-
margin: 5em auto;
540-
padding: 2em;
541-
background-color: #fdfdff;
542-
border-radius: 0.5em;
543-
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
544-
}
545-
a:link, a:visited {
546-
color: #38488f;
547-
text-decoration: none;
548-
}
549-
@media (max-width: 700px) {
550-
div {
551-
margin: 0 auto;
552-
width: auto;
553-
}
554-
}
555-
</style>
556-
</head>
557-
558-
<body>
559-
<div>
560-
<h1>Example Domain</h1>
561-
<p>This domain is for use in illustrative examples in documents. You may use this
562-
domain in literature without prior coordination or asking for permission.</p>
563-
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
564-
</div>
565-
</body>
566-
</html>
567-
"
568-
["headers"]=>
569-
array(13) {
570-
["Accept-Ranges"]=>
571-
string(5) "bytes"
572-
["Age"]=>
573-
string(6) "506325"
574-
["Cache-Control"]=>
575-
string(14) "max-age=604800"
576-
["Content-Type"]=>
577-
string(24) "text/html; charset=UTF-8"
578-
["Date"]=>
579-
string(29) "Wed, 30 Oct 2024 15:37:43 GMT"
580-
["Etag"]=>
581-
string(17) ""3147526947+gzip""
582-
["Expires"]=>
583-
string(29) "Wed, 06 Nov 2024 15:37:43 GMT"
584-
["Last-Modified"]=>
585-
string(29) "Thu, 17 Oct 2019 07:18:26 GMT"
586-
[""]=>
587-
string(16) "ECAcc (dcd/7D5A)"
588-
["Vary"]=>
589-
string(15) "Accept-Encoding"
590-
["X-Cache"]=>
591-
string(3) "HIT"
592-
["Content-Length"]=>
593-
string(4) "1256"
594-
["Connection"]=>
595-
string(5) "close"
596-
}
597-
}
598-
599-
```
600-
601375
### `Mrloop::addTimer`
602376

603377
```php

config.m4

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
dnl ext-mrloop config.m4 file
1+
dnl mrloop extension for PHP (c) 2024 Lochemem Bruno Michael
22

33
dnl PHP_ARG_ENABLE([mrloop],
44
dnl [for mrloop support],
@@ -11,12 +11,6 @@ PHP_ARG_WITH([mrloop],
1111
[specify path to mrloop library])],
1212
[no])
1313

14-
PHP_ARG_WITH([picohttp],
15-
[for picohttp library],
16-
[AS_HELP_STRING([--with-picohttp],
17-
[specify path to picohttp library])],
18-
[no])
19-
2014
if test "$PHP_MRLOOP" != "no"; then
2115
dnl add PHP version check
2216
PHP_VERSION=$($PHP_CONFIG --vernum)
@@ -51,15 +45,7 @@ if test "$PHP_MRLOOP" != "no"; then
5145
AC_MSG_ERROR(Please download mrloop)
5246
fi
5347

54-
AC_MSG_CHECKING([for picohttpparser package])
55-
if test -s "$PHP_PICOHTTP/picohttpparser.c"; then
56-
AC_MSG_RESULT(found picohttpparser package)
57-
else
58-
AC_MSG_RESULT(picohttpparser is not downloaded)
59-
AC_MSG_ERROR(Please download picohttpparser)
60-
fi
61-
62-
CFLAGS="-g -O3 -luring -I$PHP_MRLOOP/ -I$PHP_PICOHTTP/"
48+
CFLAGS="-g -O3 -luring -I$PHP_MRLOOP/"
6349
AC_DEFINE(HAVE_MRLOOP, 1, [ Have mrloop support ])
6450

6551
PHP_NEW_EXTENSION(mrloop, php_mrloop.c, $ext_shared)

mrloop_arginfo.h

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,6 @@ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nbytes, IS_LONG, 0, "null")
2525
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
2626
ZEND_END_ARG_INFO()
2727

28-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_parseHttpRequest, 0, 0, 2)
29-
ZEND_ARG_TYPE_INFO(0, request, IS_STRING, 0)
30-
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, header_limit, IS_LONG, 0, "100")
31-
ZEND_END_ARG_INFO()
32-
33-
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_parseHttpResponse, 0, 0, 2)
34-
ZEND_ARG_TYPE_INFO(0, response, IS_STRING, 0)
35-
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, header_limit, IS_LONG, 0, "100")
36-
ZEND_END_ARG_INFO()
37-
3828
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Mrloop_addSignal, 0, 0, 2)
3929
ZEND_ARG_TYPE_INFO(0, signal, IS_LONG, 0)
4030
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
@@ -70,11 +60,9 @@ ZEND_METHOD(Mrloop, run);
7060
ZEND_METHOD(Mrloop, addTimer);
7161
ZEND_METHOD(Mrloop, addPeriodicTimer);
7262
ZEND_METHOD(Mrloop, tcpServer);
73-
ZEND_METHOD(Mrloop, parseHttpRequest);
7463
ZEND_METHOD(Mrloop, addSignal);
7564
ZEND_METHOD(Mrloop, addReadStream);
7665
ZEND_METHOD(Mrloop, addWriteStream);
77-
ZEND_METHOD(Mrloop, parseHttpResponse);
7866
ZEND_METHOD(Mrloop, writev);
7967
ZEND_METHOD(Mrloop, futureTick);
8068

@@ -85,11 +73,9 @@ static const zend_function_entry class_Mrloop_methods[] = {
8573
PHP_ME(Mrloop, addTimer, arginfo_class_Mrloop_addTimer, ZEND_ACC_PUBLIC)
8674
PHP_ME(Mrloop, addPeriodicTimer, arginfo_class_Mrloop_addPeriodicTimer, ZEND_ACC_PUBLIC)
8775
PHP_ME(Mrloop, tcpServer, arginfo_class_Mrloop_tcpServer, ZEND_ACC_PUBLIC)
88-
PHP_ME(Mrloop, parseHttpRequest, arginfo_class_Mrloop_parseHttpRequest, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
89-
PHP_ME(Mrloop, addSignal, arginfo_class_Mrloop_addSignal, ZEND_ACC_PUBLIC)
90-
PHP_ME(Mrloop, addReadStream, arginfo_class_Mrloop_addReadStream, ZEND_ACC_PUBLIC)
91-
PHP_ME(Mrloop, addWriteStream, arginfo_class_Mrloop_addWriteStream, ZEND_ACC_PUBLIC)
92-
PHP_ME(Mrloop, parseHttpResponse, arginfo_class_Mrloop_parseHttpResponse, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
93-
PHP_ME(Mrloop, writev, arginfo_class_Mrloop_writev, ZEND_ACC_PUBLIC)
94-
PHP_ME(Mrloop, futureTick, arginfo_class_Mrloop_futureTick, ZEND_ACC_PUBLIC)
95-
PHP_FE_END};
76+
PHP_ME(Mrloop, addSignal, arginfo_class_Mrloop_addSignal, ZEND_ACC_PUBLIC)
77+
PHP_ME(Mrloop, addReadStream, arginfo_class_Mrloop_addReadStream, ZEND_ACC_PUBLIC)
78+
PHP_ME(Mrloop, addWriteStream, arginfo_class_Mrloop_addWriteStream, ZEND_ACC_PUBLIC)
79+
PHP_ME(Mrloop, writev, arginfo_class_Mrloop_writev, ZEND_ACC_PUBLIC)
80+
PHP_ME(Mrloop, futureTick, arginfo_class_Mrloop_futureTick, ZEND_ACC_PUBLIC)
81+
PHP_FE_END};

php_mrloop.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,6 @@ PHP_METHOD(Mrloop, tcpServer)
4949
}
5050
/* }}} */
5151

52-
/* {{{ proto array Mrloop::parseHttpRequest( string request [, int headerlimit = 100 ] ) */
53-
PHP_METHOD(Mrloop, parseHttpRequest)
54-
{
55-
php_mrloop_parse_http_request(INTERNAL_FUNCTION_PARAM_PASSTHRU);
56-
}
57-
/* }}} */
58-
59-
/* {{{ proto array Mrloop::parseHttpResponse( string request [, int headerlimit = 100 ] ) */
60-
PHP_METHOD(Mrloop, parseHttpResponse)
61-
{
62-
php_mrloop_parse_http_response(INTERNAL_FUNCTION_PARAM_PASSTHRU);
63-
}
64-
/* }}} */
65-
6652
/* {{{ proto void Mrloop::addSignal( int signal [, callable callback ] ) */
6753
PHP_METHOD(Mrloop, addSignal)
6854
{

0 commit comments

Comments
 (0)