Ejemplo n.º 1
0
int
athenaTransportLinkAdapter_CloseByName(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, const char *linkName)
{
    if (athenaTransportLinkAdapter->listenerList) {
        for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->listenerList); index++) {
            AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->listenerList, index);
            if (strcmp(athenaTransportLink_GetName(athenaTransportLink), linkName) == 0) {
                athenaTransportLink_Close(athenaTransportLink);
                return 0;
            }
        }
    }
    if (athenaTransportLinkAdapter->instanceList) {
        for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->instanceList); index++) {
            AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, index);
            if (athenaTransportLink) {
                if (strcmp(athenaTransportLink_GetName(athenaTransportLink), linkName) == 0) {
                    athenaTransportLink_Close(athenaTransportLink);
                    return 0;
                }
            }
        }
    }
    errno = ENOENT;
    return -1;
}
Ejemplo n.º 2
0
/**
 * @abstract add a new link instance to the AthenaTransportLinkAdapter instance list
 * @discussion
 *
 * When athenaTransportLinkAdapter_Open is called on a link specific module, the module instantiates
 * the link and then creates a new AthenaTransportLink to interface with the AthenaTransportLinkAdapter.
 * The AthenaTransportLinkModule passes the new AthenaTransportLink to the AthenaTransportLinkAdapter by
 * calling AthenaTransportLinkAdapter_AddLink with the new link AthenaTransportLink data. The AthenaTransportLinkAdapter
 * then places the new link instance on its internal instance list in a pending state until it has been verified and ensures
 * that the new link doesn't collide (i.e. by name) with any currently registered link before returning success.
 *
 * New routable links are placed into instanceList slots that have previously been vacated before being added
 * to the end of the instanceList.  This is in order to keep bit vectors that are based on the instanceList as
 * small as is necessary.
 *
 * @param [in] athenaTransportLinkAdapter link adapter instance
 * @param [in] linkInstance instance structure created by the link specific module
 * @return 0 on success, -1 with errno set to indicate the error
 *
 * Example:
 * @code
 * {
 * }
 * @endcode
 */
static int
_athenaTransportLinkAdapter_AddLink(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, AthenaTransportLink *newTransportLink)
{
    int linkId = -1;

    // Check for existing linkName in listenerList
    if (athenaTransportLinkAdapter->listenerList) {
        for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->listenerList); index++) {
            AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->listenerList, index);
            if (strcmp(athenaTransportLink_GetName(athenaTransportLink), athenaTransportLink_GetName(newTransportLink)) == 0) {
                errno = EADDRINUSE; // name is already in listenerList
                return -1;
            }
        }
    }

    // Check for existing linkName in the instanceList
    if (athenaTransportLinkAdapter->instanceList) {
        for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->instanceList); index++) {
            AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, index);
            if (athenaTransportLink) {
                if (strcmp(athenaTransportLink_GetName(athenaTransportLink), athenaTransportLink_GetName(newTransportLink)) == 0) {
                    errno = EADDRINUSE; // name is already in instanceList
                    return -1;
                }
            } else {
                // remember the first available index found along the way
                if (linkId == -1) {
                    linkId = index;
                }
            }
        }
    }

    // Add to listenerList or instanceList
    athenaTransportLink_Acquire(newTransportLink);
    if (athenaTransportLink_IsNotRoutable(newTransportLink)) { // listener
        bool result = parcArrayList_Add(athenaTransportLinkAdapter->listenerList, newTransportLink);
        assertTrue(result, "parcArrayList_Add failed to add new listener");
    } else { // routable link, add to instances using the last available id if one was seen
        if (linkId != -1) {
            parcArrayList_Set(athenaTransportLinkAdapter->instanceList, linkId, newTransportLink);
        } else {
            bool result = parcArrayList_Add(athenaTransportLinkAdapter->instanceList, newTransportLink);
            assertTrue(result, "parcArrayList_Add failed to add new link instance");
        }
    }

    // If any transport link has a registered file descriptor add it to the general polling list.
    int eventFd = athenaTransportLink_GetEventFd(newTransportLink);
    if (eventFd != -1) {
        _add_to_pollfdList(athenaTransportLinkAdapter, newTransportLink, eventFd);
    }
    return 0;
}
Ejemplo n.º 3
0
/**
 * @abstract called from below the link adapter to coordinate termination of a link instance
 * @discussion
 *
 * This is called exclusively from the Transport Link Module to instigate the removal of
 * an active link.  The link has been flagged closing by the originator.  This method
 * must ensure that all references to the link have been removed and then call the
 * instance close method to finish the operation.
 *
 * @param [in] athenaTransportLinkAdapter link adapter instance
 * @param [in] athenaTransportLink link instance to remove
 *
 * Example:
 * @code
 * {
 *
 * }
 * @endcode
 */
