diff options
Diffstat (limited to 'modules/http2/h2_bucket_beam.h')
-rw-r--r-- | modules/http2/h2_bucket_beam.h | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/modules/http2/h2_bucket_beam.h b/modules/http2/h2_bucket_beam.h new file mode 100644 index 0000000..c58ce98 --- /dev/null +++ b/modules/http2/h2_bucket_beam.h @@ -0,0 +1,267 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef h2_bucket_beam_h +#define h2_bucket_beam_h + +#include "h2_conn_ctx.h" + +struct apr_thread_mutex_t; +struct apr_thread_cond_t; + +/** + * A h2_bucket_beam solves the task of transferring buckets, esp. their data, + * across threads with as little copying as possible. + */ + +typedef struct h2_bucket_beam h2_bucket_beam; + +typedef void h2_beam_io_callback(void *ctx, h2_bucket_beam *beam, + apr_off_t bytes); +typedef void h2_beam_ev_callback(void *ctx, h2_bucket_beam *beam); + +/** + * h2_blist can hold a list of buckets just like apr_bucket_brigade, but + * does not to any allocations or related features. + */ +typedef struct { + APR_RING_HEAD(h2_bucket_list, apr_bucket) list; +} h2_blist; + +struct h2_bucket_beam { + int id; + const char *name; + conn_rec *from; + apr_pool_t *pool; + h2_blist buckets_to_send; + h2_blist buckets_consumed; + h2_blist buckets_eor; + + apr_size_t max_buf_size; + apr_interval_time_t timeout; + + int aborted; + int closed; + int tx_mem_limits; /* only memory size counts on transfers */ + int copy_files; + + struct apr_thread_mutex_t *lock; + struct apr_thread_cond_t *change; + + h2_beam_ev_callback *was_empty_cb; /* event: beam changed to non-empty in h2_beam_send() */ + void *was_empty_ctx; + h2_beam_ev_callback *recv_cb; /* event: buckets were transfered in h2_beam_receive() */ + void *recv_ctx; + h2_beam_ev_callback *send_cb; /* event: buckets were added in h2_beam_send() */ + void *send_ctx; + h2_beam_ev_callback *eagain_cb; /* event: a receive results in ARP_EAGAIN */ + void *eagain_ctx; + + apr_off_t recv_bytes; /* amount of bytes transferred in h2_beam_receive() */ + apr_off_t recv_bytes_reported; /* amount of bytes reported as received via callback */ + h2_beam_io_callback *cons_io_cb; /* report: recv_bytes deltas for sender */ + void *cons_ctx; +}; + +/** + * Creates a new bucket beam for transfer of buckets across threads. + * + * The pool the beam is created with will be protected by the given + * mutex and will be used in multiple threads. It needs a pool allocator + * that is only used inside that same mutex. + * + * @param pbeam will hold the created beam on return + * @param c_from connection from which buchets are sent + * @param pool pool owning the beam, beam will cleanup when pool released + * @param id identifier of the beam + * @param tag tag identifying beam for logging + * @param buffer_size maximum memory footprint of buckets buffered in beam, or + * 0 for no limitation + * @param timeout timeout for blocking operations + */ +apr_status_t h2_beam_create(h2_bucket_beam **pbeam, + conn_rec *from, + apr_pool_t *pool, + int id, const char *tag, + apr_size_t buffer_size, + apr_interval_time_t timeout); + +/** + * Destroys the beam immediately without cleanup. + */ +apr_status_t h2_beam_destroy(h2_bucket_beam *beam, conn_rec *c); + +/** + * Switch copying of file buckets on/off. + */ +void h2_beam_set_copy_files(h2_bucket_beam * beam, int enabled); + +/** + * Send buckets from the given brigade through the beam. + * This can block of the amount of bucket data is above the buffer limit. + * @param beam the beam to add buckets to + * @param from the connection the sender operates on, must be the same as + * used to create the beam + * @param bb the brigade to take buckets from + * @param block if the sending should block when the buffer is full + * @param pwritten on return, contains the number of data bytes sent + * @return APR_SUCCESS when buckets were added to the beam. This can be + * a partial transfer and other buckets may still remain in bb + * APR_EAGAIN on non-blocking send when the buffer is full + * APR_TIMEUP on blocking semd that time out + * APR_ECONNABORTED when beam has been aborted + */ +apr_status_t h2_beam_send(h2_bucket_beam *beam, conn_rec *from, + apr_bucket_brigade *bb, + apr_read_type_e block, + apr_off_t *pwritten); + +/** + * Receive buckets from the beam into the given brigade. The caller is + * operating on connection `to`. + * @param beam the beam to receive buckets from + * @param to the connection the receiver is working with + * @param bb the bucket brigade to append to + * @param block if the read should block when buckets are unavailable + * @param readbytes the amount of data the receiver wants + * @return APR_SUCCESS when buckets were appended + * APR_EAGAIN on non-blocking read when no buckets are available + * APR_TIMEUP on blocking reads that time out + * APR_ECONNABORTED when beam has been aborted + */ +apr_status_t h2_beam_receive(h2_bucket_beam *beam, conn_rec *to, + apr_bucket_brigade *bb, + apr_read_type_e block, + apr_off_t readbytes); + +/** + * Determine if beam is empty. + */ +int h2_beam_empty(h2_bucket_beam *beam); + +/** + * Abort the beam, either from receiving or sending side. + * + * @param beam the beam to abort + * @param c the connection the caller is working with + */ +void h2_beam_abort(h2_bucket_beam *beam, conn_rec *c); + +/** + * Close the beam. Make certain an EOS is sent. + * + * @param beam the beam to abort + * @param c the connection the caller is working with + */ +void h2_beam_close(h2_bucket_beam *beam, conn_rec *c); + +/** + * Set/get the timeout for blocking sebd/receive operations. + */ +void h2_beam_timeout_set(h2_bucket_beam *beam, + apr_interval_time_t timeout); + +apr_interval_time_t h2_beam_timeout_get(h2_bucket_beam *beam); + +/** + * Set/get the maximum buffer size for beam data (memory footprint). + */ +void h2_beam_buffer_size_set(h2_bucket_beam *beam, + apr_size_t buffer_size); +apr_size_t h2_beam_buffer_size_get(h2_bucket_beam *beam); + +/** + * Register a callback to be invoked on the sender side with the + * amount of bytes that have been consumed by the receiver, since the + * last callback invocation or reset. + * @param beam the beam to set the callback on + * @param io_cb the callback or NULL, called on sender with bytes consumed + * @param ctx the context to use in callback invocation + * + * Call from the sender side, io callbacks invoked on sender side, ev callback + * from any side. + */ +void h2_beam_on_consumed(h2_bucket_beam *beam, + h2_beam_io_callback *io_cb, void *ctx); + +/** + * Register a callback to be invoked on the receiver side whenever + * buckets have been transfered in a h2_beam_receive() call. + * @param beam the beam to set the callback on + * @param recv_cb the callback or NULL, called when buckets are received + * @param ctx the context to use in callback invocation + */ +void h2_beam_on_received(h2_bucket_beam *beam, + h2_beam_ev_callback *recv_cb, void *ctx); + +/** + * Register a callback to be invoked on the receiver side whenever + * APR_EAGAIN is being returned in h2_beam_receive(). + * @param beam the beam to set the callback on + * @param egain_cb the callback or NULL, called before APR_EAGAIN is returned + * @param ctx the context to use in callback invocation + */ +void h2_beam_on_eagain(h2_bucket_beam *beam, + h2_beam_ev_callback *eagain_cb, void *ctx); + +/** + * Register a call back from the sender side to be invoked when send + * has added buckets to the beam. + * Unregister by passing a NULL on_send_cb. + * @param beam the beam to set the callback on + * @param on_send_cb the callback to invoke after buckets were added + * @param ctx the context to use in callback invocation + */ +void h2_beam_on_send(h2_bucket_beam *beam, + h2_beam_ev_callback *on_send_cb, void *ctx); + +/** + * Register a call back from the sender side to be invoked when send + * has added to a previously empty beam. + * Unregister by passing a NULL was_empty_cb. + * @param beam the beam to set the callback on + * @param was_empty_cb the callback to invoke on blocked send + * @param ctx the context to use in callback invocation + */ +void h2_beam_on_was_empty(h2_bucket_beam *beam, + h2_beam_ev_callback *was_empty_cb, void *ctx); + +/** + * Call any registered consumed handler, if any changes have happened + * since the last invocation. + * @return !=0 iff a handler has been called + * + * Needs to be invoked from the sending side. + */ +int h2_beam_report_consumption(h2_bucket_beam *beam); + +/** + * Get the amount of bytes currently buffered in the beam (unread). + */ +apr_off_t h2_beam_get_buffered(h2_bucket_beam *beam); + +/** + * Get the memory used by the buffered buckets, approximately. + */ +apr_off_t h2_beam_get_mem_used(h2_bucket_beam *beam); + +/** + * @return != 0 iff beam has been closed or has an EOS bucket buffered + * waiting to be received. + */ +int h2_beam_is_complete(h2_bucket_beam *beam); + +#endif /* h2_bucket_beam_h */ |