aboutsummaryrefslogtreecommitdiffstats
path: root/metis/ccnx/forwarder/metis/io/metis_IoOperations.h
blob: 861298655b5670aab4932418410370dc31d7455e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
/*
 * 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.
 */

/**
 * Defines the interface all connections use to communicate with the forwarder.
 *
 * @code
 *
 *   static MetisIoOperations _template = {
 *      .closure           = NULL,
 *      .send              = &_metisEtherConnection_Send,
 *      .getRemoteAddress  = &_metisEtherConnection_GetRemoteAddress,
 *      .getAddressPair    = &_metisEtherConnection_GetAddressPair,
 *      .getConnectionId   = &_metisEtherConnection_GetConnectionId,
 *      .isUp              = &_metisEtherConnection_IsUp,
 *      .isLocal           = &_metisEtherConnection_IsLocal,
 *      .destroy           = &_metisEtherConnection_DestroyOperations,
 *      .class             = &_metisEtherConnection_Class,
 *      .getConnectionType = &_metisEtherConnection_getConnectionType
 *   };
 *
 *   MetisIoOperations *
 *   metisEtherConnection_Create(MetisForwarder *metis, MetisGenericEther *ether, MetisAddressPair *pair)
 *   {
 *      _MetisEtherState *etherConnState = parcMemory_Allocate(sizeof(_MetisEtherState));
 *      // Fill in etherConnState with instance variables
 *
 *      MetisIoOperations *io_ops = parcMemory_Allocate(sizeof(MetisIoOperations));
 *      memcpy(io_ops, &_template, sizeof(MetisIoOperations));
 *      io_ops->closure = etherConnState;
 *      // Add to connection table, send missives about connection state
 *
 *      return op_ops;
 *   }
 * @endcode
 *
 */

/**
 * I/O is built around a callback structure.  The connection table contains an operations
 * structure built around function pointers.  These allow the connection table to be
 * agnostic about underlying connections.
 */

#ifndef Metis_metis_io_h
#define Metis_metis_io_h

#include <ccnx/api/control/cpi_Connection.h>
#include <ccnx/api/control/cpi_Address.h>
#include <ccnx/forwarder/metis/io/metis_AddressPair.h>
#include <ccnx/forwarder/metis/core/metis_Message.h>
#include <ccnx/forwarder/metis/core/metis_Ticks.h>

//packet types for probing
#define METIS_PACKET_TYPE_PROBE_REQUEST 5
#define METIS_PACKET_TYPE_PROBE_REPLY 6

struct metis_io_ops;
typedef struct metis_io_ops MetisIoOperations;

/**
 * @typedef MetisIoOperations
 * @abstract The IO Operations structure abstracts an connection's properties and send() method
 * @constant context Implementation specific opaque data, passed back on each call
 * @constant send function pointer to send a message, does not destroy the message
 * @constant getRemoteAddress function pointer to return the "to" address associated with the connection.
 *           Some connections might not have a specific peer, such as multicast, where its the group address.
 * @constant isUp test if the connection is up, ready to send a message.
 * @constant isLocal test if the connection is local to the host.
 * @constant getConnectionId returns the Metis id for the connection.
 * @constant destroy releases a refernce count on the connection and possibly destroys the connection.
 * @constant class A unique identifier for each class that instantiates MetisIoOperations.
 * @constant getConnectionType Returns the type of connection (TCP, UDP, L2, etc.) of the underlying connection.
 * @discussion <#Discussion#>
 */
struct metis_io_ops {
    void *closure;
    bool (*send)(MetisIoOperations *ops, const CPIAddress *nexthop, MetisMessage *message);
    const CPIAddress *       (*getRemoteAddress)(const MetisIoOperations *ops);
    const MetisAddressPair * (*getAddressPair)(const MetisIoOperations *ops);
    bool (*isUp)(const MetisIoOperations *ops);
    bool (*isLocal)(const MetisIoOperations *ops);
    unsigned (*getConnectionId)(const MetisIoOperations *ops);
    void (*destroy)(MetisIoOperations **opsPtr);
    const void * (*class)(const MetisIoOperations *ops);
    CPIConnectionType (*getConnectionType)(const MetisIoOperations *ops);
    MetisTicks (*sendProbe)(MetisIoOperations *ops, unsigned probeType);
};

/**
 * Returns the closure of the interface
 *
 * The creator of the closure sets this parameter to store its state.
 *
 * @param [in] ops A concrete instance of the interface
 *
 * @return The value set by the concrete instance of the interface.
 *
 * Example:
 * @clode
 * {

 * }
 * @endcode
 */
