コード例 #1
0
ファイル: ajs_io.c プロジェクト: avernon/asl_distribution
AJ_Status AJS_ServiceIO(duk_context* ctx)
{
    AJS_IO_PinTriggerCondition condition;
    int32_t trigId;

    trigId = AJS_TargetIO_PinTrigId(&condition);
    if (trigId != AJS_IO_PIN_NO_TRIGGER) {
        AJ_InfoPrintf(("triggered on id %d\n", trigId));
        /*
         * Lookup the pin object in the triggers array
         */
        duk_get_global_string(ctx, AJS_IOObjectName);
        duk_get_prop_string(ctx, -1, AJS_HIDDEN_PROP("trigs"));
        do {
            duk_get_prop_index(ctx, -1, trigId);
            if (duk_is_object(ctx, -1)) {
                /*
                 * Call the trigger function passing the pin object and value as the argument
                 */
                duk_get_prop_string(ctx, -1, "trigger");
                if (duk_is_callable(ctx, -1)) {
                    /*
                     * Pin object is the "this" object
                     */
                    duk_dup(ctx, -2);
                    duk_push_int(ctx, condition);
                    if (duk_pcall_method(ctx, 1) != DUK_EXEC_SUCCESS) {
                        AJS_ConsoleSignalError(ctx);
                    }
                }
                /*
                 * Pop pin object
                 */
                duk_pop(ctx);
            } else {
                AJ_ErrPrintf(("Expected a pin object trigId = %d\n", trigId));
            }
            duk_pop(ctx);
            trigId = AJS_TargetIO_PinTrigId(&condition);
        } while (trigId != AJS_IO_PIN_NO_TRIGGER);
        duk_pop_2(ctx);
    }
    return AJ_OK;
}
コード例 #2
0
AJ_Status AJS_HandleAcceptSession(duk_context* ctx, AJ_Message* msg, uint16_t port, uint32_t sessionId, const char* joiner)
{
    uint32_t accept = TRUE;
    SessionInfo* sessionInfo;

    /*
     * Create an entry in the sessions table so we can track this peer
     */
    AJS_GetGlobalStashObject(ctx, "sessions");
    sessionInfo = AllocSessionObject(ctx, joiner);
    /*
     * If there is no handler automatically accept the connection
     */
    AJS_GetAllJoynProperty(ctx, "onPeerConnected");
    if (duk_is_callable(ctx, -1)) {
        /* Empty interface array */
        duk_push_array(ctx);
        AddServiceObject(ctx, sessionInfo, "/", joiner);
        if (AJS_DebuggerIsAttached()) {
            msg = AJS_CloneAndCloseMessage(ctx, msg);
        }
        if (duk_pcall(ctx, 1) != DUK_EXEC_SUCCESS) {
            AJS_ConsoleSignalError(ctx);
            accept = FALSE;
        } else {
            accept = duk_get_boolean(ctx, -1);
        }
    }
    duk_pop_2(ctx);
    /*
     * It is possible that we already have an outbound session to this peer so if we are not
     * accepting the session we can only delete the entry if the refCount is zero.
     */
    if (accept) {
        ++sessionInfo->refCount;
        sessionInfo->port = port;
        sessionInfo->sessionId = sessionId;
    } else if (sessionInfo->refCount == 0) {
        duk_del_prop_string(ctx, -1, joiner);
    }
    /* Pop sessions object */
    duk_pop(ctx);
    return AJ_BusReplyAcceptSession(msg, accept);
}
コード例 #3
0
/*
 * Delete session info object pointed to by sessionId. If sessionId
 * is zero then delete all session info objects.
 */
