| #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 |