void *metisIoOperations_GetClosure(const MetisIoOperations *ops);

/**
 * Release all memory related to the interface and implementation
 *
 * This function must release all referenced memory in the concrete implementation and
 * memory related to the MetisIoOperations.  It should NULL the input parameter.
 *
 * @param [in,out] opsPtr Pointer to interface.  Will be NULLed.
 *
 * Example:
 * @code
 *
 *   static void
 *   _metisEtherConnection_InternalRelease(_MetisEtherState *etherConnState)
 *   {
 *      // release internal state of _MetisEtherState
 *   }
 *
 *   static void
 *   _metisEtherConnection_Release(MetisIoOperations **opsPtr)
 *   {
 *      MetisIoOperations *ops = *opsPtr;
 *
 *      _MetisEtherState *etherConnState = (_MetisEtherState *) metisIoOperations_GetClosure(ops);
 *      _metisEtherConnection_InternalRelease(etherConnState);
 *
 *      parcMemory_Deallocate((void **) &ops);
 *   }
 *
 *   MetisIoOperations *
 *   metisEtherConnection_Create(MetisForwarder *metis, MetisGenericEther *ether, MetisAddressPair *pair)
 *   {
 *      size_t allocationSize = sizeof(_MetisEtherState) + sizeof(MetisIoOperations);
 *      MetisIoOperations *ops = parcMemory_AllocateAndClear(allocationSize);
 *      if (ops) {
 *         // fill in other interface functions
 *         ops->destroy = &_metisEtherConnection_Release;
 *         ops->closure = (uint8_t *) ops + sizeof(MetisIoOperations);
 *
 *         _MetisEtherState *etherConnState = metisIoOperations_GetClosure(ops);
 *         // fill in Ethernet state
 *      }
 *      return ops;
 *   }
 * @endcode
 */
void metisIoOperations_Release(MetisIoOperations **opsPtr);

/**
 * Sends the specified MetisMessage out this connection
 *
 * The the implementation of send may queue the message, it must acquire a reference to it.
 *
 * @param [in] ops The connection implementation.
 * @param [in] nexthop On multiple access networks, this parameter might be used, usually NULL.
 * @param [in] message The message to send.  If the message will be queued, it will be acquired.
 *
 * @return true The message was sent or queued
 * @retrun false An error occured and the message will not be sent or queued
 *
 * Example:
 * @code
 * {
 *     if (metisIoOperations_IsUp(conn->ops)) {
 *        return metisIoOperations_Send(conn->ops, NULL, message);
 *     }
 * }
 * @endcode
 */
bool metisIoOperations_Send(MetisIoOperations *ops, const CPIAddress *nexthop, MetisMessage *message);

/**
 * A connection is made up of a local and a remote address.  This function returns the remote address.
 *
 * Represents the destination endpoint of the communication.
 *
 * @param [in] ops The connection implementation.
 *
 * @return non-null The remote address
 * @return null The connection does not have a remote address
 *
 * Example:
 * @code
 * {
 *    CPIAddress *local =  cpiAddress_CreateFromLink((uint8_t []) { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }, 6);
 *    CPIAddress *remote = cpiAddress_CreateFromLink((uint8_t []) { 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, 6);
 *    MetisAddressPair *pair = metisAddressPair_Create(local, remote);
 *    MetisIoOperations *ops = metisEtherConnection_Create(metis, ether, pair);
 *
 *    const CPIAddress *test = metisIoOperations_GetRemoteAddress(ops);
 *    assertTrue(cpiAddress_Equals(test, remote), "Wrong remote address");
 *    metisIoOperations_Release(&ops);
 *    metisAddressPair_Release(&pair);
 *    cpiAddress_Destroy(&local);
 *    cpiAddress_Destroy(&remote);
 * }
 * @endcode
 */
const CPIAddress *metisIoOperations_GetRemoteAddress(const MetisIoOperations *ops);

/**
 * A connection is made up of a local and a remote address.  This function returns the address pair.
 *
 * Represents the destination endpoint of the communication.
 *
 * @param [in] ops The connection implementation.
 *
 * @return non-null The address pair
 * @return null An error.
 *
 * Example:
 * @code
 * {
 *    CPIAddress *local =  cpiAddress_CreateFromLink((uint8_t []) { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }, 6);
 *    CPIAddress *remote = cpiAddress_CreateFromLink((uint8_t []) { 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, 6);
 *    MetisAddressPair *pair = metisAddressPair_Create(local, remote);
 *    MetisIoOperations *ops = metisEtherConnection_Create(metis, ether, pair);
 *
 *    const MetisAddressPair *test = metisIoOperations_GetAddressPair(ops);
 *    assertTrue(metisAddressPair(test, pair), "Wrong address pair");
 *    metisIoOperations_Release(&ops);
 *    metisAddressPair_Release(&pair);
 *    cpiAddress_Destroy(&local);
 *    cpiAddress_Destroy(&remote);
 * }
 * @endcode
 */
