00001 #ifndef PROTON_CONNECTION_ENGINE_H 00002 #define PROTON_CONNECTION_ENGINE_H 00003 00004 /* 00005 * Licensed to the Apache Software Foundation (ASF) under one 00006 * or more contributor license agreements. See the NOTICE file 00007 * distributed with this work for additional information 00008 * regarding copyright ownership. The ASF licenses this file 00009 * to you under the Apache License, Version 2.0 (the 00010 * "License"); you may not use this file except in compliance 00011 * with the License. You may obtain a copy of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, 00016 * software distributed under the License is distributed on an 00017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 00018 * KIND, either express or implied. See the License for the 00019 * specific language governing permissions and limitations 00020 * under the License. 00021 */ 00022 00023 ///@file 00024 /// 00025 /// **Experimental** The Connection Engine API wraps up the proton engine 00026 /// objects associated with a single connection: pn_connection_t, pn_transport_t 00027 /// and pn_collector_t. It provides a simple bytes-in/bytes-out interface for IO 00028 /// and generates pn_event_t events to be handled by the application. 00029 /// 00030 /// The connection engine can be fed with raw AMQP bytes from any source, and it 00031 /// generates AMQP byte output to be written to any destination. You can use the 00032 /// engine to integrate proton AMQP with any IO library, or native IO on any 00033 /// platform. 00034 /// 00035 /// The engine is not thread safe but each engine is independent. Separate 00036 /// engines can be used concurrently. For example a multi-threaded application 00037 /// can process connections in multiple threads, but serialize work for each 00038 /// connection to the corresponding engine. 00039 /// 00040 /// The engine is designed to be thread and IO neutral so it can be integrated with 00041 /// single or multi-threaded code in reactive or proactive IO frameworks. 00042 /// 00043 /// Summary of use: 00044 /// 00045 /// - while !pn_connection_engine_finished() 00046 /// - Read data from your source into pn_connection_engine_read_buffer() 00047 /// - Call pn_connection_engine_read_done() when complete. 00048 /// - Write data from pn_connection_engine_write_buffer() to your destination. 00049 /// - Call pn_connection_engine_write_done() to indicate how much was written. 00050 /// - Call pn_connection_engine_dispatch() to dispatch events until it returns NULL. 00051 /// 00052 /// Note on error handling: most of the pn_connection_engine_*() functions do 00053 /// not return an error code. If a fatal error occurs, the transport error 00054 /// condition will be set and the next call to pn_connection_engine_dispatch() 00055 /// report it to the handler as a PN_TRANSPORT_ERROR event and return false. 00056 /// 00057 /// @defgroup connection_engine The Connection Engine 00058 /// @ingroup connection_engine 00059 /// @{ 00060 /// 00061 00062 #include <proton/condition.h> 00063 #include <proton/event.h> 00064 #include <proton/import_export.h> 00065 #include <proton/types.h> 00066 00067 #ifdef __cplusplus 00068 extern "C" { 00069 #endif 00070 00071 /// A modifiable memory buffer. 00072 typedef struct pn_buf_t { 00073 char* data; ///< Beginning of the buffered data. 00074 size_t size; ///< Number of bytes in the buffer. 00075 } pn_buf_t; 00076 00077 /// Create a pn_buf 00078 PN_EXTERN pn_buf_t pn_buf(char* data, size_t size); 00079 00080 /// A read-only memory buffer. 00081 typedef struct pn_cbuf_t { 00082 const char* data; ///< Beginning of the buffered data. 00083 size_t size; ///< Number of bytes in the buffer. 00084 } pn_cbuf_t; 00085 00086 /// Create a pn_cbuf 00087 PN_EXTERN pn_cbuf_t pn_cbuf(const char* data, size_t size); 00088 00089 /// A connection engine is a trio of pn_connection_t, pn_transport_t and pn_collector_t. 00090 /// Use the pn_connection_engine_*() functions to operate on it. 00091 /// It is a plain struct, not a proton object. Use pn_connection_engine_init to set up 00092 /// the initial objects and pn_connection_engine_final to release them. 00093 /// 00094 typedef struct pn_connection_engine_t { 00095 pn_connection_t* connection; 00096 pn_transport_t* transport; 00097 pn_collector_t* collector; 00098 pn_event_t* event; 00099 } pn_connection_engine_t; 00100 00101 /// Initialize a pn_connection_engine_t struct with a new connection, transport 00102 /// and collector. Return 0 on success, a proton error code on failure. 00103 PN_EXTERN int pn_connection_engine_init(pn_connection_engine_t* engine); 00104 00105 /// Release the connection, transport and collector associated with engine, set all the pointers 00106 /// to NULL. Only call on an engine that was initialized with pn_connection_engine_init 00107 PN_EXTERN void pn_connection_engine_final(pn_connection_engine_t* engine); 00108 00109 /// The engine's read buffer. Read data from your IO source into buf.data, up to 00110 /// a max of buf.size. Then call pn_connection_engine_read_done(). 00111 /// 00112 /// buf.size==0 means the engine cannot read presently, calling 00113 /// pn_connection_engine_dispatch() may create more buffer space. 00114 /// 00115 PN_EXTERN pn_buf_t pn_connection_engine_read_buffer(pn_connection_engine_t*); 00116 00117 /// Consume the first n bytes of data in pn_connection_engine_read_buffer() and 00118 /// update the buffer. 00119 PN_EXTERN void pn_connection_engine_read_done(pn_connection_engine_t*, size_t n); 00120 00121 /// Close the read side of the transport when no more data is available. 00122 /// Note there may still be events for pn_connection_engine_dispatch() or data 00123 /// in pn_connection_engine_write_buffer() 00124 PN_EXTERN void pn_connection_engine_read_close(pn_connection_engine_t*); 00125 00126 /// The engine's write buffer. Write data from buf.data to your IO destination, 00127 /// up to a max of buf.size. Then call pn_connection_engine_write_done(). 00128 /// 00129 /// buf.size==0 means the engine has nothing to write presently. Calling 00130 /// pn_connection_engine_dispatch() may generate more data. 00131 PN_EXTERN pn_cbuf_t pn_connection_engine_write_buffer(pn_connection_engine_t*); 00132 00133 /// Call when the first n bytes of pn_connection_engine_write_buffer() have been 00134 /// written to IO and can be re-used for new data. Updates the buffer. 00135 PN_EXTERN void pn_connection_engine_write_done(pn_connection_engine_t*, size_t n); 00136 00137 /// Call when the write side of IO has closed and no more data can be written. 00138 /// Note that there may still be events for pn_connection_engine_dispatch() or 00139 /// data to read into pn_connection_engine_read_buffer(). 00140 PN_EXTERN void pn_connection_engine_write_close(pn_connection_engine_t*); 00141 00142 /// Close both sides of the transport, equivalent to 00143 /// pn_connection_engine_read_close(); pn_connection_engine_write_close() 00144 /// 00145 /// You must still call pn_connection_engine_dispatch() to process final 00146 /// events. 00147 /// 00148 /// To provide transport error information to the handler, set it on 00149 /// pn_connection_engine_condition() 00150 /// *before* calling pn_connection_engine_disconnected(). This sets 00151 /// the error on the pn_transport_t object. 00152 /// 00153 /// Note this does *not* modify the pn_connection_t, so you can distinguish 00154 /// between a connection close error sent by the remote peer (which will set the 00155 /// connection condition) and a transport error (which sets the transport 00156 /// condition.) 00157 /// 00158 PN_EXTERN void pn_connection_engine_disconnected(pn_connection_engine_t*); 00159 00160 /// Get the next available event. 00161 /// Call in a loop until it returns NULL to dispatch all available events. 00162 /// Note this call may modify the read and write buffers. 00163 /// 00164 /// @return Pointer to the next event, or NULL if there are none available. 00165 /// 00166 PN_EXTERN pn_event_t* pn_connection_engine_dispatch(pn_connection_engine_t*); 00167 00168 /// Return true if the engine is finished - all data has been written, all 00169 /// events have been handled and the transport is closed. 00170 PN_EXTERN bool pn_connection_engine_finished(pn_connection_engine_t*); 00171 00172 /// Get the AMQP connection, owned by the pn_connection_engine_t. 00173 PN_EXTERN pn_connection_t* pn_connection_engine_connection(pn_connection_engine_t*); 00174 00175 /// Get the proton transport, owned by the pn_connection_engine_t. 00176 PN_EXTERN pn_transport_t* pn_connection_engine_transport(pn_connection_engine_t*); 00177 00178 /// Get the condition object for the engine's transport. 00179 /// 00180 /// Note that IO errors should be set on this, the transport condition, not on 00181 /// the pn_connection_t condition. The connection's condition is for errors 00182 /// received via the AMQP protocol, the transport condition is for errors in the 00183 /// the IO layer such as a socket read or disconnect errors. 00184 /// 00185 PN_EXTERN pn_condition_t* pn_connection_engine_condition(pn_connection_engine_t*); 00186 00187 ///@} 00188 00189 #ifdef __cplusplus 00190 } 00191 #endif 00192 00193 #endif // PROTON_CONNECTION_ENGINE_H