| 1035 | } |
| 1036 | |
| 1037 | static apr_status_t buffer_output_receive(h2_stream *stream) |
| 1038 | { |
| 1039 | apr_status_t rv = APR_EAGAIN; |
| 1040 | apr_off_t buf_len; |
| 1041 | conn_rec *c1 = stream->session->c1; |
| 1042 | apr_bucket *b, *e; |
| 1043 | |
| 1044 | if (!stream->output) { |
| 1045 | goto cleanup; |
| 1046 | } |
| 1047 | if (stream->rst_error) { |
| 1048 | rv = APR_ECONNRESET; |
| 1049 | goto cleanup; |
| 1050 | } |
| 1051 | |
| 1052 | if (!stream->out_buffer) { |
| 1053 | stream->out_buffer = apr_brigade_create(stream->pool, c1->bucket_alloc); |
| 1054 | buf_len = 0; |
| 1055 | } |
| 1056 | else { |
| 1057 | /* if the brigade contains a file bucket, its normal report length |
| 1058 | * might be megabytes, but the memory used is tiny. For buffering, |
| 1059 | * we are only interested in the memory footprint. */ |
| 1060 | buf_len = h2_brigade_mem_size(stream->out_buffer); |
| 1061 | } |
| 1062 | |
| 1063 | if (buf_len > APR_INT32_MAX |
| 1064 | || (apr_size_t)buf_len >= stream->session->max_stream_mem) { |
| 1065 | /* we have buffered enough. No need to read more. |
| 1066 | * However, we have now output pending for which we may not |
| 1067 | * receive another poll event. We need to make sure that this |
| 1068 | * stream is not suspended so we keep on processing output. |
| 1069 | */ |
| 1070 | ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c1, |
| 1071 | H2_STRM_MSG(stream, "out_buffer, already has %ld length"), |
| 1072 | (long)buf_len); |
| 1073 | rv = APR_SUCCESS; |
| 1074 | goto cleanup; |
| 1075 | } |
| 1076 | |
| 1077 | if (stream->output_eos) { |
| 1078 | rv = APR_BRIGADE_EMPTY(stream->out_buffer)? APR_EOF : APR_SUCCESS; |
| 1079 | } |
| 1080 | else { |
| 1081 | H2_STREAM_OUT_LOG(APLOG_TRACE2, stream, "pre"); |
| 1082 | rv = h2_beam_receive(stream->output, stream->session->c1, stream->out_buffer, |
| 1083 | APR_NONBLOCK_READ, stream->session->max_stream_mem - buf_len); |
| 1084 | if (APR_SUCCESS != rv) { |
| 1085 | if (APR_EAGAIN != rv) { |
| 1086 | ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c1, |
| 1087 | H2_STRM_MSG(stream, "out_buffer, receive unsuccessful")); |
| 1088 | } |
| 1089 | } |
| 1090 | } |
| 1091 | |
| 1092 | /* get rid of buckets we have no need for */ |
| 1093 | if (!APR_BRIGADE_EMPTY(stream->out_buffer)) { |
| 1094 | b = APR_BRIGADE_FIRST(stream->out_buffer); |
no test coverage detected