Skip to content

Commit b3c23c2

Browse files
committed
Implement phpGH-8641: [Stream] STREAM_NOTIFY_COMPLETED over HTTP never emitted
This adds support for the completed event. Since the read handler could be entered twice towards the end of the stream we remember what the eof flag was before reading so we can emit the completed event when the flag changes to true.
1 parent 47ed190 commit b3c23c2

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

ext/openssl/xp_ssl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,7 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si
20322032
}
20332033

20342034
/* Main IO loop. */
2035+
bool old_eof = stream->eof;
20352036
do {
20362037
struct timeval cur_time, elapsed_time, left_time;
20372038

@@ -2140,6 +2141,9 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si
21402141
if (nr_bytes > 0) {
21412142
php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0);
21422143
}
2144+
if (old_eof != stream->eof) {
2145+
php_stream_notify_completed(PHP_STREAM_CONTEXT(stream));
2146+
}
21432147

21442148
/* And if we were originally supposed to be blocking, let's reset the socket to that. */
21452149
if (began_blocked && php_set_sock_blocking(sslsock->s.socket, 1) == SUCCESS) {

ext/standard/tests/http/gh8641.phpt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
GH-8641 ([Stream] STREAM_NOTIFY_COMPLETED over HTTP never emitted)
3+
--SKIPIF--
4+
<?php require 'server.inc'; http_server_skipif(); ?>
5+
--INI--
6+
allow_url_fopen=1
7+
--FILE--
8+
<?php
9+
require 'server.inc';
10+
11+
function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max)
12+
{
13+
if ($notification_code === STREAM_NOTIFY_COMPLETED) {
14+
echo $notification_code, ' ', $bytes_transferred, ' ', $bytes_max, PHP_EOL;
15+
}
16+
}
17+
18+
$ctx = stream_context_create();
19+
stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
20+
21+
$responses = array(
22+
"data://text/plain,HTTP/1.0 200 Ok\r\nContent-Length: 11\r\n\r\nHello world",
23+
);
24+
25+
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
26+
27+
$f = file_get_contents($uri, 0, $ctx);
28+
29+
http_server_kill($pid);
30+
var_dump($f);
31+
?>
32+
--EXPECTF--
33+
8 11 11
34+
string(11) "Hello world"

main/streams/php_stream_context.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ END_EXTERN_C()
9494
php_stream_notification_notify((context), PHP_STREAM_NOTIFY_PROGRESS, PHP_STREAM_NOTIFY_SEVERITY_INFO, \
9595
NULL, 0, (bsofar), (bmax), NULL); } } while(0)
9696

97+
#define php_stream_notify_completed(context) do { if ((context) && (context)->notifier) { \
98+
php_stream_notification_notify((context), PHP_STREAM_NOTIFY_COMPLETED, PHP_STREAM_NOTIFY_SEVERITY_INFO, \
99+
NULL, 0, (context)->notifier->progress, (context)->notifier->progress_max, NULL); } } while(0)
100+
97101
#define php_stream_notify_progress_init(context, sofar, bmax) do { if ((context) && (context)->notifier) { \
98102
(context)->notifier->progress = (sofar); \
99103
(context)->notifier->progress_max = (bmax); \

main/streams/xp_socket.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,11 @@ static ssize_t php_sockop_read(php_stream *stream, char *buf, size_t count)
189189
}
190190

191191
ssize_t nr_bytes = recv(sock->socket, buf, XP_SOCK_BUF_SIZE(count), recv_flags);
192-
int err = php_socket_errno();
192+
193+
bool old_eof = stream->eof;
193194

194195
if (nr_bytes < 0) {
196+
int err = php_socket_errno();
195197
if (PHP_IS_TRANSIENT_ERROR(err)) {
196198
nr_bytes = 0;
197199
} else {
@@ -204,6 +206,9 @@ static ssize_t php_sockop_read(php_stream *stream, char *buf, size_t count)
204206
if (nr_bytes > 0) {
205207
php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0);
206208
}
209+
if (old_eof != stream->eof) {
210+
php_stream_notify_completed(PHP_STREAM_CONTEXT(stream));
211+
}
207212

208213
return nr_bytes;
209214
}

0 commit comments

Comments
 (0)