static AJ_Status RemoveSessions(duk_context* ctx, uint32_t sessionId)
{
    AJ_Status status = AJ_OK;
    AJS_GetGlobalStashObject(ctx, "sessions");
    duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
    while (duk_next(ctx, -1, 1)) {
        SessionInfo* sessionInfo;
        const char* peer = duk_get_string(ctx, -2);
        duk_get_prop_string(ctx, -1, "info");
        sessionInfo = duk_get_buffer(ctx, -1, NULL);
        duk_pop_3(ctx);
        if (sessionId == 0) {
            AJ_InfoPrintf(("RemoveSessions(): Leaving session: %u\n", sessionInfo->sessionId));
            status = AJ_BusLeaveSession(AJS_GetBusAttachment(), sessionInfo->sessionId);
        } else if (sessionInfo->sessionId == sessionId) {
            status = AJ_BusLeaveSession(AJS_GetBusAttachment(), sessionInfo->sessionId);
            duk_del_prop_string(ctx, -2, peer);
            break;
        }
    }
    duk_pop_2(ctx);
    /*
     * TODO - this is not all that useful because it only indicates that a peer has gone away
     * without being able to specify exactly which services are affected. The problem is we cannot
     * hold a reference to the service object because we a relying on the service object finalizer
     * to clean up sessions that are no longer in use. If we hold a reference the finalizer will
     * never get called.
     */
    if (sessionId != 0) {
        AJS_GetAllJoynProperty(ctx, "onPeerDisconnected");
        if (duk_is_callable(ctx, -1)) {
            if (duk_pcall(ctx, 0) != DUK_EXEC_SUCCESS) {
                AJS_ConsoleSignalError(ctx);
            }
        }
        duk_pop(ctx);
    } else {
        AJS_ClearGlobalStashObject(ctx, "sessions");
    }
    return status;
}
コード例 #4
0
/*
 * Called with "sessions" at the top of the stack.
 *
 * Iterate over the accumulated announcents and make callbacks into JavaScript
 */
static void AnnouncementCallbacks(duk_context* ctx, const char* peer, SessionInfo* sessionInfo)
{
    size_t i;
    size_t numSvcs;
    AJ_ASSERT(sessionInfo->sessionId);
    /*
     * Get the session object (indexed by the peer string) and from this get the announcements array
     */
    duk_get_prop_string(ctx, -1, peer);
    duk_get_prop_string(ctx, -1, "anno");
    /*
     * Iterate over the services implemented by this peer
     */
    numSvcs = duk_get_length(ctx, -1);

    for (i = 0; i < numSvcs; ++i) {
        size_t j;
        size_t numIfaces;
        duk_idx_t svcIdx;

        duk_get_prop_index(ctx, -1, i);
        if (duk_is_undefined(ctx, -1)) {
            /*
             * Undefined means the iface has been deleted so pop "interfaces"
             */
            duk_pop(ctx);
            /*
             * Delete the announcement entry and continue
             */
            duk_del_prop_index(ctx, -1, i);
            continue;
        }
        svcIdx = duk_get_top_index(ctx);
        /*
         * Iterate over the interfaces for this service
         */
        duk_get_prop_string(ctx, svcIdx, "interfaces");
        numIfaces = duk_get_length(ctx, -1);
        for (j = 0; j < numIfaces; ++j) {
            const char* iface;
            duk_get_prop_index(ctx, -1, j);
            iface = duk_get_string(ctx, -1);
            duk_pop(ctx);
            /*
             * If there is a callback registered for this interface call it
             *
             * TODO - should we really make a callback for each interface or just call the first one
             * that has an callback referenced. If the same callback function has been registered
             * for multiple interfaces we definitely don't want to call it multiple times.
             */
            if (PushServiceCallback(ctx, iface)) {
                /*
                 * Set the session information on the service
                 */
                duk_push_int(ctx, sessionInfo->sessionId);
                duk_put_prop_string(ctx, svcIdx, "session");
                duk_push_string(ctx, peer);
                duk_put_prop_string(ctx, svcIdx, "dest");
                /*
                 * Call the callback function
                 */
                duk_dup(ctx, svcIdx);
                if (duk_pcall(ctx, 1) != DUK_EXEC_SUCCESS) {
                    AJS_ConsoleSignalError(ctx);
                }
                duk_pop(ctx);
            }
        }
        /*
         * Pop "interfaces" and the service object
         */
        duk_pop_2(ctx);
        /*
         * Delete the announcement entry
         */
        duk_del_prop_index(ctx, -1, i);
    }
    /* Pop "anno" and the session object */
    duk_pop_2(ctx);
}