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; }
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; }
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; }