const MetisAddressPair *metisIoOperations_GetAddressPair(const MetisIoOperations *ops);

/**
 * Returns true if the underlying connection is in operation
 *
 * An UP connection is able to send and receive packets. If a subsystem needs to take actions
 * when a connection goes UP or DOWN, it should subscribe as a MetisMissive listener.
 *
 * @param [in] ops The connection implementation.
 *
 * @return true The connection is UP
 * @return false The connection is not UP
 *
 * Example:
 * @code
 * {
 *     if (metisIoOperations_IsUp(conn->ops)) {
 *        return metisIoOperations_Send(conn->ops, NULL, message);
 *     }
 * }
 * @endcode
 */
bool metisIoOperations_IsUp(const MetisIoOperations *ops);

/**
 * If the remote address is local to this system, returns true
 *
 * Will return true if an INET or INET6 connection is on localhost.  Will return
 * true for AF_UNIX.  An Ethernet connection is not local.
 *
 * @param [in] ops The connection implementation.
 *
 * @return true The remote address is local to the system
 * @return false The remote address is not local
 *
 * Example:
 * @code
 * {
 *     // Is the ingress connection remote?  If so check for non-zero and decrement
 *     if (!metisIoOperations(ingressConnectionOps) {
 *        uint8_t hoplimit = metisMessage_GetHopLimit(interestMessage);
 *        if (hoplimit == 0) {
 *           // error
 *        } else {
 *           hoplimit--;
 *        }
 *        // take actions on hoplimit
 *     }
 * }
 * @endcode
 */
bool metisIoOperations_IsLocal(const MetisIoOperations *ops);

/**
 * Returns the connection ID represented by this MetisIoOperations in the ConnectionTable.
 *
 * <#Paragraphs Of Explanation#>
 *
 * @param [in] ops The connection implementation.
 *
 * @return number The connection ID in the connection table.
 *
 * Example:
 * @code
 * {
 *     unsigned id = metisIoOperations_GetConnectionId(ingressIoOps);
 *     const MetisConnection *conn = metisConnectionTable_FindById(metis->connectionTable, id);
 * }
 * @endcode
 */
unsigned metisIoOperations_GetConnectionId(const MetisIoOperations *ops);

/**
 * A pointer that represents the class of the connection
 *
 * Each concrete implementation has a class pointer that is unique to the implementation (not instance).
 * Each implementation is free to choose how to determine the value, so long as it is unique on the system.
 * This is a system-local value.
 *
 * @param [in] ops The connection implementation.
 *
 * @return non-null A pointer value unique to the implementation (not instance).
 *
 * Example:
 * @code
 *   bool
 *   metisEtherConnection_IsInstanceOf(const MetisConnection *conn)
 *   {
 *      bool result = false;
 *      if (conn != NULL) {
 *         MetisIoOperations *ops = metisConnection_GetIoOperations(conn);
 *         const void *class = metisIoOperations_Class(ops);
 *         result = (class == _metisEtherConnection_Class(ops));
 *      }
 *      return result;
 *   }
 * @endcode
 */
const void *metisIoOperations_Class(const MetisIoOperations *ops);

/**
 * Returns the transport type of the connection (TCP, UDP, L2, etc.).
 *
 * TCP and AF_UNIX are both stream connections and will both return "cpiConnection_TCP".
 * Ethernet will return "cpiConnection_L2".
 *
 * @param [in] ops The connection implementation.
 *
 * @return cpiConnection_TCP A TCP4, TCP6, or AF_UNIX connection
 * @return cpiConnection_UDP A UDP4 or UDP6 connection
 * @return cpiConnection_L2 An Ethernet connection
 *
 * Example:
 * @code
 * {
 *     CPIConnectionType type = metisIoOperations_GetConnectionType(metisConnection_GetIoOperations(connection));
 *     CPIConnection *cpiConn = cpiConnection_Create(metisConnection_GetConnectionId(connection), localAddress, remoteAddress, type);
 * }
 * @endcode
 */
CPIConnectionType metisIoOperations_GetConnectionType(const MetisIoOperations *ops);

MetisTicks metisIoOperations_SendProbe(MetisIoOperations *ops, unsigned probeType);
#endif // Metis_metis_io_h