blob: 4fdeb85713e89256223efc5e93d27c4cb3e37a6b [file] [log] [blame]
#ifndef PROTON_CONNECTION_ENGINE_H
#define PROTON_CONNECTION_ENGINE_H
/*
* 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.
*/
///@file
///
/// **Experimental** The Connection Engine API wraps up the proton engine
/// objects associated with a single connection: pn_connection_t, pn_transport_t
/// and pn_collector_t. It provides a simple bytes-in/bytes-out interface for IO
/// and generates pn_event_t events to be handled by the application.
///
/// The connection engine can be fed with raw AMQP bytes from any source, and it
/// generates AMQP byte output to be written to any destination. You can use the
/// engine to integrate proton AMQP with any IO library, or native IO on any
/// platform.
///
/// The engine is not thread safe but each engine is independent. Separate
/// engines can be used concurrently. For example a multi-threaded application
/// can process connections in multiple threads, but serialize work for each
/// connection to the corresponding engine.
///
/// The engine is designed to be thread and IO neutral so it can be integrated with
/// single or multi-threaded code in reactive or proactive IO frameworks.
///
/// Summary of use:
///
/// - while !pn_connection_engine_finished()
/// - Read data from your source into pn_connection_engine_read_buffer()
/// - Call pn_connection_engine_read_done() when complete.
/// - Write data from pn_connection_engine_write_buffer() to your destination.
/// - Call pn_connection_engine_write_done() to indicate how much was written.
/// - Call pn_connection_engine_dispatch() to dispatch events until it returns NULL.
///
/// Note on error handling: most of the pn_connection_engine_*() functions do
/// not return an error code. If a fatal error occurs, the transport error
/// condition will be set and the next call to pn_connection_engine_dispatch()
/// report it to the handler as a PN_TRANSPORT_ERROR event and return false.
///
/// @defgroup connection_engine The Connection Engine
/// @ingroup connection_engine
/// @{
///
#include <proton/condition.h>
#include <proton/event.h>
#include <proton/import_export.h>
#include <proton/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/// A modifiable memory buffer.
typedef struct pn_buf_t {
char* data; ///< Beginning of the buffered data.
size_t size; ///< Number of bytes in the buffer.
} pn_buf_t;
/// Create a pn_buf
PN_EXTERN pn_buf_t pn_buf(char* data, size_t size);
/// A read-only memory buffer.
typedef struct pn_cbuf_t {
const char* data; ///< Beginning of the buffered data.
size_t size; ///< Number of bytes in the buffer.
} pn_cbuf_t;
/// Create a pn_cbuf
PN_EXTERN pn_cbuf_t pn_cbuf(const char* data, size_t size);
/// A connection engine is a trio of pn_connection_t, pn_transport_t and pn_collector_t.
/// Use the pn_connection_engine_*() functions to operate on it.
/// It is a plain struct, not a proton object. Use pn_connection_engine_init to set up
/// the initial objects and pn_connection_engine_final to release them.
///
typedef struct pn_connection_engine_t {
pn_connection_t* connection;
pn_transport_t* transport;
pn_collector_t* collector;
pn_event_t* event;
} pn_connection_engine_t;
/// Initialize a pn_connection_engine_t struct with a new connection, transport
/// and collector. Return 0 on success, a proton error code on failure.
PN_EXTERN int pn_connection_engine_init(pn_connection_engine_t* engine);
/// Release the connection, transport and collector associated with engine, set all the pointers
/// to NULL. Only call on an engine that was initialized with pn_connection_engine_init
PN_EXTERN void pn_connection_engine_final(pn_connection_engine_t* engine);
/// The engine's read buffer. Read data from your IO source into buf.data, up to
/// a max of buf.size. Then call pn_connection_engine_read_done().
///
/// buf.size==0 means the engine cannot read presently, calling
/// pn_connection_engine_dispatch() may create more buffer space.
///
PN_EXTERN pn_buf_t pn_connection_engine_read_buffer(pn_connection_engine_t*);
/// Consume the first n bytes of data in pn_connection_engine_read_buffer() and
/// update the buffer.
PN_EXTERN void pn_connection_engine_read_done(pn_connection_engine_t*, size_t n);
/// Close the read side of the transport when no more data is available.
/// Note there may still be events for pn_connection_engine_dispatch() or data
/// in pn_connection_engine_write_buffer()
PN_EXTERN void pn_connection_engine_read_close(pn_connection_engine_t*);
/// The engine's write buffer. Write data from buf.data to your IO destination,
/// up to a max of buf.size. Then call pn_connection_engine_write_done().
///
/// buf.size==0 means the engine has nothing to write presently. Calling
/// pn_connection_engine_dispatch() may generate more data.
PN_EXTERN pn_cbuf_t pn_connection_engine_write_buffer(pn_connection_engine_t*);
/// Call when the first n bytes of pn_connection_engine_write_buffer() have been
/// written to IO and can be re-used for new data. Updates the buffer.
PN_EXTERN void pn_connection_engine_write_done(pn_connection_engine_t*, size_t n);
/// Call when the write side of IO has closed and no more data can be written.
/// Note that there may still be events for pn_connection_engine_dispatch() or
/// data to read into pn_connection_engine_read_buffer().
PN_EXTERN void pn_connection_engine_write_close(pn_connection_engine_t*);
/// Close both sides of the transport, equivalent to
/// pn_connection_engine_read_close(); pn_connection_engine_write_close()
///
/// You must still call pn_connection_engine_dispatch() to process final
/// events.
///
/// To provide transport error information to the handler, set it on
/// pn_connection_engine_condition()
/// *before* calling pn_connection_engine_disconnected(). This sets
/// the error on the pn_transport_t object.
///
/// Note this does *not* modify the pn_connection_t, so you can distinguish
/// between a connection close error sent by the remote peer (which will set the
/// connection condition) and a transport error (which sets the transport
/// condition.)
///
PN_EXTERN void pn_connection_engine_disconnected(pn_connection_engine_t*);
/// Get the next available event.
/// Call in a loop until it returns NULL to dispatch all available events.
/// Note this call may modify the read and write buffers.
///
/// @return Pointer to the next event, or NULL if there are none available.
///
PN_EXTERN pn_event_t* pn_connection_engine_dispatch(pn_connection_engine_t*);
/// Return true if the engine is finished - all data has been written, all
/// events have been handled and the transport is closed.
PN_EXTERN bool pn_connection_engine_finished(pn_connection_engine_t*);
/// Get the AMQP connection, owned by the pn_connection_engine_t.
PN_EXTERN pn_connection_t* pn_connection_engine_connection(pn_connection_engine_t*);
/// Get the proton transport, owned by the pn_connection_engine_t.
PN_EXTERN pn_transport_t* pn_connection_engine_transport(pn_connection_engine_t*);
/// Get the condition object for the engine's transport.
///
/// Note that IO errors should be set on this, the transport condition, not on
/// the pn_connection_t condition. The connection's condition is for errors
/// received via the AMQP protocol, the transport condition is for errors in the
/// the IO layer such as a socket read or disconnect errors.
///
PN_EXTERN pn_condition_t* pn_connection_engine_condition(pn_connection_engine_t*);
///@}
#ifdef __cplusplus
}
#endif
#endif // PROTON_CONNECTION_ENGINE_H