static void
_athenaTransportLinkAdapter_RemoveLink(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, AthenaTransportLink *athenaTransportLink)
{
    int linkId = -1;

    // if this is a listener it can simply be removed
    if (athenaTransportLink_IsNotRoutable(athenaTransportLink)) {
        if (athenaTransportLinkAdapter->listenerList) {
            for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->listenerList); index++) {
                AthenaTransportLink *transportLink = parcArrayList_Get(athenaTransportLinkAdapter->listenerList, index);
                if (athenaTransportLink == transportLink) {
                    parcArrayList_RemoveAtIndex(athenaTransportLinkAdapter->listenerList, index);
                    _remove_from_pollfdList(athenaTransportLinkAdapter, athenaTransportLink);
                    parcLog_Debug(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter), "listener removed: %s",
                                  athenaTransportLink_GetName(athenaTransportLink));
                    athenaTransportLink_Release(&athenaTransportLink);
                    return;
                }
            }
        }
    }

    // Remove from our internal instance list.
    // The index entry remains to be reused by links that are added in the future.
    if (athenaTransportLinkAdapter->instanceList) {
        for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->instanceList); index++) {
            AthenaTransportLink *transportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, index);
            if (athenaTransportLink == transportLink) {
                parcArrayList_Set(athenaTransportLinkAdapter->instanceList, index, NULL);
                _remove_from_pollfdList(athenaTransportLinkAdapter, athenaTransportLink);
                linkId = index;
                break;
            }
        }
    }

    assertFalse(linkId == -1, "Attempt to remove link not found in link adapter lists");

    // Callback to notify that the link has been removed and references need to be dropped.
    PARCBitVector *linkVector = parcBitVector_Create();
    parcBitVector_Set(linkVector, linkId);
    athenaTransportLinkAdapter->removeLink(athenaTransportLinkAdapter->removeLinkContext, linkVector);
    parcBitVector_Release(&linkVector);

    // we assume all references to the linkId associated with this instance have been
    // cleared from the PIT and FIB when removeLink returns.

    parcLog_Debug(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter),
                  "link removed: %s", athenaTransportLink_GetName(athenaTransportLink));

    athenaTransportLink_Release(&athenaTransportLink);
}
Ejemplo n.º 4
0
const char *
athenaTransportLinkAdapter_Open(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, PARCURI *connectionURI)
{
    AthenaTransportLinkModule *athenaTransportLinkModule;
    const char *moduleName = parcURI_GetScheme(connectionURI);

    if (moduleName == NULL) {
        errno = EINVAL;
        return NULL;
    }

    athenaTransportLinkModule = _LookupModule(athenaTransportLinkAdapter, moduleName);
    if (athenaTransportLinkModule == NULL) {
        athenaTransportLinkModule = _LoadModule(athenaTransportLinkAdapter, moduleName);
        if (athenaTransportLinkModule == NULL) {
            errno = ENOENT;
            return NULL;
        }
    }

    AthenaTransportLink *athenaTransportLink = athenaTransportLinkModule_Open(athenaTransportLinkModule, connectionURI);
    if (athenaTransportLink == NULL) {
        return NULL;
    }

    return athenaTransportLink_GetName(athenaTransportLink);
}
Ejemplo n.º 5
0
AthenaTransportLink *
athenaTransportLinkModule_Open(AthenaTransportLinkModule *athenaTransportLinkModule, PARCURI *connectionURI)
{
    AthenaTransportLink *athenaTransportLink = athenaTransportLinkModule->openMethod(athenaTransportLinkModule, connectionURI);
    if (athenaTransportLink) {
        athenaTransportLink_SetAddLinkCallback(athenaTransportLink,
                                               (AthenaTransportLink_AddLinkCallback *) _athenaTransportLinkModule_AddLink,
                                               athenaTransportLinkModule);

        int result = _athenaTransportLinkModule_AddLink(athenaTransportLinkModule, athenaTransportLink);
        if (result == -1) {
            int addLinkError = errno;
            parcLog_Error(athenaTransportLinkModule_GetLogger(athenaTransportLinkModule),
                          "Adding link %s failed: %s", athenaTransportLink_GetName(athenaTransportLink), strerror(errno));
            athenaTransportLink_Close(athenaTransportLink);
            errno = addLinkError;
            return NULL;
        }

        athenaTransportLink_SetRemoveLinkCallback(athenaTransportLink,
                                                  (AthenaTransportLink_RemoveLinkCallback *) _athenaTransportLinkModule_RemoveLink,
                                                  athenaTransportLinkModule);
    }
    return athenaTransportLink;
}
static void
_TemplateClose(AthenaTransportLink *athenaTransportLink)
{
    parcLog_Info(athenaTransportLink_GetLogger(athenaTransportLink),
                 "link %s closed", athenaTransportLink_GetName(athenaTransportLink));
    _TemplateLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink);
    _TemplateLinkData_Destroy(&linkData);
}
Ejemplo n.º 7
0
const char *
athenaTransportLinkAdapter_LinkIdToName(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, int linkId)
{
    if (athenaTransportLinkAdapter->instanceList == NULL) {
        return NULL;
    }
    if (linkId < parcArrayList_Size(athenaTransportLinkAdapter->instanceList)) {
        AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, linkId);
        if (athenaTransportLink) {
            return athenaTransportLink_GetName(athenaTransportLink);
        }
    }
    return NULL;
}
Ejemplo n.º 8
0
int
athenaTransportLinkAdapter_LinkNameToId(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, const char *linkName)
{
    if (athenaTransportLinkAdapter->instanceList == NULL) {
        return -1;
    }
    for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->instanceList); index++) {
        AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, index);
        if (athenaTransportLink) {
            if (strcmp(athenaTransportLink_GetName(athenaTransportLink), linkName) == 0) {
                return index;
            }
        }
    }
    return -1;
}
Ejemplo n.º 9
0
static AthenaTransportLink *
_newLink(AthenaTransportLink *athenaTransportLink, _UDPLinkData *newLinkData)
{
    // Accept a new tunnel connection.

    // Clone a new link from the current listener.
    const char *derivedLinkName = _createNameFromLinkData(&newLinkData->link);
    AthenaTransportLink *newTransportLink = athenaTransportLink_Clone(athenaTransportLink,
                                                                      derivedLinkName,
                                                                      _UDPSend,
                                                                      _UDPReceiveProxy,
                                                                      _UDPClose);
    if (newTransportLink == NULL) {
        parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink),
                      "athenaTransportLink_Clone failed");
        parcMemory_Deallocate(&derivedLinkName);
        _UDPLinkData_Destroy(&newLinkData);
        return NULL;
    }

    _setConnectLinkState(newTransportLink, newLinkData);

    // Send the new link up to be added.
    int result = athenaTransportLink_AddLink(athenaTransportLink, newTransportLink);
    if (result == -1) {
        parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink),
                      "athenaTransportLink_AddLink failed: %s", strerror(errno));
        _UDPLinkData_Destroy(&newLinkData);
        athenaTransportLink_Release(&newTransportLink);
    } else {
        parcLog_Info(athenaTransportLink_GetLogger(athenaTransportLink),
                     "new link accepted by %s: %s %s",
                     athenaTransportLink_GetName(athenaTransportLink), derivedLinkName,
                     athenaTransportLink_IsNotLocal(athenaTransportLink) ? "" : "(Local)");
    }

    parcMemory_Deallocate(&derivedLinkName);

    // Could pass a message back here regarding the new link.
    return newTransportLink;
}
Ejemplo n.º 10
0
static bool
_linkIsEOF(AthenaTransportLink *athenaTransportLink)
{
    struct _UDPLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink);

    // If poll indicates there's a read event and a subsequent read returns zero our peer has hungup.
    struct pollfd pollfd = { .fd = linkData->fd, .events = POLLIN };
    int events = poll(&pollfd, 1, 0);
    if (events == -1) {
        parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "poll error (%s)", strerror(errno));
        return true; // poll error, close the link
    } else if (events == 0) {
        // there are no pending events, was truly a zero read
        return false;
    }
    if (pollfd.revents & POLLIN) {
        char peekBuffer;
        ssize_t readCount = recv(linkData->fd, (void *) &peekBuffer, 1, MSG_PEEK);
        if (readCount == -1) {
            if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { // read blocked
                linkData->_stats.receive_ReadWouldBlock++;
                return false;
            }
            return true; // read error
        }
        if (readCount == 0) { // EOF
            return true;
        }
    }
    return false;
}

