static AJ_Status AJApp_ConnectedHandler(AJ_BusAttachment* busAttachment)
{
    AJ_Status status = AJ_OK;

    if (AJ_GetUniqueName(busAttachment)) {
        if (currentServicesInitializationState == nextServicesInitializationState) {
            switch (currentServicesInitializationState) {
            case INIT_SERVICES:
                status = AJSVC_ConnectedHandler(busAttachment);
                if (status != AJ_OK) {
                    goto ErrorExit;
                }
                currentServicesInitializationState = nextServicesInitializationState = INIT_SERVICES_PORT;
                break;

            case INIT_SERVICES_PORT:
                status = AJ_BusBindSessionPort(busAttachment, AJ_ABOUT_SERVICE_PORT, NULL, 0);
                if (status != AJ_OK) {
                    goto ErrorExit;
                }
                nextServicesInitializationState = INIT_ADVERTISE_NAME;
                break;

            case INIT_ADVERTISE_NAME:
                status = AJ_BusAdvertiseName(busAttachment, AJ_GetUniqueName(busAttachment), AJ_TRANSPORT_ANY, AJ_BUS_START_ADVERTISING, 0);
                if (status != AJ_OK) {
                    goto ErrorExit;
                }
                currentServicesInitializationState = nextServicesInitializationState = INIT_ABOUT;
                break;

            case INIT_ABOUT:
                status = AJ_AboutInit(busAttachment, AJ_ABOUT_SERVICE_PORT);
                if (status != AJ_OK) {
                    goto ErrorExit;
                }
                currentServicesInitializationState = nextServicesInitializationState = INIT_CHECK_ANNOUNCE;
                break;

            case INIT_CHECK_ANNOUNCE:
                status = AJ_AboutAnnounce(busAttachment);
                if (status != AJ_OK) {
                    goto ErrorExit;
                }
                break;

            default:
                break;
            }
        }
    }
    return status;

ErrorExit:

    AJ_ErrPrintf(("Application ConnectedHandler returned an error %s\n", (AJ_StatusText(status))));
    return status;
}
Exemple #2
0
AJ_Status AJ_StartService(AJ_BusAttachment* bus,
                          const char* daemonName,
                          uint32_t timeout,
                          uint8_t connected,
                          uint16_t port,
                          const char* name,
                          uint32_t flags,
                          const AJ_SessionOpts* opts
                          )
{
    AJ_Status status;
    AJ_Time timer;
    uint8_t serviceStarted = FALSE;

    AJ_InfoPrintf(("AJ_StartService(bus=0x%p, daemonName=\"%s\", timeout=%d., connected=%d., port=%d., name=\"%s\", flags=0x%x, opts=0x%p)\n",
                   bus, daemonName, timeout, connected, port, name, flags, opts));

    AJ_InitTimer(&timer);

    while (TRUE) {
        if (AJ_GetElapsedTime(&timer, TRUE) > timeout) {
            return AJ_ERR_TIMEOUT;
        }
        if (!connected) {
            AJ_InfoPrintf(("AJ_StartService(): AJ_FindBusAndConnect()\n"));
            status = AJ_FindBusAndConnect(bus, daemonName, AJ_CONNECT_TIMEOUT);
            if (status != AJ_OK) {
                AJ_WarnPrintf(("AJ_StartService(): connect failed: sleeping for %d seconds\n", AJ_CONNECT_PAUSE / 1000));
                AJ_Sleep(AJ_CONNECT_PAUSE);
                continue;
            }
            AJ_InfoPrintf(("AJ_StartService(): connected to bus\n"));
        }
        /*
         * Kick things off by binding a session port
         */
        AJ_InfoPrintf(("AJ_StartService(): AJ_BindSessionPort()\n"));
        status = AJ_BusBindSessionPort(bus, port, opts, 0);
        if (status == AJ_OK) {
            break;
        }
        AJ_ErrPrintf(("AJ_StartService(): AJ_Disconnect(): status=%s.\n", AJ_StatusText(status)));
        AJ_Disconnect(bus);
    }

    while (!serviceStarted && (status == AJ_OK)) {
        AJ_Message msg;

        status = AJ_UnmarshalMsg(bus, &msg, AJ_UNMARSHAL_TIMEOUT);
        if (status == AJ_ERR_NO_MATCH) {
            // Ignore unknown messages
            status = AJ_OK;
            continue;
        }
        if (status != AJ_OK) {
            AJ_ErrPrintf(("AJ_StartService(): status=%s.\n", AJ_StatusText(status)));
            break;
        }

        switch (msg.msgId) {
        case AJ_REPLY_ID(AJ_METHOD_BIND_SESSION_PORT):
            if (msg.hdr->msgType == AJ_MSG_ERROR) {
                AJ_ErrPrintf(("AJ_StartService(): AJ_METHOD_BIND_SESSION_PORT: %s\n", msg.error));
                status = AJ_ERR_FAILURE;
            } else {
                AJ_InfoPrintf(("AJ_StartService(): AJ_BusRequestName()\n"));
                status = AJ_BusRequestName(bus, name, flags);
            }
            break;

        case AJ_REPLY_ID(AJ_METHOD_REQUEST_NAME):
            if (msg.hdr->msgType == AJ_MSG_ERROR) {
                AJ_ErrPrintf(("AJ_StartService(): AJ_METHOD_REQUEST_NAME: %s\n", msg.error));
                status = AJ_ERR_FAILURE;
            } else {
                AJ_InfoPrintf(("AJ_StartService(): AJ_BusAdvertiseName()\n"));
                status = AJ_BusAdvertiseName(bus, name, AJ_TRANSPORT_ANY, AJ_BUS_START_ADVERTISING, 0);
            }
            break;

        case AJ_REPLY_ID(AJ_METHOD_ADVERTISE_NAME):
            if (msg.hdr->msgType == AJ_MSG_ERROR) {
                AJ_ErrPrintf(("AJ_StartService(): AJ_METHOD_ADVERTISE_NAME: %s\n", msg.error));
                status = AJ_ERR_FAILURE;
            } else {
                serviceStarted = TRUE;
            }
            break;

        default:
            /*
             * Pass to the built-in bus message handlers
             */
            AJ_InfoPrintf(("AJ_StartService(): AJ_BusHandleBusMessage()\n"));
            status = AJ_BusHandleBusMessage(&msg);
            break;
        }
        AJ_CloseMsg(&msg);
    }

    if (status == AJ_OK) {
        status = AJ_AboutInit(bus, port);
    } else {
        AJ_WarnPrintf(("AJ_StartService(): AJ_Disconnect(): status=%s\n", AJ_StatusText(status)));
        AJ_Disconnect(bus);
    }
    return status;
}
Exemple #3
0
AJ_Status AJS_AttachAllJoyn(AJ_BusAttachment* aj)
{
    AJ_Status status;
    uint8_t isConnected = FALSE;
    uint32_t linkTO = LINK_TO;
    size_t sapSz;

    /*
     * Initialize the onboarding service
     */
    sapSz = min(sizeof(obSettings.AJOBS_SoftAPSSID), sizeof(softAPSSID));
    memcpy((char*)obSettings.AJOBS_SoftAPSSID, softAPSSID, sapSz);
    status = AJOBS_Start(&obSettings);
    if (status != AJ_OK) {
        goto Exit;
    }
    AJ_InfoPrintf(("Attempting to attach to AllJoyn\n"));
    while (!isConnected) {
        status = AJSVC_RoutingNodeConnect(aj, busNode, CONNECT_TO, CONNECT_PAUSE, linkTO, &isConnected);
        if (status != AJ_ERR_TIMEOUT) {
            break;
        }
    }
    if (isConnected) {
        status = AJS_ServicesInit(aj);
        if (status != AJ_OK) {
            AJ_ErrPrintf(("Failed to initialize services"));
        }
    }
    if (isConnected && (AJOBS_GetState() != AJOBS_STATE_CONFIGURED_VALIDATED)) {
        /*
         * Kick of onboarding
         */
        status = AJ_BusBindSessionPort(aj, ONBOARDING_PORT, NULL, 0);
        /*
         * Allow onboarding service to run its course
         */
        while (status == AJ_OK) {
            AJ_Message msg;
            status = AJ_UnmarshalMsg(aj, &msg, MSG_TO);
            if (status == AJ_ERR_NO_MATCH) {
                /*
                 * Discard unknown messages
                 */
                status = AJ_CloseMsg(&msg);
                continue;
            }
            if (status == AJ_ERR_TIMEOUT) {
                /*
                 * Check the link is still up
                 */
                status = AJ_BusLinkStateProc(aj);
                if (status == AJ_OK) {
                    continue;
                }
            }
            if (status != AJ_OK) {
                break;
            }
            switch (msg.msgId) {
            case AJ_REPLY_ID(AJ_METHOD_BIND_SESSION_PORT):
                AJ_AboutInit(aj, ONBOARDING_PORT);
                break;

            case AJ_METHOD_ACCEPT_SESSION:
                /*
                 * TODO - check that the port number is correct
                 */
                status = AJ_BusReplyAcceptSession(&msg, TRUE);
                if (status == AJ_OK) {
                    status = AJOBS_ConnectedHandler(aj);
                }
                break;

            default:
                /*
                 * Let the service message handlers have first dibs on the message
                 */
                status = AJS_ServicesMsgHandler(&msg);
                if (status == AJ_ERR_NO_MATCH) {
                    /*
                     * Pass the unhandled message to the standard bus handler
                     */
                    status = AJ_BusHandleBusMessage(&msg);
                    if (status == AJ_ERR_NO_MATCH) {
                        AJ_ErrPrintf(("Discarding unhandled message\n"));
                        status = AJ_OK;
                    }
                }
                break;
            }
            /*
             * Let the link monitor know we are receiving messages
             */
            AJ_NotifyLinkActive();
            /*
             * Free resources used by the message
             */
            AJ_CloseMsg(&msg);
            if (AJOBS_GetState() == AJOBS_STATE_CONFIGURED_VALIDATED) {
                AJ_InfoPrintf(("Onboarding completed\n"));
                break;
            }
            AJ_InfoPrintf(("Onboarding continuing\n"));
        }
        /*
         * If we got an error during onboarding we should restart
         */
        if (status != AJ_OK) {
            status = AJ_ERR_RESTART;
        }
    }
    /*
     * If all went well let the services know we are connected
     */
    if (isConnected && (status == AJ_OK)) {
        /*
         * Add match rules to subscribe to session related signals
         */
        status = AJ_BusSetSignalRuleFlags(aj, sessionLostMatchRule, AJ_BUS_SIGNAL_ALLOW, AJ_FLAG_NO_REPLY_EXPECTED);
        if (status == AJ_OK) {
            status = AJSVC_ConnectedHandler(aj);
        }
    }

Exit:
    return status;
}
AJ_Status AJS_MessageLoop(duk_context* ctx, AJ_BusAttachment* aj, duk_idx_t ajIdx)
{
    AJ_Status status = AJ_OK;
    AJ_Message msg;
    AJ_Time timerClock;
    uint32_t linkTO;
    uint32_t msgTO = 0x7FFFFFFF;
    duk_idx_t top = duk_get_top_index(ctx);
    uint8_t ldstate;

    AJ_InfoPrintf(("AJS_MessageLoop top=%d\n", (int)top));

    deferredOp = AJS_OP_NONE;

    if (ajIdx >= 0) {
        /*
         * Read the link timeout property from the config set
         */
        duk_get_prop_string(ctx, -1, "config");
        duk_get_prop_string(ctx, -1, "linkTimeout");
        linkTO = duk_get_int(ctx, -1);
        duk_pop_2(ctx);
        AJ_SetBusLinkTimeout(aj, linkTO);
    }
    /*
     * timer clock must be initialized
     */
    AJ_InitTimer(&timerClock);

    AJ_ASSERT(duk_get_top_index(ctx) == top);

    /*
     * Initialize About we can start sending announcements
     */
    AJ_AboutInit(aj, AJS_APP_PORT);

    while (status == AJ_OK) {
        /*
         * Check we are cleaning up the duktape stack correctly.
         */
        if (duk_get_top_index(ctx) != top) {
            AJ_ErrPrintf(("!!!AJS_MessageLoop top=%d expected %d\n", (int)duk_get_top_index(ctx), (int)top));
            AJS_DumpStack(ctx);
            AJ_ASSERT(duk_get_top_index(ctx) == top);
        }
        AJS_SetWatchdogTimer(AJS_DEFAULT_WATCHDOG_TIMEOUT);
        /*
         * Pinned items (strings/buffers) are only valid while running script
         */
        AJS_ClearPins(ctx);
        /*
         * Check if there are any pending I/O operations to perform.
         */
        status = AJS_ServiceIO(ctx);
        if (status != AJ_OK) {
            AJ_ErrPrintf(("Error servicing I/O functions\n"));
            break;
        }
        /*
         * Services the internal and timeout timers and updates the timeout value for any new
         * timers that have been registered since this function was last called.
         */
        status = AJS_RunTimers(ctx, &timerClock, &msgTO);
        if (status != AJ_OK) {
            AJ_ErrPrintf(("Error servicing timer functions\n"));
            break;
        }
        /*
         * Do any announcing required
         */
        status = AJS_GetLockdownState(&ldstate);
        if (status == AJ_OK && ldstate == AJS_CONSOLE_UNLOCKED) {
            status = AJ_AboutAnnounce(aj);
        }
        if (status != AJ_OK) {
            break;
        }
        /*
         * This special wildcard allows us to unmarshal signals with any source path
         */
        AJS_SetObjectPath("!");
        /*
         * Block until a message is received, the timeout expires, or the operation is interrupted.
         */
        status = AJ_UnmarshalMsg(aj, &msg, msgTO);
        if (status != AJ_OK) {
            if ((status == AJ_ERR_INTERRUPTED) || (status == AJ_ERR_TIMEOUT)) {
                status = AJ_OK;
                continue;
            }
            if (status == AJ_ERR_NO_MATCH) {
                status = AJ_OK;
            }
            AJ_CloseMsg(&msg);
            continue;
        }

        switch (msg.msgId) {
        case 0:
            /* If a message was parsed but is unrecognized and should be ignored */
            break;

        /* Introspection messages */
        case AJ_METHOD_PING:
        case AJ_METHOD_BUS_PING:
        case AJ_METHOD_GET_MACHINE_ID:
        case AJ_METHOD_INTROSPECT:
        case AJ_METHOD_GET_DESCRIPTION_LANG:
        case AJ_METHOD_INTROSPECT_WITH_DESC:
        /* About messages */
        case AJ_METHOD_ABOUT_GET_PROP:
        case AJ_METHOD_ABOUT_SET_PROP:
        case AJ_METHOD_ABOUT_GET_ABOUT_DATA:
        case AJ_METHOD_ABOUT_GET_OBJECT_DESCRIPTION:
        case AJ_METHOD_ABOUT_ICON_GET_PROP:
        case AJ_METHOD_ABOUT_ICON_SET_PROP:
        case AJ_METHOD_ABOUT_ICON_GET_URL:
        case AJ_METHOD_ABOUT_ICON_GET_CONTENT:
        /* Authentication messages and replies */
        case AJ_METHOD_EXCHANGE_GUIDS:
        case AJ_REPLY_ID(AJ_METHOD_EXCHANGE_GUIDS):
        case AJ_METHOD_EXCHANGE_SUITES:
        case AJ_REPLY_ID(AJ_METHOD_EXCHANGE_SUITES):
        case AJ_METHOD_AUTH_CHALLENGE:
        case AJ_REPLY_ID(AJ_METHOD_AUTH_CHALLENGE):
        case AJ_METHOD_GEN_SESSION_KEY:
        case AJ_REPLY_ID(AJ_METHOD_GEN_SESSION_KEY):
        case AJ_METHOD_EXCHANGE_GROUP_KEYS:
        case AJ_REPLY_ID(AJ_METHOD_EXCHANGE_GROUP_KEYS):
        case AJ_METHOD_KEY_EXCHANGE:
        case AJ_REPLY_ID(AJ_METHOD_KEY_EXCHANGE):
        case AJ_METHOD_KEY_AUTHENTICATION:
        case AJ_REPLY_ID(AJ_METHOD_KEY_AUTHENTICATION):
        /* Replies the app ignores */
        case AJ_REPLY_ID(AJ_METHOD_ADD_MATCH):
        case AJ_REPLY_ID(AJ_METHOD_REMOVE_MATCH):
        case AJ_REPLY_ID(AJ_METHOD_PING):
        case AJ_REPLY_ID(AJ_METHOD_BUS_PING):
        /* Signals the app ignores */
        case AJ_SIGNAL_PROBE_ACK:
        case AJ_SIGNAL_PROBE_REQ:
        case AJ_SIGNAL_NAME_OWNER_CHANGED:
            status = AJ_BusHandleBusMessage(&msg);
            break;

        case AJ_METHOD_ACCEPT_SESSION:
            status = SessionDispatcher(ctx, &msg);
            break;

        case AJ_REPLY_ID(AJ_METHOD_BIND_SESSION_PORT):
            status = SessionBindReply(ctx, &msg);
            break;

        default:
            status = HandleMessage(ctx, ajIdx, &msg);
            break;
        }
        /*
         * Free message resources
         */
        AJ_CloseMsg(&msg);
        /*
         * Decide which messages should cause us to exit
         */
        switch (status) {
        case AJ_OK:
            break;

        case AJ_ERR_READ:
        case AJ_ERR_WRITE:
        case AJ_ERR_RESTART:
        case AJ_ERR_RESTART_APP:
            break;

        default:
            AJ_ErrPrintf(("Got error %s - continuing anyway\n", AJ_StatusText(status)));
            status = AJ_OK;
        }
        /*
         * Let link monitor know we are getting messages
         */
        AJ_NotifyLinkActive();
        /*
         * Perform any deferred operations. These are operations such as factory reset that cannot
         * be cleanly performed from inside duktape.
         */
        if (status == AJ_OK) {
            status = DoDeferredOperation(ctx);
        }
    }
    AJS_ClearPins(ctx);
    AJS_ClearWatchdogTimer();
    return status;
}