static _TemplateLinkData *
_TemplateLinkData_Create()
{
    _TemplateLinkData *linkData = parcMemory_AllocateAndClear(sizeof(_TemplateLinkData));
    assertNotNull(linkData, "Could not create private data for new link");

    // Any identity name can be used as long as it's guaranteed to be unique.
    // Typically, we use some identifying attribute of the link (such as its sockaddr info)
    // In this case we're using the current time.
    CCNxTimeStamp *timeStamp = ccnxTimeStamp_CreateFromCurrentUTCTime();
    char *timeString = ccnxTimeStamp_ToString(timeStamp);
    ccnxTimeStamp_Release(&timeStamp);
    linkData->linkIdentity = parcMemory_StringDuplicate(timeString, strlen(timeString));
    parcMemory_Deallocate(&timeString);

    linkData->queue = parcDeque_Create();

    return linkData;
}
static void
_demuxDelivery(AthenaTransportLink *athenaTransportLink, CCNxMetaMessage *ccnxMetaMessage, struct sockaddr_in *peerAddress, socklen_t peerAddressLength)
{
    struct _UDPLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink);

    AthenaTransportLink *demuxLink = parcHashCodeTable_Get(linkData->multiplexTable, (void *) _hashAddress(peerAddress));

    // If it's an unknown peer, try to create a new link
    if (demuxLink == NULL) {
        _UDPLinkData *newLinkData = _UDPLinkData_Create();

        // We use our parents fd to send, and receive demux'd messages from our parent on our queue
        newLinkData->fd = dup(linkData->fd);
        newLinkData->queue = parcDeque_Create();
        assertNotNull(newLinkData->queue, "Could not create data queue for new link");

        newLinkData->link.myAddressLength = linkData->link.myAddressLength;
        memcpy(&newLinkData->link.myAddress, &linkData->link.myAddress, linkData->link.myAddressLength);

        newLinkData->link.peerAddressLength = peerAddressLength;
        memcpy(&newLinkData->link.peerAddress, peerAddress, peerAddressLength);

        demuxLink = _newLink(athenaTransportLink, newLinkData);
        if (demuxLink) {
            parcHashCodeTable_Add(linkData->multiplexTable, (void *) _hashAddress(peerAddress), demuxLink);
        }
    }

    // If there's no existing link and a new one can't be created, drop the message
    if (demuxLink == NULL) {
        ccnxMetaMessage_Release(&ccnxMetaMessage);
        return;
    }

    _queueMessage(demuxLink, ccnxMetaMessage);
}