Skip to content

Commit 38ee90a

Browse files
committed
Implement GH-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 4d4b960 commit 38ee90a

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
@@ -2035,6 +2035,7 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si
20352035
}
20362036

20372037
/* Main IO loop. */
2038+
bool old_eof = stream->eof;
20382039
do {
20392040
struct timeval cur_time, elapsed_time, left_time;
20402041

@@ -2143,6 +2144,9 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si
21432144
if (nr_bytes > 0) {
21442145
php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0);
21452146
}
2147+
if (old_eof != stream->eof) {
2148+
php_stream_notify_completed(PHP_STREAM_CONTEXT(stream));
2149+
}
21462150

21472151
/* And if we were originally supposed to be blocking, let's reset the socket to that. */
21482152
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)