aboutsummaryrefslogtreecommitdiffstats
path: root/libccnx-transport-rta/ccnx/transport/transport_rta/core/rta_Component.h
diff options
context:
space:
mode:
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.h258
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