static uint8_t AJRouter_Connect(AJ_BusAttachment* busAttachment, const char* routerName) { AJ_Status status; const char* busUniqueName; while (TRUE) { AJ_InfoPrintf(("Attempting to connect to bus '%s'\n", routerName)); status = AJ_FindBusAndConnect(busAttachment, routerName, AJAPP_CONNECT_TIMEOUT); if (status != AJ_OK) { AJ_InfoPrintf(("Failed to connect to bus sleeping for %d seconds\n", AJAPP_CONNECT_PAUSE / 1000)); AJ_Sleep(AJAPP_CONNECT_PAUSE); continue; } busUniqueName = AJ_GetUniqueName(busAttachment); if (busUniqueName == NULL) { AJ_ErrPrintf(("Failed to GetUniqueName() from newly connected bus, retrying\n")); continue; } AJ_InfoPrintf(("Connected to router with BusUniqueName=%s\n", busUniqueName)); break; } /* Setup password based authentication listener for secured peer to peer connections */ AJ_BusSetPasswordCallback(busAttachment, PasswordCallback); /* Configure timeout for the link to the Router bus */ AJ_SetBusLinkTimeout(busAttachment, 60); // 60 seconds return TRUE; }
AJ_Status AJServices_ConnectedHandler(AJ_BusAttachment* busAttachment) { AJ_BusSetPasswordCallback(busAttachment, PasswordCallback); /* Configure timeout for the link to the Router bus */ AJ_SetBusLinkTimeout(busAttachment, 60); // 60 seconds AJ_Status status = AJ_OK; status = AJ_About_ConnectedHandler(busAttachment); if (status != AJ_OK) { goto ErrorExit; } #ifdef CONFIG_SERVICE status = AJCFG_ConnectedHandler(busAttachment); if (status != AJ_OK) { goto ErrorExit; } #endif #ifdef ONBOARDING_SERVICE status = AJOBS_ConnectedHandler(busAttachment); if (status != AJ_OK) { goto ErrorExit; } #endif #ifdef NOTIFICATION_SERVICE_PRODUCER status = AJNS_Producer_ConnectedHandler(busAttachment); if (status != AJ_OK) { goto ErrorExit; } #endif #ifdef CONTROLPANEL_SERVICE status = AJCPS_ConnectedHandler(busAttachment); if (status != AJ_OK) { goto ErrorExit; } #endif #ifdef NOTIFICATION_SERVICE_CONSUMER status = AJNS_Consumer_ConnectedHandler(busAttachment); if (status != AJ_OK) { goto ErrorExit; } #endif return status; ErrorExit: AJ_AlwaysPrintf(("Service ConnectedHandler returned an error %s\n", (AJ_StatusText(status)))); return status; }
AJ_Status AJ_RunAllJoynService(AJ_BusAttachment* bus, AllJoynConfiguration* config) { uint8_t connected = FALSE; AJ_Status status = AJ_OK; while (TRUE) { AJ_Time start = { 0, 0 }; AJ_Message msg; uint32_t now; // get the next timeout //Timer* timer = GetNextTimeout(); uint32_t next; // wait forever uint32_t timeout = (uint32_t) -1; if (!connected) { status = AJ_StartService2( bus, config->daemonName, config->connect_timeout, config->connected, config->session_port, config->service_name, config->flags, config->opts); if (status != AJ_OK) { continue; } AJ_InfoPrintf(("StartService returned AJ_OK\n")); AJ_InfoPrintf(("Connected to Daemon:%s\n", AJ_GetUniqueName(bus))); connected = TRUE; /* Register a callback for providing bus authentication password */ AJ_BusSetPasswordCallback(bus, config->password_callback); /* Configure timeout for the link to the daemon bus */ AJ_SetBusLinkTimeout(bus, config->link_timeout); if (config->connection_handler != NULL) { (config->connection_handler)(connected); } } // absolute time in milliseconds now = AJ_GetElapsedTime(&start, FALSE); next = RunExpiredTimers(now); if (next != (uint32_t) -1) { // if no timers running, wait forever timeout = next; } status = AJ_UnmarshalMsg(bus, &msg, min(500, timeout)); if (AJ_ERR_TIMEOUT == status && AJ_ERR_LINK_TIMEOUT == AJ_BusLinkStateProc(bus)) { status = AJ_ERR_READ; } if (status == AJ_ERR_TIMEOUT) { // go back around and handle the expired timers continue; } if (status == AJ_OK) { uint8_t handled = FALSE; const MessageHandlerEntry* message_entry = config->message_handlers; const PropHandlerEntry* prop_entry = config->prop_handlers; // check the user's handlers first. ANY message that AllJoyn can handle is override-able. while (handled != TRUE && message_entry->msgid != 0) { if (message_entry->msgid == msg.msgId) { if (msg.hdr->msgType == AJ_MSG_METHOD_CALL) { // build a method reply AJ_Message reply; status = AJ_MarshalReplyMsg(&msg, &reply); if (status == AJ_OK) { status = (message_entry->handler)(&msg, &reply); } if (status == AJ_OK) { status = AJ_DeliverMsg(&reply); } } else { // call the handler! status = (message_entry->handler)(&msg, NULL); } handled = TRUE; } ++message_entry; } // we need to check whether this is a property getter or setter. // these are stored in an array because multiple getters and setters can exist if running more than one bus object while (handled != TRUE && prop_entry->msgid != 0) { if (prop_entry->msgid == msg.msgId) { // extract the method from the ID; GetProperty or SetProperty uint32_t method = prop_entry->msgid & 0x000000FF; if (method == AJ_PROP_GET) { status = AJ_BusPropGet(&msg, prop_entry->callback, prop_entry->context); } else if (method == AJ_PROP_SET) { status = AJ_BusPropSet(&msg, prop_entry->callback, prop_entry->context); } else { // this should never happen!!! AJ_ASSERT(!"Invalid property method"); } handled = TRUE; } ++prop_entry; } // handler not found! if (handled == FALSE) { if (msg.msgId == AJ_METHOD_ACCEPT_SESSION) { uint8_t accepted = (config->acceptor)(&msg); status = AJ_BusReplyAcceptSession(&msg, accepted); } else { status = AJ_BusHandleBusMessage(&msg); } } // Any received packets indicates the link is active, so call to reinforce the bus link state AJ_NotifyLinkActive(); } /* * Unarshaled messages must be closed to free resources */ AJ_CloseMsg(&msg); if (status == AJ_ERR_READ) { AJ_InfoPrintf(("AllJoyn disconnect\n")); AJ_InfoPrintf(("Disconnected from Daemon:%s\n", AJ_GetUniqueName(bus))); AJ_Disconnect(bus); connected = FALSE; if (config->connection_handler != NULL) { (config->connection_handler)(connected); } /* * Sleep a little while before trying to reconnect */ AJ_Sleep(10 * 1000); } } // this will never actually return! return AJ_OK; }
int AJ_Main() { AJ_Status status = AJ_OK; AJ_BusAttachment bus; uint8_t connected = FALSE; uint32_t sessionId = 0; /* * One time initialization before calling any other AllJoyn APIs */ AJ_Initialize(); AJ_PrintXML(AppObjects); AJ_RegisterObjects(AppObjects, NULL); SetBusAuthPwdCallback(MyBusAuthPwdCB); while (TRUE) { AJ_Message msg; if (!connected) { status = AJ_StartService(&bus, NULL, CONNECT_TIMEOUT, FALSE, ServicePort, ServiceName, AJ_NAME_REQ_DO_NOT_QUEUE, NULL); if (status != AJ_OK) { continue; } AJ_InfoPrintf(("StartService returned AJ_OK\n")); AJ_InfoPrintf(("Connected to Daemon:%s\n", AJ_GetUniqueName(&bus))); connected = TRUE; #ifdef SECURE_OBJECT status = AJ_SetObjectFlags("/org/alljoyn/alljoyn_test", AJ_OBJ_FLAG_SECURE, 0); if (status != AJ_OK) { AJ_ErrPrintf(("Error calling AJ_SetObjectFlags.. [%s] \n", AJ_StatusText(status))); return -1; } #endif #if defined(SECURE_INTERFACE) || defined(SECURE_OBJECT) /* Register a callback for providing bus authentication password */ AJ_BusSetPasswordCallback(&bus, PasswordCallback); AJ_BusEnableSecurity(&bus, suites, numsuites); AJ_BusSetAuthListenerCallback(&bus, AuthListenerCallback); #endif /* Configure timeout for the link to the daemon bus */ AJ_SetBusLinkTimeout(&bus, 60); // 60 seconds } status = AJ_UnmarshalMsg(&bus, &msg, UNMARSHAL_TIMEOUT); if (AJ_ERR_TIMEOUT == status && AJ_ERR_LINK_TIMEOUT == AJ_BusLinkStateProc(&bus)) { status = AJ_ERR_READ; } if (status != AJ_OK) { if (status == AJ_ERR_TIMEOUT) { AppDoWork(); continue; } } if (status == AJ_OK) { switch (msg.msgId) { case AJ_REPLY_ID(AJ_METHOD_ADD_MATCH): if (msg.hdr->msgType == AJ_MSG_ERROR) { AJ_InfoPrintf(("Failed to add match\n")); status = AJ_ERR_FAILURE; } else { status = AJ_OK; } break; case AJ_METHOD_ACCEPT_SESSION: { uint16_t port; char* joiner; AJ_UnmarshalArgs(&msg, "qus", &port, &sessionId, &joiner); if (port == ServicePort) { status = AJ_BusReplyAcceptSession(&msg, TRUE); AJ_InfoPrintf(("Accepted session session_id=%u joiner=%s\n", sessionId, joiner)); } else { status = AJ_BusReplyAcceptSession(&msg, FALSE); AJ_InfoPrintf(("Accepted rejected session_id=%u joiner=%s\n", sessionId, joiner)); } } break; case APP_MY_PING: status = AppHandlePing(&msg); break; case APP_GET_PROP: status = AJ_BusPropGet(&msg, PropGetHandler, NULL); break; case APP_SET_PROP: status = AJ_BusPropSet(&msg, PropSetHandler, NULL); if (status == AJ_OK) { AJ_InfoPrintf(("Property successfully set to %d.\n", propVal)); } else { AJ_InfoPrintf(("Property set attempt unsuccessful. Status = 0x%04x.\n", status)); } break; case AJ_SIGNAL_SESSION_LOST_WITH_REASON: { uint32_t id, reason; AJ_UnmarshalArgs(&msg, "uu", &id, &reason); AJ_InfoPrintf(("Session lost. ID = %u, reason = %u", id, reason)); if (CancelAdvertiseName) { status = AJ_BusAdvertiseName(&bus, ServiceName, AJ_TRANSPORT_ANY, AJ_BUS_START_ADVERTISING, 0); } status = AJ_ERR_SESSION_LOST; } break; case AJ_SIGNAL_SESSION_JOINED: if (CancelAdvertiseName) { status = AJ_BusAdvertiseName(&bus, ServiceName, AJ_TRANSPORT_ANY, AJ_BUS_STOP_ADVERTISING, 0); } break; case AJ_REPLY_ID(AJ_METHOD_CANCEL_ADVERTISE): case AJ_REPLY_ID(AJ_METHOD_ADVERTISE_NAME): if (msg.hdr->msgType == AJ_MSG_ERROR) { status = AJ_ERR_FAILURE; } break; case APP_MY_SIGNAL: AJ_InfoPrintf(("Received my_signal\n")); status = AJ_OK; if (ReflectSignal) { AJ_Message out; AJ_MarshalSignal(&bus, &out, APP_MY_SIGNAL, msg.destination, msg.sessionId, 0, 0); AJ_MarshalArgs(&out, "a{ys}", 0, NULL); AJ_DeliverMsg(&out); AJ_CloseMsg(&out); } break; default: /* * Pass to the built-in bus message handlers */ status = AJ_BusHandleBusMessage(&msg); break; } // Any received packets indicates the link is active, so call to reinforce the bus link state AJ_NotifyLinkActive(); } /* * Unarshaled messages must be closed to free resources */ AJ_CloseMsg(&msg); if ((status == AJ_ERR_READ) || (status == AJ_ERR_LINK_DEAD)) { AJ_InfoPrintf(("AllJoyn disconnect\n")); AJ_InfoPrintf(("Disconnected from Daemon:%s\n", AJ_GetUniqueName(&bus))); AJ_Disconnect(&bus); connected = FALSE; /* * Sleep a little while before trying to reconnect */ AJ_Sleep(10 * 1000); } } AJ_WarnPrintf(("svclite EXIT %d\n", status)); 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; }