diff options
Diffstat (limited to 'libccnx-transport-rta/ccnx/transport/transport_rta/core/rta_Component.h')
-rw-r--r-- | libccnx-transport-rta/ccnx/transport/transport_rta/core/rta_Component.h | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/core/rta_Component.h b/libccnx-transport-rta/ccnx/transport/transport_rta/core/rta_Component.h new file mode 100644 index 00000000..24efa6aa --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/core/rta_Component.h @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed 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 rta_Component.h + * @brief <#Brief Description#> + * + * A Component is a functional block within a protocol stack. It exists + * between the API Connector (at the top) and the Forwarder Connector + * (at the bottom). All components have a similar interface. The only + * slight variation is that components betwen the Forwarder Connector + * and the Codec deal in "wire" message formats, while components above + * the connector deal with "parsed" (CCNxMessage) formats. + * + * To write a component, follow these procedures: + * 1) add your component's name to components.h enum. This is the + * symbolic name you will use for it in the code. We'll call + * it PROTO_WIZ. + * 2) Copy a skeleton, such as component_Verifier.h for your header. + * Let's call it component_Wizard.h. Inside the header, you'll + * define the "operations" structure that's exported to the system. + * @code{.c} + **#ifndef Libccnx_component_wizard_h + **#define Libccnx_component_wizard_h + * + * // Function structs for component variations + * extern ComponentOperations proto_wizard_ops; + * + **#endif + * @endcode + * + * 3) Copy a skeleton, like component_Verifier_Null.c, for your + * implementation. Let's call it component_Wizard.c. Inside + * you must: + * a) instantiate proto_wizard_ops: + * @code{.c} + * static int component_Wizard_Init(ProtocolStack *stack); + * static int component_Wizard_Opener(RtaConnection *conn); + * static void component_Wizard_Upcall_Read(PARCEventQueue *, void *conn); + * static void component_Wizard_Downcall_Read(PARCEventQueue *, void *conn); + * static int component_Wizard_Closer(RtaConnection *conn); + * static int component_Wizard_Release(ProtocolStack *stack); + * + * ComponentOperations verify_null_ops = { + * component_Wizard_Init, + * component_Wizard_Opener, + * component_Wizard_Upcall_Read, + * NULL, + * component_Wizard_Downcall_Read, + * NULL, + * component_Wizard_Closer, + * component_Wizard_Release + * }; + * @endcode + * + * These define the interface your component exposes to the stack + * Init: called once on stack creation + * Open: called once per connection Open + * UpcallRead: Called when the "upward" buffer has something to read + * DowncallRead: Called when the "downward" buffer has something to read + * Closer: called once per connection Close + * Release: called on protocol stack destruction. + * + * Optionally, you may include UpcallEvents and DowncallEvents, but + * in general those are not useful. + * + * Any of the function pointers in the "ops" may be NULL. + * + * b) Implement your Init. If you need to create a stack-wide data structure + * to track state, you would do something like this, which allocates + * memory and sticks it away in component-specific storage in the stack. + * Notice that protocolStack_SetPrivateData takes our protocol's name + * PROTO_WIZ as a parameter. + * + * @code{.c} + * static int + * component_Wizard_Init(ProtocolStack *stack) + * { + * struct mydata *data = mydata_Create(); + * protocolStack_SetPrivateData(stack, PROTO_WIZ, data); + * return 0; + * } + * @endcode + * + * c) Implement your Opener. You will very likely want to keep per-connection + * state. This follows a similar method to the Init, but in a connection. + * We squirl away the connection-specific data similarly to the stack-wide + * data. In addition, it's good practice to fetch your component's Stats + * for the connection and increment the OPENS counter for a successful open. + * + * @code{.c} + * static int + * component_Wizard_Opener(RtaConnection *connection) + * { + * ComponentStats *stats; + * struct myState *mystate; + * + * parcMemory_AlocateAndClear(&mystate, sizeof(void *), sizeof(struct api_conn_state)); + * rtaConnection_SetPrivateData(connection, PROTO_WIZ, mystate); + * + * stats = rtaConnection_GetStats(connection, PROTO_WIZ); + * stats_Increment(stats, STATS_OPENS); + * return 0; + * } + * @endcode + * + * d) Implement your Close and Release. These perform the inverse + * of the Open and Init. They should fetch your private data, if + * any, and free it: + * @code{.c} + * static int + * component_Wizard_Closer(RtaConnection *conn) + * { + * ComponentStats *stats = rtaConnection_GetStats(conn, PROTO_WIZ); + * struct myState *mystate = rtaConnection_GetPrivateData(conn, PROTO_WIZ); + * + * stats_Increment(stats, STATS_CLOSES); + * myState_Destroy(&mystate); + * return 0; + * } + * + * static int + * component_Wizard_Release(ProtocolStack *stack) + * { + * ComponentStats *stats = protocoLStack_GetStats(stack, PROTO_WIZ); + * struct myData *mydata = protocolStack_GetPrivateData(stack, PROTO_WIZ); + * + * stats_Increment(stats, STATS_CLOSES); + * myData_Destroy(&mydata); + * return 0; + * } + * @endcode + * + * d) Implement your Read handlers. They are similar for the upcall + * and downcall handlers. The main issue to be aware of is that + * you must *drain* the queue on each call. The callback is edge + * triggered. + * + * Below we show an example of the Upcall read callback, which means + * there is data from below travelling up the stack. Therefore, we + * retrieve the RTA_UP output queue to pass messages up the stack. + * The while() loop is what drains the queue. + * + * Note also that "ptr" is a pointer to the ProtocolStack that owns + * connecition (what your Init was called with). The Connection information + * rides inside the transport message, and is retrieved with a call + * to transportMessage_GetInfo(). + * + * @code{.c} + * static void + * component_Wizard_Upcall_Read(PARCEventQueue *in, PARCEvent_EventType event, void *ptr) + * { + * ProtocolStack *stack = (ProtocolStack *) ptr; + * PARCEventQueue *out = protocoStack_GetPutQueue(stack, PROTO_WIZ, RTA_UP); + * TransportMessage *tm; + * + * while( (tm = rtaComponent_GetMessage(in)) != NULL ) + * { + * RtaConnection *conn = transportMessage_GetInfo(tm); + * ComponentStats *stats = rtaConnection_GetStats(conn, PROTO_WIZ); + * CCNxMessage *msg = TransportMessage_GetCcnxMessage(tm); + * + * stats_Increment(stats, STATS_UPCALL_IN); + * + * // do something with the CCNxMessage + * + * if( rtaComponent_PutMessage(out, tm) ) + * stats_Increment(stats, STATS_UPCALL_OUT); + * } + * } + * @endcode + * + * Example: + * @code + * <#example#> + * @endcode + * + */ +/** + */ + +#ifndef Libccnx_rta_component_h +#define Libccnx_rta_component_h + +#include "components.h" +#include "rta_ComponentQueue.h" +#include "rta_ComponentStats.h" + +/** + * Init: one time initialization on first instantiation (0 success, -1 failure) + * Open: Per connection open, returns valid descriptor or -1 on failure + * upcallRead: Callback when one or more messages are available + * downcallRead: Callback when one or more messages are available. + * xEvent: Called for events on the queue + * Close: Per connection close + * Release: One time release of state when whole stack taken down + * stateChagne: Called when there is a state change related to the connection + * + * Example: + * @code + * <#example#> + * @endcode + */ +typedef struct { + int (*init)(RtaProtocolStack *stack); + int (*open)(RtaConnection *conn); + void (*upcallRead)(PARCEventQueue *queue, PARCEventType events, void *stack); + void (*upcallEvent)(PARCEventQueue *queue, PARCEventQueueEventType events, void *stack); + void (*downcallRead)(PARCEventQueue *queue, PARCEventType events, void *stack); + void (*downcallEvent)(PARCEventQueue *queue, PARCEventQueueEventType events, void *stack); + int (*close)(RtaConnection *conn); + int (*release)(RtaProtocolStack *stack); + void (*stateChange)(RtaConnection *conn); +} RtaComponentOperations; + +extern PARCEventQueue *rtaComponent_GetOutputQueue(RtaConnection *conn, + RtaComponents component, + RtaDirection direction); + +/** + * Send a message between components. The API connector and Forwarder connector + * must set the connection information in the transport message with + * rtaConnection_SetInTransport(). + * + * returns 1 on success, 0 on failure + * + * Example: + * @code + * <#example#> + * @endcode + */ +extern int rtaComponent_PutMessage(PARCEventQueue *queue, TransportMessage *tm); + +/** + * Fetch a message from the queue. Will return NULL if no message + * is available. + * + * As a side effect, it will drain message on a closed connection. + * + * Example: + * @code + * <#example#> + * @endcode + */ +extern TransportMessage *rtaComponent_GetMessage(PARCEventQueue *queue); +#endif |