static int read_msg(request_rec *r, msg_t **msg) { conn_rec *c = r->connection; apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc); char *dbuf = apr_palloc(r->pool, MAX_MSG_SIZE); int dbpos = 0; int seen_eos = 0; do { apr_status_t rv; apr_bucket *bucket; rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "reading request entity data"); return HTTP_INTERNAL_SERVER_ERROR; } for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb); bucket = APR_BUCKET_NEXT(bucket)) { const char *data; apr_size_t len; if (APR_BUCKET_IS_EOS(bucket)) { seen_eos = 1; break; } /* We can't do much with this. */ if (APR_BUCKET_IS_FLUSH(bucket)) continue; /* read */ apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ); if (dbpos < MAX_MSG_SIZE) { int cursize = (dbpos + len) > MAX_MSG_SIZE ? (MAX_MSG_SIZE - dbpos) : len; memcpy(dbuf + dbpos, data, cursize); dbpos += cursize; } } apr_brigade_cleanup(bb); } while (!seen_eos); (*msg) = apr_pcalloc(r->pool, sizeof(msg_t)); (*msg)->data = dbuf; (*msg)->data[dbpos] = '\0'; (*msg)->size = dbpos; return OK; }
/* * This function assumes that either ctx->buffered_bb == NULL, or * ctx->buffered_bb is empty, or ctx->buffered_bb == bb */ static void setaside_remaining_output(ap_filter_t *f, core_output_filter_ctx_t *ctx, apr_bucket_brigade *bb, conn_rec *c) { if (bb == NULL) { return; } remove_empty_buckets(bb); if (!APR_BRIGADE_EMPTY(bb)) { c->data_in_output_filters = 1; if (bb != ctx->buffered_bb) { if (!ctx->deferred_write_pool) { apr_pool_create(&ctx->deferred_write_pool, c->pool); apr_pool_tag(ctx->deferred_write_pool, "deferred_write"); } ap_save_brigade(f, &(ctx->buffered_bb), &bb, ctx->deferred_write_pool); apr_brigade_cleanup(bb); } } else if (ctx->deferred_write_pool) { /* * There are no more requests in the pipeline. We can just clear the * pool. */ apr_pool_clear(ctx->deferred_write_pool); } }
apr_status_t h2_stream_prep_read(h2_stream *stream, apr_size_t *plen, int *peos) { apr_status_t status = APR_SUCCESS; const char *src; if (stream->bbout && !APR_BRIGADE_EMPTY(stream->bbout)) { src = "stream"; status = h2_util_bb_avail(stream->bbout, plen, peos); if (status == APR_SUCCESS && !*peos && !*plen) { apr_brigade_cleanup(stream->bbout); return h2_stream_prep_read(stream, plen, peos); } } else { src = "mplx"; status = h2_mplx_out_readx(stream->m, stream->id, NULL, NULL, plen, peos); } if (status == APR_SUCCESS && !*peos && !*plen) { status = APR_EAGAIN; } ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, stream->m->c, "h2_stream(%ld-%d): prep_read %s, len=%ld eos=%d", stream->m->id, stream->id, src, (long)*plen, *peos); return status; }
static int php_apache_sapi_read_post(char *buf, uint count_bytes) { apr_size_t len; php_struct *ctx = SG(server_context); apr_bucket_brigade *brigade; apr_bucket *partition; brigade = ctx->post_data; len = count_bytes; switch (apr_brigade_partition(ctx->post_data, count_bytes, &partition)) { case APR_SUCCESS: apr_brigade_flatten(ctx->post_data, buf, &len); brigade = apr_brigade_split(ctx->post_data, partition); apr_brigade_destroy(ctx->post_data); ctx->post_data = brigade; break; case APR_INCOMPLETE: apr_brigade_flatten(ctx->post_data, buf, &len); apr_brigade_cleanup(ctx->post_data); break; } return len; }
static ssize_t write_flush(mgs_handle_t * ctxt) { apr_bucket *e; if (!(ctxt->output_blen || ctxt->output_length)) { ctxt->output_rc = APR_SUCCESS; return 1; } if (ctxt->output_blen) { e = apr_bucket_transient_create(ctxt->output_buffer, ctxt->output_blen, ctxt->output_bb-> bucket_alloc); /* we filled this buffer first so add it to the * * head of the brigade * */ APR_BRIGADE_INSERT_HEAD(ctxt->output_bb, e); ctxt->output_blen = 0; } ctxt->output_length = 0; e = apr_bucket_flush_create(ctxt->output_bb->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next, ctxt->output_bb); /* clear the brigade to be ready for next time */ apr_brigade_cleanup(ctxt->output_bb); return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; }
static apr_status_t pass_out(apr_bucket_brigade *bb, void *ctx) { h2_conn_io *io = (h2_conn_io*)ctx; apr_status_t status; apr_off_t bblen; if (APR_BRIGADE_EMPTY(bb)) { return APR_SUCCESS; } ap_update_child_status(io->connection->sbh, SERVER_BUSY_WRITE, NULL); status = apr_brigade_length(bb, 0, &bblen); if (status == APR_SUCCESS) { ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, io->connection, "h2_conn_io(%ld): pass_out brigade %ld bytes", io->connection->id, (long)bblen); status = ap_pass_brigade(io->connection->output_filters, bb); if (status == APR_SUCCESS) { io->bytes_written += (apr_size_t)bblen; io->last_write = apr_time_now(); } apr_brigade_cleanup(bb); } return status; }
static int php_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes) { php_struct *ctx; apr_status_t rv; if (f->r->proxyreq) { return ap_get_brigade(f->next, bb, mode, block, readbytes); } ctx = SG(server_context); if (ctx == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, "php failed to get server context"); return HTTP_INTERNAL_SERVER_ERROR; } if ((rv = ap_get_brigade(f->next, bb, mode, block, readbytes)) != APR_SUCCESS) { return rv; } if (!ctx->post_data) { ctx->post_data = apr_brigade_create(f->r->pool, f->c->bucket_alloc); } if ((rv = ap_save_brigade(f, &ctx->post_data, &bb, f->r->pool)) != APR_SUCCESS) { return rv; } apr_brigade_cleanup(bb); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); return APR_SUCCESS; }
/** * This works right now because all timers are invoked in the single listener * thread in the Event MPM -- the same thread that serf callbacks are made * from, so we don't technically need a mutex yet, but with the Simple MPM, * invocations are made from worker threads, and we need to figure out locking */ static void timed_cleanup_callback(void *baton) { s_baton_t *ctx = baton; /* Causes all serf connections to unregister from the event mpm */ if (ctx->rstatus) { ap_log_rerror(APLOG_MARK, APLOG_ERR, ctx->rstatus, ctx->r, APLOGNO(01119) "serf: request returned: %d", ctx->rstatus); ctx->r->status = HTTP_OK; apr_pool_destroy(ctx->serf_pool); ap_die(ctx->rstatus, ctx->r); } else { apr_bucket *e; apr_brigade_cleanup(ctx->tmpbb); e = apr_bucket_flush_create(ctx->r->connection->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, e); e = apr_bucket_eos_create(ctx->r->connection->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, e); /* TODO: return code? bleh */ ap_pass_brigade(ctx->r->output_filters, ctx->tmpbb); apr_pool_destroy(ctx->serf_pool); ap_finalize_request_protocol(ctx->r); ap_process_request_after_handler(ctx->r); return; } }
static apr_status_t flush_out(apr_bucket_brigade *bb, void *ctx) { h2_conn_io *io = (h2_conn_io*)ctx; apr_status_t status = ap_pass_brigade(io->connection->output_filters, bb); apr_brigade_cleanup(bb); return status; }
static int brigade_cleanup(lua_State*L) { apr_bucket_brigade *bb = (apr_bucket_brigade *)CHECK_BUCKETBRIGADE_OBJECT(1); apr_status_t rc = apr_brigade_cleanup(bb); lua_pushinteger(L,rc); return 1; }
APU_DECLARE(apr_bucket_brigade *) apr_brigade_split_ex(apr_bucket_brigade *b, apr_bucket *e, apr_bucket_brigade *a) { apr_bucket *f; if (!a) { a = apr_brigade_create(b->p, b->bucket_alloc); } else if (!APR_BRIGADE_EMPTY(a)) { apr_brigade_cleanup(a); } /* Return an empty brigade if there is nothing left in * the first brigade to split off */ if (e != APR_BRIGADE_SENTINEL(b)) { f = APR_RING_LAST(&b->list); APR_RING_UNSPLICE(e, f, link); APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link); } APR_BRIGADE_CHECK_CONSISTENCY(a); APR_BRIGADE_CHECK_CONSISTENCY(b); return a; }
static apr_size_t php_apache_sapi_read_post(char *buf, size_t count_bytes) { apr_size_t len, tlen=0; php_struct *ctx = SG(server_context); request_rec *r; apr_bucket_brigade *brigade; r = ctx->r; brigade = ctx->brigade; len = count_bytes; /* * This loop is needed because ap_get_brigade() can return us partial data * which would cause premature termination of request read. Therefor we * need to make sure that if data is available we fill the buffer completely. */ while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) { apr_brigade_flatten(brigade, buf, &len); apr_brigade_cleanup(brigade); tlen += len; if (tlen == count_bytes || !len) { break; } buf += len; len = count_bytes - tlen; } return tlen; }
static apr_status_t read_complete_body(request_rec *r, apr_bucket_brigade *kept_body) { apr_bucket_brigade *tmp_bb; apr_bucket *t_bucket1, *t_bucket2; unsigned short eos_seen = 0; apr_status_t status; tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); while (!eos_seen) { status = ap_get_brigade( r->input_filters, tmp_bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN); /* This means the filter discovered an error. * Furthermore input-filter already handeld the error and sends * something to the output chain. * For example ap_http_filter does this if LimitRequestBody is reached */ if (status == AP_FILTER_ERROR) { apr_brigade_destroy(tmp_bb); return AP_FILTER_ERROR; } /* Cool no need to search for the eos bucket */ if (APR_STATUS_IS_EOF(status)) { apr_brigade_destroy(tmp_bb); return APR_SUCCESS; } if (status != APR_SUCCESS) { apr_brigade_destroy(tmp_bb); return status; } ITER_BRIGADE(t_bucket1, tmp_bb) { apr_bucket_copy(t_bucket1, &t_bucket2); /* If SSL is used TRANSIENT buckets are returned. * However we need this bucket for a longer period than * this function call, hence 'setaside' the bucket. */ if APR_BUCKET_IS_TRANSIENT(t_bucket2) { apr_bucket_setaside(t_bucket2, r->pool); } APR_BRIGADE_INSERT_TAIL(kept_body, t_bucket2); if (!eos_seen && APR_BUCKET_IS_EOS(t_bucket1)) { eos_seen = 1; } } apr_brigade_cleanup(tmp_bb); }
static int process_fortune_connection(conn_rec *c) { apr_status_t rv; apr_procattr_t *pattr; apr_pool_t *p = c->pool; apr_bucket *b; apr_bucket_brigade *bb; const char *err_msg = "200 OK\n"; fortune_conf_t *fconf = ap_get_module_config(c->base_server->module_config, &fortune_module); if (!fconf->enabled) { return DECLINED; } bb = apr_brigade_create(p, c->bucket_alloc); /* prepare process attribute */ if ((rv = apr_procattr_create(&pattr, c->pool)) != APR_SUCCESS) { goto error; } if ((rv = apr_procattr_io_set(pattr, APR_NO_PIPE, APR_FULL_BLOCK, APR_NO_PIPE)) != APR_SUCCESS) { goto error; } /* default value: APR_PROGRAM */ if ((rv = apr_procattr_cmdtype_set(pattr, APR_PROGRAM_ENV)) != APR_SUCCESS) { goto error; } /* run the program and read the output from the pipe */ if ((rv = fortune_process(c, pattr, bb)) != APR_SUCCESS) { apr_brigade_cleanup(bb); } error: if (rv != APR_SUCCESS) { err_msg = "500 ERROR\n"; } b = apr_bucket_pool_create(err_msg, strlen(err_msg), p, c->bucket_alloc); APR_BRIGADE_INSERT_HEAD(bb, b); b = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); rv = ap_pass_brigade(c->output_filters, bb); return OK; }
static apr_status_t tmpfile_filter(ap_filter_t *f, apr_bucket_brigade *bbout, ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes) { apr_bucket_brigade* bbin = apr_brigade_create(f->r->pool, f->r->connection->bucket_alloc); apr_file_t* tmpfile ; char* tmpname = apr_pstrdup(f->r->pool, "/tmp/mod-upload.XXXXXX") ; if ( f->ctx ) { APR_BRIGADE_INSERT_TAIL(bbout, apr_bucket_eos_create(bbout->bucket_alloc)) ; return APR_SUCCESS ; } if ( apr_file_mktemp(&tmpfile, tmpname, KEEPONCLOSE, f->r->pool) != APR_SUCCESS ) { // error ap_remove_input_filter(f) ; } apr_pool_cleanup_register(f->r->pool, tmpfile, (void*)apr_file_close, apr_pool_cleanup_null) ; for ( ; ; ) { apr_bucket* b ; const char* ptr = 0 ; apr_size_t bytes ; #ifdef DEBUG ap_log_rerror(APLOG_MARK,APLOG_DEBUG,0, f->r, "get_brigade") ; #endif ap_get_brigade(f->next, bbin, AP_MODE_READBYTES, APR_BLOCK_READ, BUFLEN) ; for ( b = APR_BRIGADE_FIRST(bbin) ; b != APR_BRIGADE_SENTINEL(bbin) && ! f->ctx ; b = APR_BUCKET_NEXT(b) ) { if ( APR_BUCKET_IS_EOS(b) ) { f->ctx = f ; // just using it as a flag; any nonzero will do apr_file_flush(tmpfile) ; apr_brigade_puts(bbout, ap_filter_flush, f, tmpname) ; APR_BRIGADE_INSERT_TAIL(bbout, apr_bucket_eos_create(bbout->bucket_alloc) ) ; } else if ( apr_bucket_read(b, &ptr, &bytes, APR_BLOCK_READ) == APR_SUCCESS ) { #ifdef DEBUG ap_log_rerror(APLOG_MARK,APLOG_DEBUG,0, f->r, " %d bytes in bucket", bytes) ; #endif apr_file_write(tmpfile, ptr, &bytes) ; } } if ( f->ctx ) break ; else apr_brigade_cleanup(bbin) ; } apr_brigade_destroy(bbin) ; return APR_SUCCESS ; }
apr_status_t h2_conn_io_read(h2_conn_io *io, apr_read_type_e block, h2_conn_io_on_read_cb on_read_cb, void *puser) { apr_status_t status; int done = 0; ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, io->connection, "h2_conn_io: try read, block=%d", block); if (!APR_BRIGADE_EMPTY(io->input)) { /* Seems something is left from a previous read, lets * satisfy our caller with the data we already have. */ status = h2_conn_io_bucket_read(io, block, on_read_cb, puser, &done); apr_brigade_cleanup(io->input); if (status != APR_SUCCESS || done) { return status; } } /* We only do a blocking read when we have no streams to process. So, * in httpd scoreboard lingo, we are in a KEEPALIVE connection state. * When reading non-blocking, we do have streams to process and update * child with NULL request. That way, any current request information * in the scoreboard is preserved. */ if (block == APR_BLOCK_READ) { ap_update_child_status_from_conn(io->connection->sbh, SERVER_BUSY_KEEPALIVE, io->connection); } else { ap_update_child_status(io->connection->sbh, SERVER_BUSY_READ, NULL); } /* TODO: replace this with a connection filter itself, so that we * no longer need to transfer incoming buckets to our own brigade. */ status = ap_get_brigade(io->connection->input_filters, io->input, AP_MODE_READBYTES, block, 64 * 4096); switch (status) { case APR_SUCCESS: return h2_conn_io_bucket_read(io, block, on_read_cb, puser, &done); case APR_EOF: case APR_EAGAIN: break; default: ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, io->connection, "h2_conn_io: error reading"); break; } return status; }
static apr_status_t send_bucket_downstream(ap_filter_t *f, apr_bucket *b) { charset_filter_ctx_t *ctx = f->ctx; apr_status_t rv; APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, b); rv = ap_pass_brigade(f->next, ctx->tmpbb); if (rv != APR_SUCCESS) { ctx->ees = EES_DOWNSTREAM; } apr_brigade_cleanup(ctx->tmpbb); return rv; }
static apr_status_t CaseFilterOutFilter(ap_filter_t *f, apr_bucket_brigade *pbbIn) { request_rec *r = f->r; conn_rec *c = r->connection; apr_bucket *pbktIn; apr_bucket_brigade *pbbOut; pbbOut=apr_brigade_create(r->pool, c->bucket_alloc); for (pbktIn = APR_BRIGADE_FIRST(pbbIn); pbktIn != APR_BRIGADE_SENTINEL(pbbIn); pbktIn = APR_BUCKET_NEXT(pbktIn)) { const char *data; apr_size_t len; char *buf; apr_size_t n; apr_bucket *pbktOut; if(APR_BUCKET_IS_EOS(pbktIn)) { apr_bucket *pbktEOS=apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(pbbOut,pbktEOS); continue; } /* read */ apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ); /* write */ buf = apr_bucket_alloc(len, c->bucket_alloc); for(n=0 ; n < len ; ++n) buf[n] = apr_toupper(data[n]); pbktOut = apr_bucket_heap_create(buf, len, apr_bucket_free, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(pbbOut,pbktOut); } /* Q: is there any advantage to passing a brigade for each bucket? * A: obviously, it can cut down server resource consumption, if this * experimental module was fed a file of 4MB, it would be using 8MB for * the 'read' buckets and the 'write' buckets. * * Note it is more efficient to consume (destroy) each bucket as it's * processed above than to do a single cleanup down here. In any case, * don't let our caller pass the same buckets to us, twice; */ apr_brigade_cleanup(pbbIn); return ap_pass_brigade(f->next,pbbOut); }
static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) { request_rec *r = f->r; ef_ctx_t *ctx = f->ctx; apr_status_t rv; if (!ctx) { if ((rv = init_filter_instance(f)) != APR_SUCCESS) { ctx = f->ctx; ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "can't initialise output filter %s: %s", f->frec->name, (ctx->dc->onfail == 1) ? "removing" : "aborting"); ap_remove_output_filter(f); if (ctx->dc->onfail == 1) { return ap_pass_brigade(f->next, bb); } else { apr_bucket *e; f->r->status_line = "500 Internal Server Error"; apr_brigade_cleanup(bb); e = ap_bucket_error_create(HTTP_INTERNAL_SERVER_ERROR, NULL, r->pool, f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); e = apr_bucket_eos_create(f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); ap_pass_brigade(f->next, bb); return AP_FILTER_ERROR; } } ctx = f->ctx; } if (ctx->noop) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } rv = ef_unified_filter(f, bb); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "ef_unified_filter() failed"); } if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "ap_pass_brigade() failed"); } return rv; }
static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, apr_bucket_brigade *bb, char *name) { int rv; #ifdef DEBUGGING apr_off_t len; #endif do { apr_brigade_cleanup(bb); rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES, APR_NONBLOCK_READ, AP_IOBUFSIZE); if (rv == APR_SUCCESS) { if (c_o->aborted) { return APR_EPIPE; } if (APR_BRIGADE_EMPTY(bb)) { break; } #ifdef DEBUGGING len = -1; apr_brigade_length(bb, 0, &len); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02440) "read %" APR_OFF_T_FMT " bytes from %s", len, name); #endif rv = ap_pass_brigade(c_o->output_filters, bb); if (rv == APR_SUCCESS) { ap_fflush(c_o->output_filters, bb); } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02441) "error on %s - ap_pass_brigade", name); } } else if (!APR_STATUS_IS_EAGAIN(rv) && !APR_STATUS_IS_EOF(rv)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(02442) "error on %s - ap_get_brigade", name); } } while (rv == APR_SUCCESS); ap_log_rerror(APLOG_MARK, APLOG_TRACE2, rv, r, "wstunnel_transfer complete"); if (APR_STATUS_IS_EAGAIN(rv)) { rv = APR_SUCCESS; } return rv; }
apr_status_t h2_stream_readx(h2_stream *stream, h2_io_data_cb *cb, void *ctx, apr_off_t *plen, int *peos) { apr_status_t status = APR_SUCCESS; apr_table_t *trailers = NULL; const char *src; H2_STREAM_OUT(APLOG_TRACE2, stream, "h2_stream readx_pre"); if (stream->rst_error) { return APR_ECONNRESET; } *peos = 0; if (!APR_BRIGADE_EMPTY(stream->bbout)) { apr_off_t origlen = *plen; src = "stream"; status = h2_util_bb_readx(stream->bbout, cb, ctx, plen, peos); if (status == APR_SUCCESS && !*peos && !*plen) { apr_brigade_cleanup(stream->bbout); *plen = origlen; return h2_stream_readx(stream, cb, ctx, plen, peos); } } else { src = "mplx"; status = h2_mplx_out_readx(stream->session->mplx, stream->id, cb, ctx, plen, peos, &trailers); } if (trailers && stream->response) { ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, stream->session->c, "h2_stream(%ld-%d): readx, saving trailers", stream->session->id, stream->id); h2_response_set_trailers(stream->response, trailers); } if (status == APR_SUCCESS && !*peos && !*plen) { status = APR_EAGAIN; } H2_STREAM_OUT(APLOG_TRACE2, stream, "h2_stream readx_post"); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, stream->session->c, "h2_stream(%ld-%d): readx %s, len=%ld eos=%d", stream->session->id, stream->id, src, (long)*plen, *peos); H2_STREAM_OUT(APLOG_TRACE2, stream, "h2_stream readx_post"); return status; }
static apr_status_t bail_out_on_error(apr_bucket_brigade *bb, ap_filter_t *f, int http_error) { apr_bucket *e; apr_brigade_cleanup(bb); e = ap_bucket_error_create(http_error, NULL, f->r->pool, f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); e = apr_bucket_eos_create(f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); return ap_pass_brigade(f->r->output_filters, bb); }
apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb, apr_size_t maxlen, int *pfile_handles_allowed) { apr_status_t status; int start_allowed; if (io->rst_error) { return APR_ECONNABORTED; } if (io->eos_out) { apr_off_t len; /* We have already delivered an EOS bucket to a reader, no * sense in storing anything more here. */ status = apr_brigade_length(bb, 1, &len); if (status == APR_SUCCESS) { if (len > 0) { /* someone tries to write real data after EOS, that * does not look right. */ status = APR_EOF; } /* cleanup, as if we had moved the data */ apr_brigade_cleanup(bb); } return status; } /* Let's move the buckets from the request processing in here, so * that the main thread can read them when it has time/capacity. * * Move at most "maxlen" memory bytes. If buckets remain, it is * the caller's responsibility to take care of this. * * We allow passing of file buckets as long as we do not have too * many open files already buffered. Otherwise we will run out of * file handles. */ start_allowed = *pfile_handles_allowed; status = h2_util_move(io->bbout, bb, maxlen, pfile_handles_allowed, "h2_io_out_write"); /* track # file buckets moved into our pool */ if (start_allowed != *pfile_handles_allowed) { io->files_handles_owned += (start_allowed - *pfile_handles_allowed); } return status; }
MP_INLINE static int get_bucket(modperl_filter_t *filter) { if (!filter->bb_in || MP_FILTER_EMPTY(filter)) { MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT "read in: bucket brigade is empty", MP_FILTER_NAME(filter->f)); return 0; } if (!filter->bucket) { filter->bucket = MP_FILTER_FIRST(filter); } else if (filter->bucket != MP_FILTER_SENTINEL(filter)) { filter->bucket = MP_FILTER_NEXT(filter); } if (filter->bucket == MP_FILTER_SENTINEL(filter)) { filter->bucket = NULL; /* can't destroy bb_in since the next read will need a brigade * to try to read from */ apr_brigade_cleanup(filter->bb_in); return 0; } if (MP_FILTER_IS_EOS(filter)) { MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT "read in: EOS bucket", MP_FILTER_NAME(filter->f)); filter->seen_eos = 1; /* there should be only one EOS sent, modperl_filter_read will * not come here, since filter->seen_eos is set */ return 0; } else if (MP_FILTER_IS_FLUSH(filter)) { MP_TRACE_f(MP_FUNC, MP_FILTER_NAME_FORMAT "read in: FLUSH bucket", MP_FILTER_NAME(filter->f)); filter->flush = 1; return 0; } else { return 1; } }
static int cdn_html_filter(ap_filter_t * f, apr_bucket_brigade * bb) { apr_bucket *b; const char *buf = 0; apr_size_t bytes = 0; /* now do HTML filtering if necessary, and pass the brigade onward */ saxctxt *ctxt = check_html_filter_init(f); if (!ctxt) return ap_pass_brigade(f->next, bb); for(b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b = APR_BUCKET_NEXT(b)) { if(APR_BUCKET_IS_EOS(b) || APR_BUCKET_IS_FLUSH(b)) { consume_buffer(ctxt, buf, 0, 1); APR_BUCKET_REMOVE(b); APR_BRIGADE_INSERT_TAIL(ctxt->bb, b); ap_pass_brigade(ctxt->f->next, ctxt->bb); return APR_SUCCESS; } if(apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS && buf) { if(ctxt->parser == NULL) { /* * for now, always output utf-8; we could incorporate * mod_proxy_html's output transcoding with little problem if * necessary */ ap_set_content_type(f->r, "text/html;charset=utf-8"); if(!initialize_parser(f, ctxt, &buf, bytes)) { apr_status_t rv = ap_pass_brigade(ctxt->f->next, bb); ap_remove_output_filter(f); return rv; } else ap_fputs(f->next, ctxt->bb, ctxt->cfg->doctype); } consume_buffer(ctxt, buf, bytes, 0); } } /*ap_fflush(ctxt->f->next, ctxt->bb) ; */ /* uncomment for debug */ apr_brigade_cleanup(bb); return APR_SUCCESS; }
static void read_post_data(sl_vm_t* vm, sl_request_opts_t* opts, request_rec* r) { apr_bucket_brigade* brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc); size_t len = 1024; opts->post_length = 0; opts->post_data = NULL; while(ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) { opts->post_data = sl_realloc(vm->arena, opts->post_data, opts->post_length + len); apr_brigade_flatten(brigade, opts->post_data + opts->post_length, &len); apr_brigade_cleanup(brigade); opts->post_length += len; if(!len) { break; } len = 1024; } }
void pstar_io::write_immortal(const char *str, int len) { if (!headers_sent) { output_headers(); } apr_status_t rv; apr_bucket *b; b = apr_bucket_immortal_create (str, len, ba); APR_BRIGADE_INSERT_TAIL(bb, b); if (waiting_buckets++ % 100 == 0) { rv = ap_pass_brigade(r->output_filters, bb); if (rv != APR_SUCCESS) { throw runtime_error("pstar_io::write(); Could not write to client"); } apr_brigade_cleanup(bb); } }
/* Return a pool-allocated NUL-terminated line, with CRLF stripped, * read from brigade 'bbin' using 'bbout' as temporary storage. */ static char *get_line(apr_bucket_brigade *bbout, apr_bucket_brigade *bbin, conn_rec *c, apr_pool_t *p) { apr_status_t rv; apr_size_t len; char *line; apr_brigade_cleanup(bbout); rv = apr_brigade_split_line(bbout, bbin, APR_BLOCK_READ, 8192); if (rv) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01977) "failed reading line from OCSP server"); return NULL; } rv = apr_brigade_pflatten(bbout, &line, &len, p); if (rv) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01978) "failed reading line from OCSP server"); return NULL; } if (len == 0) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(02321) "empty response from OCSP server"); return NULL; } if (line[len-1] != APR_ASCII_LF) { ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01979) "response header line too long from OCSP server"); return NULL; } line[len-1] = '\0'; if (len > 1 && line[len-2] == APR_ASCII_CR) { line[len-2] = '\0'; } return line; }
apr_status_t h2_stream_prep_read(h2_stream *stream, apr_off_t *plen, int *peos) { apr_status_t status = APR_SUCCESS; const char *src; apr_table_t *trailers = NULL; int test_read = (*plen == 0); if (stream->rst_error) { return APR_ECONNRESET; } H2_STREAM_OUT(APLOG_TRACE2, stream, "h2_stream prep_read_pre"); if (!APR_BRIGADE_EMPTY(stream->bbout)) { src = "stream"; status = h2_util_bb_avail(stream->bbout, plen, peos); if (!test_read && status == APR_SUCCESS && !*peos && !*plen) { apr_brigade_cleanup(stream->bbout); return h2_stream_prep_read(stream, plen, peos); } trailers = stream->response? stream->response->trailers : NULL; } else { src = "mplx"; status = h2_mplx_out_readx(stream->session->mplx, stream->id, NULL, NULL, plen, peos, &trailers); if (trailers && stream->response) { h2_response_set_trailers(stream->response, trailers); } } if (!test_read && status == APR_SUCCESS && !*peos && !*plen) { status = APR_EAGAIN; } H2_STREAM_OUT(APLOG_TRACE2, stream, "h2_stream prep_read_post"); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, stream->session->c, "h2_stream(%ld-%d): prep_read %s, len=%ld eos=%d, trailers=%s", stream->session->id, stream->id, src, (long)*plen, *peos, trailers? "yes" : "no"); return status; }
static apr_status_t urlReplaceFilterOutFilter(ap_filter_t *f, apr_bucket_brigade *pbbIn) { request_rec *r = f->r; conn_rec *c = r->connection; apr_bucket *pbktIn; apr_bucket_brigade *pbbOut; pbbOut=apr_brigade_create(r->pool, c->bucket_alloc); for (pbktIn = APR_BRIGADE_FIRST(pbbIn); pbktIn != APR_BRIGADE_SENTINEL(pbbIn); pbktIn = APR_BUCKET_NEXT(pbktIn)) { const char *data; apr_size_t len; char *buf; apr_size_t n; apr_bucket *pbktOut; if (APR_BUCKET_IS_EOS(pbktIn)) { apr_bucket *pbktEOS=apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(pbbOut,pbktEOS); continue; } /* read */ apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ); /* write */ buf = apr_bucket_alloc(len, c->bucket_alloc); for (n=0 ; n < len ; ++n) buf[n] = apr_toupper(data[n]); pbktOut = apr_bucket_heap_create(buf, len, apr_bucket_free, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(pbbOut,pbktOut); } apr_brigade_cleanup(pbbIn); return ap_pass_brigade(f->next,pbbOut); }