268 lines
9.7 KiB
C
268 lines
9.7 KiB
C
/* 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 */
|