aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/messenger
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/messenger')
-rwxr-xr-xhicn-light/src/messenger/CMakeLists.txt32
-rwxr-xr-xhicn-light/src/messenger/messenger.c171
-rwxr-xr-xhicn-light/src/messenger/messenger.h69
-rwxr-xr-xhicn-light/src/messenger/messengerRecipient.c62
-rwxr-xr-xhicn-light/src/messenger/messengerRecipient.h104
-rwxr-xr-xhicn-light/src/messenger/missive.c54
-rwxr-xr-xhicn-light/src/messenger/missive.h89
-rwxr-xr-xhicn-light/src/messenger/missiveDeque.c77
-rwxr-xr-xhicn-light/src/messenger/missiveDeque.h55
-rwxr-xr-xhicn-light/src/messenger/missiveType.h55
10 files changed, 768 insertions, 0 deletions
diff --git a/hicn-light/src/messenger/CMakeLists.txt b/hicn-light/src/messenger/CMakeLists.txt
new file mode 100755
index 000000000..92bc13b5b
--- /dev/null
+++ b/hicn-light/src/messenger/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Copyright (c) 2017-2019 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.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/missiveDeque.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/missive.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/missiveType.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/messenger.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/messengerRecipient.h
+)
+
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/messenger.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/messengerRecipient.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/missive.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/missiveDeque.c
+)
+
+set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
diff --git a/hicn-light/src/messenger/messenger.c b/hicn-light/src/messenger/messenger.c
new file mode 100755
index 000000000..26c7a85e2
--- /dev/null
+++ b/hicn-light/src/messenger/messenger.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017-2019 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.
+ */
+
+/**
+ *
+ * The messenger is contructued with a reference to the forwarder's dispatcher
+ * so it can schedule future events. When someone calls messenger_Send(...), it
+ * will put the message on a queue. If the queue was empty, it will scheudle
+ * itself to be run. By running the queue in a future dispatcher slice, it
+ * guarantees that there will be no re-entrant behavior between callers and
+ * message listeners.
+ *
+ * A recipient will receive a reference counted copy of the missive, so it must
+ * call
+ * {@link missive_Release} on it.
+ *
+ */
+
+#include <parc/algol/parc_ArrayList.h>
+#include <parc/algol/parc_Event.h>
+#include <parc/algol/parc_EventScheduler.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/assert/parc_Assert.h>
+#include <src/config.h>
+#include <stdio.h>
+
+#include <src/messenger/messenger.h>
+#include <src/messenger/missiveDeque.h>
+
+struct messenger {
+ PARCArrayList *callbacklist;
+ Dispatcher *dispatcher;
+ MissiveDeque *eventQueue;
+
+ PARCEventTimer *timerEvent;
+};
+
+static void messenger_Dequeue(int fd, PARCEventType which_event,
+ void *messengerVoidPtr);
+
+// =========================================
+// Public API
+
+Messenger *messenger_Create(Dispatcher *dispatcher) {
+ Messenger *messenger = parcMemory_AllocateAndClear(sizeof(Messenger));
+ parcAssertNotNull(messenger, "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(Messenger));
+
+ // NULL destroyer because we're storing structures owned by the caller
+ messenger->dispatcher = dispatcher;
+ messenger->callbacklist = parcArrayList_Create(NULL);
+ messenger->eventQueue = missiveDeque_Create();
+
+ // creates the timer, but does not start it
+ messenger->timerEvent =
+ dispatcher_CreateTimer(dispatcher, false, messenger_Dequeue, messenger);
+
+ return messenger;
+}
+
+void messenger_Destroy(Messenger **messengerPtr) {
+ parcAssertNotNull(messengerPtr, "Parameter must be non-null double pointer");
+ parcAssertNotNull(*messengerPtr,
+ "Parameter must dereference to non-null pointer");
+
+ Messenger *messenger = *messengerPtr;
+ parcArrayList_Destroy(&messenger->callbacklist);
+ missiveDeque_Release(&messenger->eventQueue);
+ dispatcher_DestroyTimerEvent(messenger->dispatcher, &messenger->timerEvent);
+ parcMemory_Deallocate((void **)&messenger);
+ *messengerPtr = NULL;
+}
+
+void messenger_Send(Messenger *messenger, Missive *missive) {
+ parcAssertNotNull(messenger, "Parameter messenger must be non-null");
+ parcAssertNotNull(missive, "Parameter event must be non-null");
+
+ missiveDeque_Append(messenger->eventQueue, missive);
+ if (missiveDeque_Size(messenger->eventQueue) == 1) {
+ // We need to scheudle ourself when an event is added to an empty queue
+
+ // precondition: timer should not be running.
+ struct timeval immediateTimeout = {0, 0};
+ dispatcher_StartTimer(messenger->dispatcher, messenger->timerEvent,
+ &immediateTimeout);
+ }
+}
+
+static void removeRecipient(Messenger *messenger,
+ const MessengerRecipient *recipient) {
+ // don't increment i in the loop
+ for (size_t i = 0; i < parcArrayList_Size(messenger->callbacklist);) {
+ const void *p = parcArrayList_Get(messenger->callbacklist, i);
+ if (p == recipient) {
+ // removing will compact the list, so next element will also be at i.
+ parcArrayList_RemoveAndDestroyAtIndex(messenger->callbacklist, i);
+ } else {
+ i++;
+ }
+ }
+}
+
+/**
+ * @function eventMessenger_Register
+ * @abstract Receive all event messages
+ */
+void messenger_Register(Messenger *messenger,
+ const MessengerRecipient *recipient) {
+ parcAssertNotNull(messenger, "Parameter messenger must be non-null");
+ parcAssertNotNull(recipient, "Parameter recipient must be non-null");
+
+ // do not allow duplicates
+ removeRecipient(messenger, recipient);
+
+ parcArrayList_Add(messenger->callbacklist, recipient);
+}
+
+/**
+ * @function eventMessenger_Unregister
+ * @abstract Stop receiving event messages
+ */
+void messenger_Unregister(Messenger *messenger,
+ const MessengerRecipient *recipient) {
+ parcAssertNotNull(messenger, "Parameter messenger must be non-null");
+ parcAssertNotNull(recipient, "Parameter recipient must be non-null");
+
+ removeRecipient(messenger, recipient);
+}
+
+/**
+ * Called by event scheduler to give us a slice in which to dequeue events
+ *
+ * Called inside an event callback, so we now have exclusive access to the
+ * system. Dequeues all pending events and calls all the listeners for each one.
+ *
+ * @param [in] fd unused, required for compliance with function prototype
+ * @param [in] which_event unused, required for compliance with function
+ * prototype
+ * @param [in] messengerVoidPtr A void* to Messenger
+ */
+static void messenger_Dequeue(int fd, PARCEventType which_event,
+ void *messengerVoidPtr) {
+ Messenger *messenger = (Messenger *)messengerVoidPtr;
+ parcAssertNotNull(messenger, "Called with null messenger pointer");
+
+ Missive *missive;
+ while ((missive = missiveDeque_RemoveFirst(messenger->eventQueue)) != NULL) {
+ for (size_t i = 0; i < parcArrayList_Size(messenger->callbacklist); i++) {
+ MessengerRecipient *recipient =
+ parcArrayList_Get(messenger->callbacklist, i);
+ parcAssertTrue(recipient, "Recipient is null at index %zu", i);
+
+ messengerRecipient_Deliver(recipient, missive_Acquire(missive));
+ }
+
+ // now let go of our reference to the missive
+ missive_Release(&missive);
+ }
+}
diff --git a/hicn-light/src/messenger/messenger.h b/hicn-light/src/messenger/messenger.h
new file mode 100755
index 000000000..f945e7e72
--- /dev/null
+++ b/hicn-light/src/messenger/messenger.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017-2019 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.
+ */
+
+/**
+ * The EventMessenger is the system that messages events between
+ * producers and consumers.
+ *
+ * Events are delivered in a deferred event cycle to avoid event callbacks
+ * firing when the event generator is still running.
+ */
+
+#ifndef messenger_h
+#define messenger_h
+
+#include <src/core/dispatcher.h>
+#include <src/messenger/messengerRecipient.h>
+#include <src/messenger/missive.h>
+
+struct messenger;
+typedef struct messenger Messenger;
+
+/**
+ * @function eventmessenger_Create
+ * @abstract Creates an event notification system
+ * @discussion
+ * Typically there's only one of these managed by forwarder.
+ *
+ * @param dispatcher is the event dispatcher to use to schedule events.
+ */
+Messenger *messenger_Create(Dispatcher *dispatcher);
+
+/**
+ * @function eventMessenger_Destroy
+ * @abstract Destroys the messenger system, no notification is sent
+ */
+void messenger_Destroy(Messenger **messengerPtr);
+
+/**
+ * @function eventMessenger_Send
+ * @abstract Send an event message, takes ownership of the event memory
+ */
+void messenger_Send(Messenger *messenger, Missive *missive);
+
+/**
+ * @function eventMessenger_Register
+ * @abstract Receive all event messages
+ */
+void messenger_Register(Messenger *messenger,
+ const MessengerRecipient *recipient);
+
+/**
+ * @function eventMessenger_Unregister
+ * @abstract Stop receiving event messages
+ */
+void messenger_Unregister(Messenger *messenger,
+ const MessengerRecipient *recipient);
+#endif // messenger_h
diff --git a/hicn-light/src/messenger/messengerRecipient.c b/hicn-light/src/messenger/messengerRecipient.c
new file mode 100755
index 000000000..14251f8eb
--- /dev/null
+++ b/hicn-light/src/messenger/messengerRecipient.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017-2019 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.
+ */
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/assert/parc_Assert.h>
+#include <src/config.h>
+#include <stdio.h>
+
+#include <src/messenger/messenger.h>
+#include <src/messenger/messengerRecipient.h>
+
+struct messenger_recipient {
+ void *context;
+ MessengerRecipientCallback *notify;
+};
+
+MessengerRecipient *messengerRecipient_Create(
+ void *recipientContext, MessengerRecipientCallback *recipientCallback) {
+ parcAssertNotNull(recipientCallback,
+ "Parameter recipientCallback must be non-null");
+
+ MessengerRecipient *recipient =
+ parcMemory_AllocateAndClear(sizeof(MessengerRecipient));
+ parcAssertNotNull(recipient, "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(MessengerRecipient));
+ recipient->context = recipientContext;
+ recipient->notify = recipientCallback;
+ return recipient;
+}
+
+void messengerRecipient_Destroy(MessengerRecipient **recipientPtr) {
+ parcAssertNotNull(recipientPtr, "Parameter must be non-null double pointer");
+ parcAssertNotNull(*recipientPtr,
+ "Parameter must dereference to non-null pointer");
+
+ parcMemory_Deallocate((void **)recipientPtr);
+ *recipientPtr = NULL;
+}
+
+void *messengerRecipient_GetRecipientContext(MessengerRecipient *recipient) {
+ parcAssertNotNull(recipient, "Parameter must be non-null");
+
+ return recipient->context;
+}
+
+void messengerRecipient_Deliver(MessengerRecipient *recipient,
+ Missive *missive) {
+ parcAssertNotNull(recipient, "Parameter must be non-null");
+ recipient->notify(recipient, missive);
+}
diff --git a/hicn-light/src/messenger/messengerRecipient.h b/hicn-light/src/messenger/messengerRecipient.h
new file mode 100755
index 000000000..66d8f40f5
--- /dev/null
+++ b/hicn-light/src/messenger/messengerRecipient.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2017-2019 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 messengerRecipient.h
+ * @brief A recipient represents the entity that will recieve a Missive from the
+ * Messenger.
+ *
+ * A recipient is identified by the pair (contenxt, callback). The context is
+ * the recipients context, such as it's object pointer. The callback is the
+ * function the recipient uses to receive a Missive.
+ *
+ * If the receiver is going to do a lot of work or potentially send other
+ * missives, the receiver should queue the received notifications and process
+ * them in its own slice.
+ *
+ * A recipient will receive a reference counted copy of the missive, so it must
+ * call
+ * {@link missive_Release} on it.
+ *
+ *
+ */
+
+#ifndef messengerRecipient_h
+#define messengerRecipient_h
+
+#include <src/messenger/missive.h>
+
+struct messenger_recipient;
+typedef struct messenger_recipient MessengerRecipient;
+
+/**
+ * @typedef MessengerRecipientCallback
+ * @abstract A recipient implements a callback to receive Missives.
+ * @constant recipient The recipient to recieve the missive
+ * @constant missive The missive, recipient must call {@link missive_Release} on
+ * it
+ */
+typedef void(MessengerRecipientCallback)(MessengerRecipient *recipient,
+ Missive *missive);
+
+/**
+ * Creates a Recipient, which represents a reciever of missives.
+ *
+ * Creates a Recipient that can be registerd with the Messenger using {@link
+ * messenger_Register}.
+ *
+ * @param [in] recipientContext This pointer will be passed back to the
+ * recipient with each missive, may be NULL
+ * @param [in] recipientCallback The function that receives the missive, must be
+ * non-NULL.
+ *
+ * @return non-null A recipient object
+ */
+MessengerRecipient *messengerRecipient_Create(
+ void *recipientContext, MessengerRecipientCallback *recipientCallback);
+
+/**
+ * Destroys a recipient. You should unregister it first.
+ *
+ * Destroying a recipient does not unregister it, so be sure to call
+ * {@link messenger_Unregister} first.
+ *
+ * @param [in,out] recipientPtr Double pointer to the recipient to destroy, will
+ * be NULL'd.
+ */
+void messengerRecipient_Destroy(MessengerRecipient **recipientPtr);
+
+/**
+ * Returns the recipient context passed on Create
+ *
+ * @param [in] recipient The recipient object
+ *
+ * @return pointer The context pointer used to create the object, maybe NULL
+ */
+void *messengerRecipient_GetRecipientContext(MessengerRecipient *recipient);
+
+/**
+ * Delivers a Missive to the recipient
+ *
+ * Passes the missive to the recipients callback.
+ *
+ * A recipient will receive a reference counted copy of the missive, so it must
+ * call
+ * {@link missive_Release} on it.
+ *
+ * @param [in] recipient The receiver
+ * @param [in] missive The message to send
+ */
+void messengerRecipient_Deliver(MessengerRecipient *recipient,
+ Missive *missive);
+#endif // messengerRecipient_h
diff --git a/hicn-light/src/messenger/missive.c b/hicn-light/src/messenger/missive.c
new file mode 100755
index 000000000..a8bcb0282
--- /dev/null
+++ b/hicn-light/src/messenger/missive.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017-2019 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.
+ */
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_Object.h>
+#include <parc/assert/parc_Assert.h>
+#include <src/config.h>
+#include <stdio.h>
+
+#include <src/messenger/missive.h>
+
+struct missive {
+ MissiveType missiveType;
+ unsigned connectionid;
+};
+
+parcObject_Override(Missive, PARCObject, .isLockable = false);
+
+Missive *missive_Create(MissiveType missiveType, unsigned connectionid) {
+ Missive *missive = parcObject_CreateInstance(Missive);
+ missive->missiveType = missiveType;
+ missive->connectionid = connectionid;
+ return missive;
+}
+
+Missive *missive_Acquire(const Missive *missive) {
+ return parcObject_Acquire(missive);
+}
+
+void missive_Release(Missive **missivePtr) {
+ parcObject_Release((void **)missivePtr);
+}
+
+MissiveType missive_GetType(const Missive *missive) {
+ parcAssertNotNull(missive, "Parameter missive must be non-null");
+ return missive->missiveType;
+}
+
+unsigned missive_GetConnectionId(const Missive *missive) {
+ parcAssertNotNull(missive, "Parameter missive must be non-null");
+ return missive->connectionid;
+}
diff --git a/hicn-light/src/messenger/missive.h b/hicn-light/src/messenger/missive.h
new file mode 100755
index 000000000..33f3ef8b8
--- /dev/null
+++ b/hicn-light/src/messenger/missive.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017-2019 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 missive.h
+ * @brief A Missive is a status message sent over a broadcast channel inside
+ * hicn-light
+ *
+ * Recipients use {@link messenger_Register} to receive missives. They are
+ * broadcast to all recipients.
+ *
+ */
+#ifndef missive_h
+#define missive_h
+
+#include <src/messenger/missiveType.h>
+
+struct missive;
+typedef struct missive Missive;
+
+/**
+ * Creates a Missive and sets the reference count to 1
+ *
+ * A Missive may be sent to listeners of the Messenger to inform them of events
+ * on a connection id.
+ *
+ * @param [in] MissiveType The event type
+ * @param [in] connectionid The relevant conneciton id
+ *
+ * @return non-null A message
+ * @retrun null An error
+ */
+Missive *missive_Create(MissiveType missiveType, unsigned connectionid);
+
+/**
+ * Acquire a reference counted copy
+ *
+ * Increases the reference count by 1 and returns the original object.
+ *
+ * @param [in] missive An allocated missive
+ *
+ * @return non-null The original missive with increased reference count
+ */
+Missive *missive_Acquire(const Missive *missive);
+
+/**
+ * Releases a reference counted copy.
+ *
+ * If it is the last reference, the missive is freed.
+ *
+ * @param [in,out] missivePtr Double pointer to a missive, will be nulled.
+ */
+void missive_Release(Missive **missivePtr);
+
+/**
+ * Returns the type of the missive
+ *
+ * Returns the type of event the missive represents
+ *
+ * @param [in] missive An allocated missive
+ *
+ * @return MissiveType The event type
+ */
+MissiveType missive_GetType(const Missive *missive);
+
+/**
+ * Returns the connection ID of the missive
+ *
+ * An event is usually associated with a connection id (i.e. the I/O channel
+ * that originaged the event).
+ *
+ * @param [in] missive An allocated missive
+ *
+ * @return number The relevant connection id.
+ */
+unsigned missive_GetConnectionId(const Missive *missive);
+#endif // missive_h
diff --git a/hicn-light/src/messenger/missiveDeque.c b/hicn-light/src/messenger/missiveDeque.c
new file mode 100755
index 000000000..418027d7a
--- /dev/null
+++ b/hicn-light/src/messenger/missiveDeque.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017-2019 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.
+ */
+
+/**
+ * A type-safe wrapper for Missives around a {@link PARCDeque}. We only
+ * implement the subset of functions used.
+ *
+ */
+
+#include <parc/algol/parc_Deque.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/assert/parc_Assert.h>
+#include <src/config.h>
+#include <stdio.h>
+
+#include <src/messenger/missive.h>
+#include <src/messenger/missiveDeque.h>
+
+struct missive_deque {
+ PARCDeque *queue;
+};
+
+MissiveDeque *missiveDeque_Create(void) {
+ MissiveDeque *missiveDeque =
+ parcMemory_AllocateAndClear(sizeof(MissiveDeque));
+ parcAssertNotNull(missiveDeque,
+ "parcMemory_AllocateAndClear(%zu) returned NULL",
+ sizeof(MissiveDeque));
+ missiveDeque->queue = parcDeque_Create();
+ return missiveDeque;
+}
+
+void missiveDeque_Release(MissiveDeque **dequePtr) {
+ parcAssertNotNull(dequePtr, "Double pointer must be non-null");
+ parcAssertNotNull(*dequePtr, "Double pointer must dereference to non-null");
+ MissiveDeque *missiveDeque = *dequePtr;
+
+ // flush the queue
+ while (!parcDeque_IsEmpty(missiveDeque->queue)) {
+ Missive *missive = missiveDeque_RemoveFirst(missiveDeque);
+ missive_Release(&missive);
+ }
+
+ parcDeque_Release(&missiveDeque->queue);
+ parcMemory_Deallocate((void **)&missiveDeque);
+ *dequePtr = NULL;
+}
+
+MissiveDeque *missiveDeque_Append(MissiveDeque *deque, Missive *missive) {
+ parcAssertNotNull(deque, "Parameter deque must be non-null");
+ parcAssertNotNull(missive, "Parameter missive must be non-null");
+
+ parcDeque_Append(deque->queue, missive);
+ return deque;
+}
+
+Missive *missiveDeque_RemoveFirst(MissiveDeque *deque) {
+ parcAssertNotNull(deque, "Parameter deque must be non-null");
+ return (Missive *)parcDeque_RemoveFirst(deque->queue);
+}
+
+size_t missiveDeque_Size(const MissiveDeque *deque) {
+ parcAssertNotNull(deque, "Parameter deque must be non-null");
+ return parcDeque_Size(deque->queue);
+}
diff --git a/hicn-light/src/messenger/missiveDeque.h b/hicn-light/src/messenger/missiveDeque.h
new file mode 100755
index 000000000..c6f955ce0
--- /dev/null
+++ b/hicn-light/src/messenger/missiveDeque.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2019 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 missiveDeque
+ * @brief Double ended queue of Missives
+ *
+ * Used to queue Missives. This is a type-safe wrapper around {@link PARCDeque}
+ *
+ */
+
+#ifndef missiveDeque_h
+#define missiveDeque_h
+
+struct missive_deque;
+
+typedef struct missive_deque MissiveDeque;
+
+/**
+ * Create a `PARCDeque` instance with the default element equals function.
+ *
+ * The queue is created with no elements.
+ *
+ * The default element equals function is used by the `parcDeque_Equals`
+ * function and simply compares the values using the `==` operator. Users that
+ * need more sophisticated comparisons of the elements need to supply their own
+ * function via the `parcDeque_CreateCustom` function.
+ *
+ * @return non-NULL A pointer to a PARCDeque instance.
+ */
+MissiveDeque *missiveDeque_Create(void);
+
+void missiveDeque_Release(MissiveDeque **dequePtr);
+
+/**
+ * Appends the missive to the queue, taking ownership of the memory
+ */
+MissiveDeque *missiveDeque_Append(MissiveDeque *deque, Missive *missive);
+
+Missive *missiveDeque_RemoveFirst(MissiveDeque *deque);
+
+size_t missiveDeque_Size(const MissiveDeque *deque);
+#endif // missiveDeque_h
diff --git a/hicn-light/src/messenger/missiveType.h b/hicn-light/src/messenger/missiveType.h
new file mode 100755
index 000000000..b0d9c7704
--- /dev/null
+++ b/hicn-light/src/messenger/missiveType.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2019 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 missiveType
+ * @brief Defines what a Missive represents
+ *
+ * Currently, missives only carry information about the state of a connection
+ * (created, up, down, closed, destroyed).
+ *
+ */
+
+#ifndef missiveType_h
+#define missiveType_h
+
+/**
+ * @typedef Represents the state of a connection
+ * @abstract CREATE is the initial state. UP & DOWN are recurrent states.
+ * CLOSED is transient. DESTROYED is the terminal state.
+ * @constant MissiveType_ConnectionCreate Connection created (new)
+ * @constant MissiveType_ConnectionUp Connection is active and passing
+ * data
+ * @constant MissiveType_ConnectionDown Connection is inactive and cannot
+ * pass data
+ * @constant MissiveType_ConnectionClosed Connection closed and will be
+ * destroyed
+ * @constant MissiveType_ConnectionDestroyed Connection destroyed
+ * @discussion State transitions:
+ * initial -> CREATE
+ * CREATE -> (UP | DOWN)
+ * UP -> (DOWN | DESTROYED)
+ * DOWN -> (UP | CLOSED | DESTROYED)
+ * CLOSED -> DESTROYED
+ * DESTROYED -> terminal
+ */
+typedef enum {
+ MissiveType_ConnectionCreate,
+ MissiveType_ConnectionUp,
+ MissiveType_ConnectionDown,
+ MissiveType_ConnectionClosed,
+ MissiveType_ConnectionDestroyed
+} MissiveType;
+#endif // missiveType_h