static void
_UDPClose(AthenaTransportLink *athenaTransportLink)
{
    parcLog_Info(athenaTransportLink_GetLogger(athenaTransportLink),
                 "link %s closed", athenaTransportLink_GetName(athenaTransportLink));
    _UDPLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink);
    close(linkData->fd);
    _UDPLinkData_Destroy(&linkData);
}
Ejemplo n.º 11
0
static CCNxMetaMessage *
_create_linkList_response(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, CCNxName *ccnxName)
{
    PARCJSONArray *jsonLinkList = parcJSONArray_Create();

    for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->listenerList); index++) {
        AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->listenerList, index);
        const char *linkName = athenaTransportLink_GetName(athenaTransportLink);
        bool notLocal = athenaTransportLink_IsNotLocal(athenaTransportLink);
        bool localForced = athenaTransportLink_IsForceLocal(athenaTransportLink);
        PARCJSON *jsonItem = parcJSON_Create();
        parcJSON_AddString(jsonItem, "linkName", linkName);
        parcJSON_AddInteger(jsonItem, "index", -1);
        parcJSON_AddBoolean(jsonItem, "notLocal", notLocal);
        parcJSON_AddBoolean(jsonItem, "localForced", localForced);

        PARCJSONValue *jsonItemValue = parcJSONValue_CreateFromJSON(jsonItem);
        parcJSON_Release(&jsonItem);

        parcJSONArray_AddValue(jsonLinkList, jsonItemValue);
        parcJSONValue_Release(&jsonItemValue);

        if (notLocal) {
            parcLog_Debug(athenaTransportLinkAdapter->log, "\n    Link listener%s: %s", localForced ? " (forced remote)" : "", linkName);
        } else {
            parcLog_Debug(athenaTransportLinkAdapter->log, "\n    Link listener%s: %s", localForced ? " (forced local)" : "", linkName);
        }
    }
    for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->instanceList); index++) {
        AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, index);
        if (athenaTransportLink) {
            const char *linkName = athenaTransportLink_GetName(athenaTransportLink);
            bool notLocal = athenaTransportLink_IsNotLocal(athenaTransportLink);
            bool localForced = athenaTransportLink_IsForceLocal(athenaTransportLink);
            PARCJSON *jsonItem = parcJSON_Create();
            parcJSON_AddString(jsonItem, "linkName", linkName);
            parcJSON_AddInteger(jsonItem, "index", index);
            parcJSON_AddBoolean(jsonItem, "notLocal", notLocal);
            parcJSON_AddBoolean(jsonItem, "localForced", localForced);

            PARCJSONValue *jsonItemValue = parcJSONValue_CreateFromJSON(jsonItem);
            parcJSON_Release(&jsonItem);

            parcJSONArray_AddValue(jsonLinkList, jsonItemValue);
            parcJSONValue_Release(&jsonItemValue);

            if (notLocal) {
                parcLog_Debug(athenaTransportLinkAdapter->log, "\n    Link instance [%d] %s: %s", index, localForced ? "(forced remote)" : "(remote)", linkName);
            } else {
                parcLog_Debug(athenaTransportLinkAdapter->log, "\n    Link instance [%d] %s: %s", index, localForced ? "(forced local)" : "(local)", linkName);
            }
        }
    }

    char *jsonString = parcJSONArray_ToString(jsonLinkList);

    parcJSONArray_Release(&jsonLinkList);

    PARCBuffer *payload = parcBuffer_CreateFromArray(jsonString, strlen(jsonString));

    CCNxContentObject *contentObject =
        ccnxContentObject_CreateWithDataPayload(ccnxName, parcBuffer_Flip(payload));

    struct timeval tv;
    gettimeofday(&tv, NULL);
    uint64_t nowInMillis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
    ccnxContentObject_SetExpiryTime(contentObject, nowInMillis + 100); // this response is good for 100 millis

    CCNxMetaMessage *result = ccnxMetaMessage_CreateFromContentObject(contentObject);

    ccnxContentObject_Release(&contentObject);
    parcBuffer_Release(&payload);
    parcMemory_Deallocate(&jsonString);

    athena_EncodeMessage(result);
    return result;
}