return 0;
}
-PHP_HTTP_BUFFER_API void php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_len, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC)
+PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_len, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC)
{
char *chunk = NULL;
- size_t got = 0;
+ size_t passed = 0, got = 0;
while ((got = php_http_buffer_chunk_buffer(s, data, data_len, &chunk, chunk_len))) {
- passout(opaque, chunk, got TSRMLS_CC);
+ if (PHP_HTTP_BUFFER_PASS0 == passout(opaque, chunk, got TSRMLS_CC)) {
+ STR_SET(chunk, NULL);
+ return PHP_HTTP_BUFFER_PASS0;
+ }
+ ++passed;
if (!chunk_len) {
/* we already got the last chunk,
and freed all resources */
STR_SET(chunk, NULL);
}
STR_FREE(chunk);
+ return passed;
}
PHP_HTTP_BUFFER_API ssize_t php_http_buffer_passthru(php_http_buffer_t **s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *passin_arg, php_http_buffer_pass_func_t passon, void *passon_arg TSRMLS_DC)
PHP_HTTP_BUFFER_API ssize_t php_http_buffer_passthru(php_http_buffer_t **s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *passin_arg, php_http_buffer_pass_func_t passon, void *passon_arg TSRMLS_DC);
/* wrapper around php_http_buffer_chunk_buffer, which passes available chunks to passthru() */
-PHP_HTTP_BUFFER_API void php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_size, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC);
+PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_size, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC);
/* write chunks directly into php_http_buffer_t buffer */
PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_input(php_http_buffer_t **s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *opaque TSRMLS_DC);
{
php_http_env_response_t *r = context;
- r->ops->write(r, buf, len);
+ if (SUCCESS != r->ops->write(r, buf, len)) {
+ return (size_t) -1;
+ }
/* we really only need to flush when throttling is enabled,
because we push the data as fast as possible anyway if not */
#define php_http_env_response_send_done(r) php_http_env_response_send_data((r), NULL, 0)
static STATUS php_http_env_response_send_data(php_http_env_response_t *r, const char *buf, size_t len)
{
- size_t chunk = r->throttle.chunk ? r->throttle.chunk : PHP_HTTP_SENDBUF_SIZE;
+ size_t chunks_sent, chunk = r->throttle.chunk ? r->throttle.chunk : PHP_HTTP_SENDBUF_SIZE;
TSRMLS_FETCH_FROM_CTX(r->ts);
if (r->content.encoder) {
}
}
- if (enc_str) {
- php_http_buffer_chunked_output(&r->buffer, enc_str, enc_len, buf ? chunk : 0, output, r TSRMLS_CC);
- STR_FREE(enc_str);
+ if (!enc_str) {
+ return SUCCESS;
}
+ chunks_sent = php_http_buffer_chunked_output(&r->buffer, enc_str, enc_len, buf ? chunk : 0, output, r TSRMLS_CC);
+ STR_FREE(enc_str);
} else {
- php_http_buffer_chunked_output(&r->buffer, buf, len, buf ? chunk : 0, output, r TSRMLS_CC);
+ chunks_sent = php_http_buffer_chunked_output(&r->buffer, buf, len, buf ? chunk : 0, output, r TSRMLS_CC);
}
- return SUCCESS;
+ return chunks_sent != (size_t) -1 ? SUCCESS : FAILURE;
}
php_http_env_response_t *php_http_env_response_init(php_http_env_response_t *r, zval *options, php_http_env_response_ops_t *ops, void *init_arg TSRMLS_DC)
}
}
- php_stream_write(stream_ctx->stream, data_str, data_len);
+ if (data_len != php_stream_write(stream_ctx->stream, data_str, data_len)) {
+ return FAILURE;
+ }
return SUCCESS;
}
--- /dev/null
+--TEST--
+env response send failure
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+
+echo "Test\n";
+
+class closer extends php_user_filter {
+ function filter ($in, $out, &$consumed, $closing) {
+ while ($bucket = stream_bucket_make_writeable($in)) {
+ stream_bucket_append($out, $bucket);
+ }
+ return PSFS_ERR_FATAL;
+ }
+}
+
+stream_filter_register("closer", "closer");
+
+$r = new http\Env\Response;
+$r->getBody()->append(str_repeat("a", 16*1024*4));
+$s = fopen("php://temp", "w");
+stream_filter_append($s, "closer");
+var_dump($r->send($s));
+?>
+DONE
+--EXPECTF--
+Test
+Warning: http\Env\Response::send(): Failed to send response body in %s on line %d
+bool(false)
+DONE