AJ_Status AJ_BusLinkStateProc(AJ_BusAttachment* bus) { AJ_Status status = AJ_OK; if (bus->isProbeRequired && busLinkTimeout) { if (!busLinkWatcher.linkTimerInited) { busLinkWatcher.linkTimerInited = TRUE; AJ_InitTimer(&(busLinkWatcher.linkTimer)); } else { uint32_t eclipse = AJ_GetElapsedTime(&(busLinkWatcher.linkTimer), TRUE); if (eclipse >= busLinkTimeout) { if (!busLinkWatcher.pingTimerInited) { busLinkWatcher.pingTimerInited = TRUE; AJ_InitTimer(&(busLinkWatcher.pingTimer)); if (AJ_OK != AJ_SendLinkProbeReq(bus)) { AJ_ErrPrintf(("AJ_BusLinkStateProc(): AJ_SendLinkProbeReq() failure")); } } else { eclipse = AJ_GetElapsedTime(&(busLinkWatcher.pingTimer), TRUE); if (eclipse >= AJ_BUS_LINK_PING_TIMEOUT) { if (++busLinkWatcher.numOfPingTimedOut < AJ_MAX_LINK_PING_PACKETS) { AJ_InitTimer(&(busLinkWatcher.pingTimer)); if (AJ_OK != AJ_SendLinkProbeReq(bus)) { AJ_ErrPrintf(("AJ_BusLinkStateProc(): AJ_SendLinkProbeReq() failure")); } } else { AJ_ErrPrintf(("AJ_BusLinkStateProc(): AJ_ERR_LINK_TIMEOUT")); status = AJ_ERR_LINK_TIMEOUT; // stop sending probe messages until next link timeout event memset(&busLinkWatcher, 0, sizeof(AJ_BusLinkWatcher)); } } } } } } return status; }
AJ_Status AJ_PeerAuthenticate(AJ_BusAttachment* bus, const char* peerName, AJ_PeerAuthenticateCallback callback, void* cbContext) { AJ_Message msg; char guidStr[33]; AJ_GUID localGuid; uint32_t version = REQUIRED_AUTH_VERSION; /* * Check there isn't an authentication in progress */ if (authContext.callback || authContext.peerGuid) { /* * The existing authentication may have timed-out */ if (AJ_GetElapsedTime(&authContext.timer, TRUE) < MAX_AUTH_TIME) { return AJ_ERR_RESOURCES; } /* * Report the failed authentication */ PeerAuthComplete(AJ_ERR_TIMEOUT); } authContext.callback = callback; authContext.cbContext = cbContext; authContext.peerName = peerName; AJ_InitTimer(&authContext.timer); /* * Kick off autnetication with an ExchangeGUIDS method call */ AJ_MarshalMethodCall(bus, &msg, AJ_METHOD_EXCHANGE_GUIDS, peerName, 0, AJ_NO_FLAGS, CALL_TIMEOUT); AJ_GetLocalGUID(&localGuid); AJ_GUID_ToString(&localGuid, guidStr, sizeof(guidStr)); AJ_MarshalArgs(&msg, "su", guidStr, version); return AJ_DeliverMsg(&msg); }
/* * This function just returns the work item. If there is data inside that you want * you have to unmarshal it after you receive the work item. */ AJ_Status AJ_WSL_WMI_WaitForWorkItem(uint32_t socket, uint8_t command, wsl_work_item** item, uint32_t timeout) { AJ_Status status; AJ_Time timer; AJ_InitTimer(&timer); // AJ_AlwaysPrintf(("WaitForWorkItem: %x\n", command)); //wsl_work_item* item; status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[socket].workRxQueue, item, timeout); timeout -= AJ_GetElapsedTime(&timer, TRUE); if ((status == AJ_OK) && item && *item) { if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_INTERUPT)) { // We don't care about the interrupted signal for any calls using this function AJ_WSL_WMI_FreeWorkItem((*item)); status = AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[socket].workRxQueue, item, timeout); } if ((status == AJ_OK) && ((*item)->itemType == command)) { AJ_InfoPrintf(("AJ_WSL_WMI_WaitForWorkItem(): Received work item %s\n", WSL_WorkItemText(command))); return AJ_OK; } else if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_DISCONNECT)) { AJ_InfoPrintf(("Got disconnect while waiting for %s\n", WSL_WorkItemText(command))); // Clean up the network queues int i; for (i = 0; i < AJ_WSL_SOCKET_MAX; i++) { wsl_work_item* clear; AJ_WSL_SOCKET_CONTEXT[i].valid = FALSE; // Removed any stashed data AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[i].stashedRxList, 1); // Reallocate a new stash AJ_WSL_SOCKET_CONTEXT[i].stashedRxList = AJ_BufListCreate(); // Reset the queue, any work items are now invalid since the socket was closed while (AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue, &clear, 0) == AJ_OK) { AJ_WSL_WMI_FreeWorkItem(clear); } while (AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue, &clear, 0) == AJ_OK) { AJ_WSL_WMI_FreeWorkItem(clear); } AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue); AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue); } AJ_WSL_WMI_FreeWorkItem((*item)); return AJ_ERR_LINK_DEAD; } else if ((status == AJ_OK) && ((*item)->itemType == WSL_NET_DATA_RX)) { // If we got data we want to save it and not throw it away, its still not what we // wanted so we can free the work item as it wont be needed at a higher level AJ_InfoPrintf(("Got data while waiting for %s\n", WSL_WorkItemText(command))); if ((*item)->node->length) { AJ_BufNode* new_node = AJ_BufNodeCreateAndTakeOwnership((*item)->node); AJ_BufListPushTail(AJ_WSL_SOCKET_CONTEXT[socket].stashedRxList, new_node); AJ_WSL_WMI_FreeWorkItem((*item)); return AJ_ERR_NULL; } } else { AJ_WarnPrintf(("AJ_WSL_WMI_WaitForWorkItem(): Received incorrect work item %s, wanted %s\n", WSL_WorkItemText((*item)->itemType), WSL_WorkItemText(command))); // Wrong work item, but return NULL because we can free the item internally AJ_WSL_WMI_FreeWorkItem((*item)); return AJ_ERR_NULL; } } return AJ_ERR_NULL; }
AJ_Status AJOBS_GetScanInfoHandler(AJ_Message* msg) { AJ_Status status = AJ_OK; AJ_Message reply; AJ_Arg array; AJ_Arg structure; uint32_t elapsed; AJ_InfoPrintf(("Handling GetScanInfo request\n")); status = AJ_MarshalReplyMsg(msg, &reply); if (status != AJ_OK) { return status; } elapsed = AJ_GetElapsedTime(AJOBS_GetLastScanTime(), TRUE); if (elapsed > 0) { elapsed /= 60000; } status = AJ_MarshalArgs(&reply, "q", (uint16_t) elapsed); if (status != AJ_OK) { return status; } status = AJ_MarshalContainer(&reply, &array, AJ_ARG_ARRAY); if (status != AJ_OK) { return status; } int i = 0; for (; i < AJOBS_GetScanInfoCount(); ++i) { status = AJ_MarshalContainer(&reply, &structure, AJ_ARG_STRUCT); if (status != AJ_OK) { return status; } status = AJ_MarshalArgs(&reply, "s", (AJOBS_GetScanInfos())[i].ssid); if (status != AJ_OK) { return status; } status = AJ_MarshalArgs(&reply, "n", (AJOBS_GetScanInfos())[i].authType); if (status != AJ_OK) { return status; } status = AJ_MarshalCloseContainer(&reply, &structure); if (status != AJ_OK) { return status; } } status = AJ_MarshalCloseContainer(&reply, &array); if (status != AJ_OK) { return status; } status = AJ_DeliverMsg(&reply); if (status != AJ_OK) { return status; } return status; }
void tm_test() { AJ_Time t; AJ_InitTimer(&t); int x = 0; while (x++ < 10) { uint32_t msec = AJ_GetElapsedTime(&t, TRUE); AJ_Printf("%d\n", msec); } }
void NotificationConsumer_DoWork(AJ_BusAttachment* busAttachment) { if (savedNotification.version > 0 && !processingAction) { if (dismissTimer != NULL) { // Dismiss timer is set if (AJ_GetElapsedTime(dismissTimer, TRUE) > DISMISS_DELAY_PERIOD) { // Delay timer expired dismissTimer = NULL; // Disable/delete timer nextAction = CONSUMER_ACTION_DISMISS; // Dismiss last saved notification Consumer_DoAction(busAttachment); } } else { // Saved notidication awaits action Consumer_DoAction(busAttachment); } } return; }
static AJ_Status SetSignalRules(AJ_BusAttachment* bus) { AJ_Status status = AJ_OK; /* * AJ_GUID needs the NameOwnerChanged signal to clear out entries in * its map. Prior to router version 10 this means we must set a * signal rule to receive every NameOwnerChanged signal. With * version 10 the router supports the arg[0,1,...] key in match * rules, allowing us to set a signal rule for just the * NameOwnerChanged signals of entries in the map. See aj_guid.c * for usage of the arg key. */ if (AJ_GetRoutingProtoVersion() < 11) { status = AJ_BusSetSignalRule(bus, "type='signal',member='NameOwnerChanged',interface='org.freedesktop.DBus'", AJ_BUS_SIGNAL_ALLOW); if (status == AJ_OK) { uint8_t found_reply = FALSE; AJ_Message msg; AJ_Time timer; AJ_InitTimer(&timer); while (found_reply == FALSE && AJ_GetElapsedTime(&timer, TRUE) < 3000) { status = AJ_UnmarshalMsg(bus, &msg, 3000); if (status == AJ_OK) { switch (msg.msgId) { case AJ_REPLY_ID(AJ_METHOD_ADD_MATCH): found_reply = TRUE; break; default: // ignore everything else AJ_BusHandleBusMessage(&msg); break; } AJ_CloseMsg(&msg); } } } } return status; }
static void UpdateTime() { uint32_t diff; if (!g_isSet) { return; // time is not set, no need to update yet } diff = AJ_GetElapsedTime(&g_aj_time, 0) / 1000; g_lastSavedTime.milliseconds = 0; g_lastSavedTime.seconds = 0; TSDateTime2AJTime(&g_ts_date, &g_ts_time, &g_lastSavedTime); g_lastSavedTime.seconds += diff; AJTime2TSDateTime(&g_lastSavedTime, &g_ts_date, &g_ts_time); }
void UpdateTimer(AJ_BusAttachment*busAttachment) { if (g_timer_runs) { uint32_t elapsed = AJ_GetElapsedTime(&g_aj_timer_time, 0); uint32_t timerLeftMilliSec = g_ts_timer_timeleft.milliseconds + ((g_ts_timer_timeleft.second + g_ts_timer_timeleft.minute * NUM_OF_SECS_IN_MIN + g_ts_timer_timeleft.hour * 24 * NUM_OF_SECS_IN_HOUR) * 1000); if (elapsed >= timerLeftMilliSec) { // emit timer signal and substarct 1 from repeat count and reset timer if (busAttachment != NULL) { AJTS_Server_TimerEvent(busAttachment, AJTS_TIMER_OBJECT_INDEX); } if ((int16_t)-- g_timer_repeat > 0) { g_ts_timer_timeleft = g_ts_timer_interval; } else { g_timer_runs = FALSE; AJTS_Server_Timer_RunStateChanged(busAttachment, AJTS_TIMER_OBJECT_INDEX, FALSE); g_timer_repeat = 0; } } else { timerLeftMilliSec -= elapsed; g_ts_timer_timeleft.milliseconds = timerLeftMilliSec % 1000; timerLeftMilliSec /= 1000; // reduce to seconds g_ts_timer_timeleft.second = timerLeftMilliSec % 60; timerLeftMilliSec /= 60; // reduce to minutes g_ts_timer_timeleft.minute = timerLeftMilliSec % 60; timerLeftMilliSec /= 60; // reduce to hours g_ts_timer_timeleft.hour = timerLeftMilliSec; } } }
uint32_t AJ_SetTimer(uint32_t relative_time, TimeoutHandler handler, void* context, uint32_t repeat) { uint32_t i; for (i = 0; i < MAX_TIMERS; ++i) { Timer* timer = Timers + i; // need to find an available timer slot if (timer->handler == NULL) { AJ_Time start = { 0, 0 }; uint32_t now = AJ_GetElapsedTime(&start, FALSE); timer->handler = handler; timer->context = context; timer->repeat = repeat; timer->abs_time = now + relative_time; return i + 1; } } // available slot not found! return 0; }
AJ_Status AJ_Authenticate(AJ_BusAttachment* bus) { AJ_Status status = AJ_OK; AJ_SASL_Context sasl; /* * Send initial NUL byte */ bus->sock.tx.writePtr[0] = 0; bus->sock.tx.writePtr += 1; status = bus->sock.tx.send(&bus->sock.tx); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Authenticate(): status=%s\n", AJ_StatusText(status))); goto ExitConnect; } AJ_SASL_InitContext(&sasl, mechList, AJ_AUTH_RESPONDER, busAuthPwdFunc, FALSE); while (TRUE) { status = AuthAdvance(&sasl, &bus->sock.rx, &bus->sock.tx); if ((status != AJ_OK) || (sasl.state == AJ_SASL_FAILED)) { break; } if (sasl.state == AJ_SASL_AUTHENTICATED) { status = SendHello(bus); break; } } if (status == AJ_OK) { AJ_Message helloResponse; status = AJ_UnmarshalMsg(bus, &helloResponse, 5000); if (status == AJ_OK) { /* * The only error we might get is a timeout */ if (helloResponse.hdr->msgType == AJ_MSG_ERROR) { status = AJ_ERR_TIMEOUT; } else { AJ_Arg arg; status = AJ_UnmarshalArg(&helloResponse, &arg); if (status == AJ_OK) { if (arg.len >= (sizeof(bus->uniqueName) - 1)) { AJ_ErrPrintf(("AJ_Authenticate(): AJ_ERR_RESOURCES\n")); status = AJ_ERR_RESOURCES; } else { memcpy(bus->uniqueName, arg.val.v_string, arg.len); bus->uniqueName[arg.len] = '\0'; } } } AJ_CloseMsg(&helloResponse); // subscribe to the signal NameOwnerChanged and wait for the response status = AJ_BusSetSignalRule(bus, "type='signal',member='NameOwnerChanged',interface='org.freedesktop.DBus'", AJ_BUS_SIGNAL_ALLOW); if (status == AJ_OK) { uint8_t found_reply = FALSE; AJ_Message msg; AJ_Time timer; AJ_InitTimer(&timer); while (found_reply == FALSE && AJ_GetElapsedTime(&timer, TRUE) < 3000) { status = AJ_UnmarshalMsg(bus, &msg, 3000); if (status == AJ_OK) { switch (msg.msgId) { case AJ_REPLY_ID(AJ_METHOD_ADD_MATCH): found_reply = TRUE; break; default: // ignore everything else AJ_BusHandleBusMessage(&msg); break; } AJ_CloseMsg(&msg); } } } } } ExitConnect: if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Authenticate(): status=%s\n", AJ_StatusText(status))); } return status; }
AJ_Status AJ_StartClient(AJ_BusAttachment* bus, const char* daemonName, uint32_t timeout, uint8_t connected, const char* name, uint16_t port, uint32_t* sessionId, const AJ_SessionOpts* opts) { AJ_Status status = AJ_OK; AJ_Time timer; uint8_t foundName = FALSE; uint8_t clientStarted = FALSE; uint32_t elapsed = 0; AJ_InfoPrintf(("AJ_StartClient(bus=0x%p, daemonName=\"%s\", timeout=%d., connected=%d., name=\"%s\", port=%d., sessionId=0x%p, opts=0x%p)\n", bus, daemonName, timeout, connected, name, port, sessionId, opts)); AJ_InitTimer(&timer); while (elapsed < timeout) { if (!connected) { AJ_InfoPrintf(("AJ_StartClient(): AJ_FindBusAndConnect()\n")); status = AJ_FindBusAndConnect(bus, daemonName, AJ_CONNECT_TIMEOUT); elapsed = AJ_GetElapsedTime(&timer, TRUE); if (status != AJ_OK) { elapsed += AJ_CONNECT_PAUSE; if (elapsed > timeout) { break; } AJ_WarnPrintf(("Failed to connect to bus sleeping for %d seconds\n", AJ_CONNECT_PAUSE / 1000)); AJ_Sleep(AJ_CONNECT_PAUSE); continue; } AJ_InfoPrintf(("AllJoyn client connected to bus\n")); } /* * Kick things off by finding the service names */ AJ_InfoPrintf(("AJ_StartClient(): AJ_BusFindAdvertisedName()\n")); status = AJ_BusFindAdvertisedName(bus, name, AJ_BUS_START_FINDING); if (status == AJ_OK) { break; } if (!connected) { AJ_WarnPrintf(("AjStartClient2(): AJ_Disconnect(): status=%s.\n", AJ_StatusText(status))); AJ_Disconnect(bus); } } if (elapsed > timeout) { return AJ_ERR_TIMEOUT; } timeout -= elapsed; *sessionId = 0; while (!clientStarted && (status == AJ_OK)) { AJ_Message msg; status = AJ_UnmarshalMsg(bus, &msg, AJ_UNMARSHAL_TIMEOUT); if ((status == AJ_ERR_TIMEOUT) && !foundName) { /* * Timeouts are expected until we find a name */ if (timeout < AJ_UNMARSHAL_TIMEOUT) { return status; } timeout -= AJ_UNMARSHAL_TIMEOUT; status = AJ_OK; continue; } if (status != AJ_OK) { AJ_ErrPrintf(("AJ_StartClient(): status=%s\n", AJ_StatusText(status))); break; } switch (msg.msgId) { case AJ_REPLY_ID(AJ_METHOD_FIND_NAME): case AJ_REPLY_ID(AJ_METHOD_FIND_NAME_BY_TRANSPORT): if (msg.hdr->msgType == AJ_MSG_ERROR) { AJ_ErrPrintf(("AJ_StartClient(): AJ_METHOD_FIND_NAME: %s\n", msg.error)); status = AJ_ERR_FAILURE; } else { uint32_t disposition; AJ_UnmarshalArgs(&msg, "u", &disposition); if ((disposition != AJ_FIND_NAME_STARTED) && (disposition != AJ_FIND_NAME_ALREADY)) { AJ_ErrPrintf(("AJ_StartClient(): AJ_ERR_FAILURE\n")); status = AJ_ERR_FAILURE; } } break; case AJ_SIGNAL_FOUND_ADV_NAME: { AJ_Arg arg; AJ_UnmarshalArg(&msg, &arg); AJ_InfoPrintf(("FoundAdvertisedName(%s)\n", arg.val.v_string)); foundName = TRUE; status = AJ_BusJoinSession(bus, arg.val.v_string, port, opts); } break; case AJ_REPLY_ID(AJ_METHOD_JOIN_SESSION): { uint32_t replyCode; if (msg.hdr->msgType == AJ_MSG_ERROR) { AJ_ErrPrintf(("AJ_StartClient(): AJ_METHOD_JOIN_SESSION: %s\n", msg.error)); status = AJ_ERR_FAILURE; } else { status = AJ_UnmarshalArgs(&msg, "uu", &replyCode, sessionId); if (replyCode == AJ_JOINSESSION_REPLY_SUCCESS) { clientStarted = TRUE; } else { AJ_ErrPrintf(("AJ_StartClient(): AJ_ERR_FAILURE\n")); status = AJ_ERR_FAILURE; } } } break; case AJ_SIGNAL_SESSION_LOST_WITH_REASON: /* * Force a disconnect */ { uint32_t id, reason; AJ_UnmarshalArgs(&msg, "uu", &id, &reason); AJ_InfoPrintf(("Session lost. ID = %u, reason = %u", id, reason)); } AJ_ErrPrintf(("AJ_StartClient(): AJ_SIGNAL_SESSION_LOST_WITH_REASON: AJ_ERR_READ\n")); status = AJ_ERR_READ; break; default: /* * Pass to the built-in bus message handlers */ AJ_InfoPrintf(("AJ_StartClient(): AJ_BusHandleBusMessage()\n")); status = AJ_BusHandleBusMessage(&msg); break; } AJ_CloseMsg(&msg); } if (status != AJ_OK) { AJ_WarnPrintf(("AJ_StartClient(): AJ_Disconnect(): status=%s\n", AJ_StatusText(status))); AJ_Disconnect(bus); } return status; }
/* * Poll over a socket until there is data ready or till a timeout * * Returns -2 on timeout * -1 on interrupted * 1 on success * 0 on close * */ int16_t AJ_WSL_NET_socket_select(AJ_WSL_SOCKNUM sock, uint32_t timeout) { AJ_Time timer; wsl_work_item* peek; AJ_Status status; int16_t ret = 0; // Check if the socket is valid if (sock >= AJ_WSL_SOCKET_MAX) { // tried to get data from an invalid socket, return an error return ret; } if (AJ_WSL_SOCKET_CONTEXT[sock].valid == FALSE) { // tried to get data from an invalid socket, return the data read from the stash AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1); AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate(); //flush the queue return ret; } AJ_InitTimer(&timer); // There are 5 conditions that we need to check for // 1. If we got an interrupted work item // 2. If there is data in the RX stash // 3. If there is a RX work item in the queue // 4. If there is a socket close work item in the queue // 5. If the timeout has expired while (1) { status = AJ_QueuePeek(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek); //AJ_AlwaysPrintf(("Item type = %u\n", peek->itemType)); if ((status == AJ_OK) && (peek->itemType == WSL_NET_INTERUPT)) { // Pull the interrupted item off because we dont need it anymore AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek, 0); AJ_WSL_WMI_FreeWorkItem(peek); ret = -1; break; } else if (AJ_BufListLengthOnWire(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList) > 0) { ret = 1; break; } else if ((status == AJ_OK) && (peek->itemType == WSL_NET_DATA_RX)) { ret = 1; break; } else if ((status == AJ_OK) && (peek->itemType == WSL_NET_CLOSE || peek->itemType == WSL_NET_DISCONNECT || peek->itemType == AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_SOCKET, WSL_SOCK_CLOSE))) { // Pull the close work item off the queue AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue, &peek, 0); // Socket was closed so tear down the connections AJ_WSL_SOCKET_CONTEXT[sock].valid = FALSE; // Removed any stashed data AJ_BufListFree(AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList, 1); // Reallocate a new stash AJ_WSL_SOCKET_CONTEXT[sock].stashedRxList = AJ_BufListCreate(); // Reset the queue, any work items are now invalid since the socket was closed AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workRxQueue); AJ_QueueReset(AJ_WSL_SOCKET_CONTEXT[sock].workTxQueue); AJ_WSL_WMI_FreeWorkItem(peek); ret = 0; break; } else if (AJ_GetElapsedTime(&timer, TRUE) >= timeout) { ret = -2; break; } } return ret; }
AJ_EXPORT AJ_Status AJ_WSL_WriteBufListToMBox(uint8_t box, uint8_t endpoint, uint16_t len, AJ_BufList* list) { AJ_Status status = AJ_ERR_SPI_WRITE; uint16_t spaceAvailable = 0; uint16_t bytesRemaining; uint16_t cause = 0; AJ_ASSERT(0 == box); // AJ_InfoPrintf(("=HTC Credits 0:%x, 1:%x, 2:%x\n", AJ_WSL_HTC_Global.endpoints[0].txCredits, AJ_WSL_HTC_Global.endpoints[1].txCredits, AJ_WSL_HTC_Global.endpoints[2].txCredits)); AJ_Time credit_timer; AJ_InitTimer(&credit_timer); while (AJ_WSL_HTC_Global.endpoints[endpoint].txCredits < 1) { // do nothing and wait until there are credits if (AJ_GetElapsedTime(&credit_timer, TRUE) > 1500) { AJ_WSL_HTC_Global.endpoints[endpoint].txCredits++; break; } AJ_YieldCurrentTask(); } // don't let the other tasks interrupt our SPI access AJ_EnterCriticalRegion(); AJ_Time space_timer; AJ_InitTimer(&space_timer); // read space available in mbox from register do { if (AJ_GetElapsedTime(&space_timer, TRUE) > 1500) { spaceAvailable = 0xc5b; AJ_WSL_SPI_RegisterWrite(AJ_WSL_SPI_REG_SPI_CONFIG, 1 << 15); break; } status = AJ_WSL_GetWriteBufferSpaceAvailable(&spaceAvailable); } while (spaceAvailable == 0); AJ_ASSERT((status == AJ_OK) && (spaceAvailable >= len)); if ((status == AJ_OK) && (spaceAvailable >= len)) { uint16_t targetAddress; // write size to be transferred status = AJ_WSL_SetDMABufferSize(len); AJ_ASSERT(status == AJ_OK); // write the target address (where we want to send data) // the write should end up at the end of the MBox alias // example 0xFFF - len targetAddress = AJ_WSL_SPI_MBOX_0_EOM_ALIAS - len; status = AJ_WSL_SPI_DMAWriteStart(targetAddress); AJ_ASSERT(status == AJ_OK); bytesRemaining = len; // Take the AJ_BufList to write out and write it out to the SPI interface via DMA AJ_WSL_BufListIterate_DMA(list); // clear the packet available interrupt cause = 0x1f; status = AJ_WSL_SPI_RegisterWrite(AJ_WSL_SPI_REG_INTR_ENABLE, cause); AJ_ASSERT(status == AJ_OK); AJ_WSL_HTC_Global.endpoints[endpoint].txCredits -= 1; } else { status = AJ_ERR_SPI_NO_SPACE; } AJ_LeaveCriticalRegion(); return status; }
AJ_Status AJ_FindBusAndConnect(AJ_BusAttachment* bus, const char* serviceName, uint32_t timeout) { AJ_Status status; AJ_Service service; AJ_Time connectionTimer; int32_t connectionTime; uint8_t finished = FALSE; bus->isAuthenticated = FALSE; bus->isProbeRequired = TRUE; AJ_InfoPrintf(("AJ_FindBusAndConnect(bus=0x%p, serviceName=\"%s\", timeout=%d, selection timeout=%d.)\n", bus, serviceName, timeout, selectionTimeout)); // Clear the bus struct memset(bus, 0, sizeof(AJ_BusAttachment)); // Clear stale name->GUID mappings AJ_GUID_ClearNameMap(); // Discover a daemon or service to connect to if (!serviceName) { serviceName = daemonService; } while (finished == FALSE) { finished = TRUE; connectionTime = (int32_t) timeout; #if AJ_CONNECT_LOCALHOST service.ipv4port = 9955; #if HOST_IS_LITTLE_ENDIAN service.ipv4 = 0x0100007F; // 127.0.0.1 #endif #if HOST_IS_BIG_ENDIAN service.ipv4 = 0x7f000001; // 127.0.0.1 #endif service.addrTypes = AJ_ADDR_TCP4; #else AJ_InitTimer(&connectionTimer); printf("AJ_FindBusAndConnect(): Connection timer started\n"); status = AJ_Discover(serviceName, &service, timeout, selectionTimeout);//aj_disco.c if (status != AJ_OK) { printf("AJ_FindBusAndConnect(): AJ_Discover status=%s\n", AJ_StatusText(status)); goto ExitConnect; } #endif // this calls into platform code that will decide whether to use UDP or TCP, based on what is available printf("TCP connection started \n"); status = AJ_Net_Connect(bus, &service); if (status != AJ_OK) { printf("AJ_FindBusAndConnect(): AJ_Net_Connect status=%s\n", AJ_StatusText(status)); goto ExitConnect; } status = AJ_Authenticate(bus); if (status != AJ_OK) { printf("AJ_FindBusAndConnect(): AJ_Authenticate status=%s\n", AJ_StatusText(status)); #if ((!AJ_CONNECT_LOCALHOST) && (!defined(ARDUINO)) && (!defined(AJ_SERIAL_CONNECTION))) printf("AJ_FindBusAndConnect(): Blacklisting routing node\n"); // какие-то махинации с данными AddRoutingNodeToBlacklist(&service); // try again finished = FALSE; connectionTime -= AJ_GetElapsedTime(&connectionTimer, FALSE); // select a new node from the response list while (connectionTime > 0) { // махинация с данными status = AJ_SelectRoutingNodeFromResponseList(&service); if (status == AJ_ERR_END_OF_DATA) { status = AJ_ERR_TIMEOUT; //AJ_InfoPrintf(("Exhausted all the retries from the response list\n")); finished = FALSE; break; } printf("Retrying with a new selection from the routing node response list\n"); status = AJ_Net_Connect(bus, &service); if (status != AJ_OK) { printf("AJ_FindBusAndConnect(): AJ_Net_Connect status=%s\n", AJ_StatusText(status)); goto ExitConnect; } status = AJ_Authenticate(bus); if (status == AJ_OK) { finished = TRUE; break; } else { connectionTime -= AJ_GetElapsedTime(&connectionTimer, FALSE); } } #endif } if (status != AJ_OK) { printf("AJ_FindBusAndConnect(): AJ_Authenticate status=%s\n", AJ_StatusText(status)); goto ExitConnect; } status = SetSignalRules(bus); if (status != AJ_OK) { printf("AJ_FindBusAndConnect(): SetSignalRules status=%s\n", AJ_StatusText(status)); goto ExitConnect; } AJ_InitRoutingNodeResponselist(); } ExitConnect: AJ_InitRoutingNodeResponselist(); if (status != AJ_OK) { printf("AJ_FindBusAndConnect(): status=%s\n", AJ_StatusText(status)); //закрываем соединение AJ_Disconnect(bus); } return status; }
AJ_Status AJ_PeerHandleAuthChallenge(AJ_Message* msg, AJ_Message* reply) { AJ_Status status; AJ_Arg arg; char* buf = NULL; const AJ_GUID* peerGuid = AJ_GUID_Find(msg->sender); /* * We expect to know the GUID of the sender */ if (!peerGuid) { return AJ_MarshalErrorMsg(msg, reply, AJ_ErrRejected); } /* * Check for an authentication conversation in progress with a different peer */ if (authContext.peerGuid && (authContext.peerGuid != peerGuid)) { /* * Reject the request if the existing conversation has not expired */ if (AJ_GetElapsedTime(&authContext.timer, TRUE) < MAX_AUTH_TIME) { return AJ_MarshalErrorMsg(msg, reply, AJ_ErrRejected); } memset(&authContext, 0, sizeof(AuthContext)); } if (authContext.sasl.state == AJ_SASL_IDLE) { /* * Remember which peer is being authenticated and initialize the timeout timer */ authContext.peerGuid = peerGuid; AJ_InitTimer(&authContext.timer); /* * Initialize SASL state machine */ AJ_SASL_InitContext(&authContext.sasl, authMechanisms, AJ_AUTH_CHALLENGER, msg->bus->pwdCallback); } if (AJ_UnmarshalArg(msg, &arg) != AJ_OK) { goto FailAuth; } /* * Need a short-lived buffer to compose the response */ buf = (char*)AJ_Malloc(AUTH_BUF_LEN); if (!buf) { status = AJ_ERR_RESOURCES; goto FailAuth; } status = AJ_SASL_Advance(&authContext.sasl, (char*)arg.val.v_string, buf, AUTH_BUF_LEN); if (status != AJ_OK) { goto FailAuth; } AJ_MarshalReplyMsg(msg, reply); AJ_MarshalArgs(reply, "s", buf); AJ_Free(buf); if (authContext.sasl.state == AJ_SASL_AUTHENTICATED) { status = authContext.sasl.mechanism->Final(peerGuid); memset(&authContext, 0, sizeof(AuthContext)); } return status; FailAuth: AJ_Free(buf); /* * Clear current authentication context then return an error response */ if (authContext.sasl.mechanism) { authContext.sasl.mechanism->Final(peerGuid); } memset(&authContext, 0, sizeof(AuthContext)); return AJ_MarshalErrorMsg(msg, reply, AJ_ErrSecurityViolation); }
void AJ_Main(void) { uint8_t i = 0; AJ_Status status = AJ_ERR_FAILURE; /* the glass is half-empty */ AJ_BusAttachment bus; /* these variables are used when kicking off DHCP */ uint32_t current_ip_address = 0; uint32_t current_subnet_mask = 0; uint32_t current_default_gateway = 0; AJ_Time dhcpTimer; uint32_t timeTakenForDhcp = 0; AJ_Initialize(); AJ_Printf("\nAllJoyn Release: %s\n\n", AJ_GetVersion()); AJ_Printf("INFO: The parameter RUN_NEGATIVE_TESTS is %s\n", (RUN_NEGATIVE_TESTS ? "true" : "false")); AJ_Printf("INFO: The parameter DELAY_BETWEEN_SCANS is %u ms\n", DELAY_BETWEEN_SCANS); AJ_Printf("INFO: The parameter DELAY_BETWEEN_ASSOCIATIONS is %u ms\n", DELAY_BETWEEN_ASSOCIATIONS); AJ_Printf("INFO: The parameter DHCP_TIMEOUT is %u ms\n", DHCP_TIMEOUT); AJ_Printf("INFO: The parameter DISCOVER_TIMEOUT is %u ms\n", DISCOVER_TIMEOUT); /* reset the wifi to start with a clean slate */ status = AJ_ResetWiFi(); if (AJ_OK != status) { AJ_Printf("WARN: AJ_ResetWiFi returned %s (code: %u).\n", AJ_StatusText(status), status); } /* * Repeatedly do the following: * a. scan for access points in the vicinity * b. For each open access point in the returned results: * i. associate using AJ_ConnectWiFi * ii. acquire an ip address using AJ_AcquireIPAddress * iii. perform a short-lived discovery on some random node prefix * using AJ_FindBusAndConnect * iv. disassociate using AJ_DisconnectWiFi * c. For each secured access point in the returned results: * i. Connect to it with intentionally incorrect parameters * (Negative test) */ while (TRUE) { AJ_RandBytes(¤tContext, sizeof(currentContext)); uint8_t currentMaxAps = 0; AJ_RandBytes(¤tMaxAps, sizeof(currentMaxAps)); /* Reset numValidScanEntries, before every scan attempt. */ numValidScanEntries = 0; status = AJ_WiFiScan((void*) (sentinelForWifiScanContext + currentContext), wifiScanResultCallback, currentMaxAps); if (AJ_OK != status) { if (AJ_ERR_FAILURE == status && 0 != currentMaxAps) { scanStats.numFailed++; } else if (AJ_ERR_RESOURCES == status) { scanStats.numFailed++; } AJ_Printf("Failed to scan: %s (code: %u)\n", AJ_StatusText(status), status); /* No point in attempting to do wifi operations, when scan failed */ continue; } else { /* * A success was returned from AJ_WiFiScan. Were any results * returned after all?? */ if (0 < numValidScanEntries) { scanStats.numSuccessful++; } else { AJ_Printf("WARN: AJ_WiFiScan returned %s (code: %u), but returned ZERO scan results...\n", AJ_StatusText(status), status); scanStats.numFailed++; /* When num of scan results is zero, there is nothing to do */ continue; } } /* numValidScanEntries is an index into the array. Hence +1. */ if (currentMaxAps < numValidScanEntries + 1) { AJ_Printf("WARN: Scan returned more results (%u) than requested (%u).\n", numValidScanEntries + 1, currentMaxAps); } else { AJ_Printf("Wifi scan successful (got %u results).\n", numValidScanEntries); } for (i = 0; i < numValidScanEntries; i++) { if (AJ_WIFI_SECURITY_NONE != wifiScanInfo[i].secType) { /* On some targets, it is not possible to check for 802.11 * authentication failure when security type is WEP. * Hence, run negative tests only for WPA/WPA2-based APs. */ if (RUN_NEGATIVE_TESTS && AJ_WIFI_SECURITY_WEP != wifiScanInfo[i].secType) { /* Run a negative test for wifi association */ AJ_Printf("RUN (negative test): Attempting to associate with %s using a randomly generated passphrase...", wifiScanInfo[i].ssid); char random_passphrase[128 + 1]; AJ_RandHex(random_passphrase, sizeof(random_passphrase), (sizeof(random_passphrase) - 1) / 2); /* Set a random passphrase length based on security type */ uint8_t randomPassphraseLen = 0; /* WPA / WPA2 - assuming min len is 8 and max is 64 */ AJ_RandBytes(&randomPassphraseLen, sizeof(randomPassphraseLen)); randomPassphraseLen = 8 + randomPassphraseLen % (64 - 8 + 1); random_passphrase[randomPassphraseLen] = '\0'; status = AJ_ConnectWiFi(wifiScanInfo[i].ssid, wifiScanInfo[i].secType, wifiScanInfo[i].cipherType, random_passphrase); if (AJ_OK == status) { /* negative test failed */ AJ_Printf("FAIL (negative test): Associated with SSID: %s BSSID: %x:%x:%x:%x:%x:%x Security: %s(%s) Passphrase: %s RSSI: %u ...\n", wifiScanInfo[i].ssid, wifiScanInfo[i].bssid[0], wifiScanInfo[i].bssid[1], wifiScanInfo[i].bssid[2], wifiScanInfo[i].bssid[3], wifiScanInfo[i].bssid[4], wifiScanInfo[i].bssid[5], secStr[wifiScanInfo[i].secType], ciphStr[wifiScanInfo[i].cipherType], random_passphrase, wifiScanInfo[i].rssi); /* negative test failed - don't go any further */ AJ_ASSERT(0); } else { AJ_Printf("Done (negative test).\n"); } status = AJ_DisconnectWiFi(); AJ_Sleep(DELAY_BETWEEN_ASSOCIATIONS); } continue; } else { AJ_Printf("Attempting to associate with SSID: %s BSSID: %x:%x:%x:%x:%x:%x Security: %s(%s) RSSI: %u ...\n", wifiScanInfo[i].ssid, wifiScanInfo[i].bssid[0], wifiScanInfo[i].bssid[1], wifiScanInfo[i].bssid[2], wifiScanInfo[i].bssid[3], wifiScanInfo[i].bssid[4], wifiScanInfo[i].bssid[5], secStr[wifiScanInfo[i].secType], ciphStr[wifiScanInfo[i].cipherType], wifiScanInfo[i].rssi); status = AJ_ConnectWiFi(wifiScanInfo[i].ssid, wifiScanInfo[i].secType, wifiScanInfo[i].cipherType, ""); if (AJ_OK != status) { associationStats.numFailed++; AJ_Printf("Failed to associate : %s (code: %u)\n", AJ_StatusText(status), status); /* * No point in proceeding any further when WiFi association * has failed */ continue; } else { associationStats.numSuccessful++; } AJ_Printf("Successfully associated. Attempting to get IP Address via DHCP...\n"); AJ_InitTimer(&dhcpTimer); status = AJ_AcquireIPAddress(¤t_ip_address, ¤t_subnet_mask, ¤t_default_gateway, DHCP_TIMEOUT); timeTakenForDhcp = AJ_GetElapsedTime(&dhcpTimer, FALSE); if (AJ_OK != status) { if (AJ_ERR_TIMEOUT == status) { dhcpStats.numTimedout++; AJ_Printf("Timedout (%u ms) while trying to get IP Address via DHCP\n", timeTakenForDhcp); /* * Discovery timed out. * Check whether the API returned in a timely manner. * See whether the actual duration is off by +/- 500ms. * Delay beyond that is unusual. */ if (500 < abs(DHCP_TIMEOUT - timeTakenForDhcp)) { AJ_Printf("WARN: AJ_AcquireIPAddress API did not return in a timely manner. Timeout parameter: %u Actual time elapsed: %u\n", DHCP_TIMEOUT, timeTakenForDhcp); } } else { dhcpStats.numFailed++; AJ_Printf("Failed to get IP Address via DHCP : %s (code: %u)\n", AJ_StatusText(status), status); } /* * No point in proceeding any further when IP address was * not acquired */ continue; } else { dhcpStats.numSuccessful++; AJ_Printf("Successfully obtained\n"); AJ_Printf("\tIP Addresss : %s\n", TestAddrStr(current_ip_address)); AJ_Printf("\tSubnet Mask : %s\n", TestAddrStr(current_subnet_mask)); AJ_Printf("\tDefault Gateway: %s\n", TestAddrStr(current_default_gateway)); } /* Generate a random name using routingNodePrefix */ char currentRoutingNodeName[32 + 1]; strncpy(currentRoutingNodeName, routingNodePrefix, sizeof(routingNodePrefix)); AJ_RandHex(currentRoutingNodeName + strlen(routingNodePrefix), sizeof(currentRoutingNodeName) - sizeof(routingNodePrefix), (sizeof(currentRoutingNodeName) - sizeof(routingNodePrefix) - 1) / 2); currentRoutingNodeName[32] = '\0'; /* just to be safe */ AJ_Printf("Attempting to discover routing node: %s...", currentRoutingNodeName); status = AJ_FindBusAndConnect(&bus, currentRoutingNodeName, DISCOVER_TIMEOUT); if (AJ_ERR_TIMEOUT == status) { /* this is the expected result */ discoverStats.numTimedout++; AJ_Printf("Done (discovery of routing node).\n"); } else if (AJ_OK != status) { discoverStats.numFailed++; AJ_Printf("Failed to connect to routing node: %s (code: %u)\n", AJ_StatusText(status), status); } else if (AJ_OK == status) { /* * the test attempted to discovery a randomly generated * routing node prefix and it worked - highly unlikely event */ AJ_Printf("FATAL: Was able to discover and connect to routing node with prefix %s. Got unique address %s.", currentRoutingNodeName, AJ_GetUniqueName(&bus)); AJ_ASSERT(0); } status = AJ_DisconnectWiFi(); if (AJ_OK != status) { disassociationStats.numFailed++; AJ_Printf("Failed to disassociate: %s (code: %u)\n", AJ_StatusText(status), status); } else { disassociationStats.numSuccessful++; AJ_Printf("Disassociated from access point. "); } AJ_Sleep(DELAY_BETWEEN_ASSOCIATIONS); } } PrintStats(); AJ_Sleep(DELAY_BETWEEN_SCANS); } }
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_EXPORT AJ_Status AJ_WSL_NET_connect(const char* SSID, const char* passphrase, WSL_NET_AUTH_MODE auth, WSL_NET_CRYPTO_TYPE crypto, uint8_t softAP) { AJ_Status status = AJ_OK; wsl_scan_list* list; list = (wsl_scan_list*)AJ_WSL_GetScanList(); AJ_WSL_NET_SetPowerMode(2); uint8_t bss_mac[6]; // Open auth does not require you to explicitly set the BSSID so this secondary scan is not needed if (!softAP) { if (auth != WSL_NET_AUTH_NONE) { AJ_Time timer; uint8_t found = 0; AJ_InitTimer(&timer); while (!found) { AJ_WSL_InitScanList(AJ_WSL_SCAN_LIST_SIZE); AJ_WSL_SetProbedSSID(SSID, 1); status = AJ_WSL_NET_scan(); // Some kind of scan error if (status != AJ_OK) { WSL_ClearScanList(); continue; } AJ_WSL_NET_scan_stop(); if (AJ_GetElapsedTime(&timer, TRUE) > AJ_WSL_CONNECT_TIMEOUT) { AJ_ErrPrintf(("AJ_WSL_NET_connect() Could not find the access point %s\n", SSID)); WSL_ClearScanList(); return AJ_ERR_FAILURE; } // Find the SSID you want to connect to in the second scan list if (getMacFromSSID(SSID, bss_mac, list)) { WSL_ClearScanList(); found = 1; break; } else { WSL_ClearScanList(); AJ_Sleep(AJ_WSL_CONNECT_WAIT); continue; } } if (crypto != WSL_NET_CRYPTO_WEP) { status = AJ_WSL_NET_SetPassphrase(SSID, passphrase, strlen(passphrase)); if (status != AJ_OK) { return status; } } } } { AJ_BufList* connect; AJ_BufList* connectOut; static const uint8_t zero_mac[6] = { 0, 0, 0, 0, 0, 0 }; uint8_t connect_mac[6]; wsl_work_item* item = NULL; connect = AJ_BufListCreate(); /* Three different ways connect can be called. * 1. SoftAP: The devices mac is fetched and used * 2. Using Auth: The SSID's mac is found and used * 3. Open auth: A zero'ed mac is used */ if (softAP) { WSL_MarshalPacket(connect, WSL_SET_SOFT_AP, 0, 0x04, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, getDeviceMac(), 0x0044, 0x0000); WMI_MarshalHeader(connect, 1, 1); } else if ((auth != WSL_NET_AUTH_NONE) && (crypto != WSL_NET_CRYPTO_WEP)) { WSL_MarshalPacket(connect, WSL_CONNECT, 0, 0x01, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, &bss_mac, 0x0044, 0x0000); WMI_MarshalHeader(connect, 1, 1); } else { // if the auth mode is open, use zero_mac, and set flags to zero WSL_MarshalPacket(connect, WSL_CONNECT, 0, 0x01, 0x01, auth, crypto, 0x00, crypto, 0x00, strlen(SSID), SSID, 0x0, &zero_mac, 0x0000, 0x0000); WMI_MarshalHeader(connect, 1, 1); } AJ_InfoPrintf(("AJ_WSL_NET_connect(): CONNECT\n")); AJ_WSL_WMI_PadPayload(connect); //AJ_BufListPrintDumpContinuous(connect); connectOut = AJ_BufListCreateCopy(connect); AJ_WSL_WMI_QueueWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), AJ_WSL_HTC_DATA_ENDPOINT1, connectOut); if (softAP) { AJ_AlwaysPrintf(("Waiting for a connection to the softAP %s\n", SSID)); memcpy(&connect_mac, (uint8_t*)getDeviceMac(), sizeof(connect_mac)); while (memcmp((uint8_t*)&connect_mac, (uint8_t*)getDeviceMac(), 6) == 0) { status = AJ_WSL_WMI_WaitForWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), &item, AJ_TIMER_FOREVER); if (item && (status == AJ_OK)) { if (item->itemType == WSL_NET_CONNECT) { AJ_InfoPrintf(("AJ_WSL_NET_connect(): WORK ITEM RECEIVED\n")); uint16_t WMIEvent; uint32_t toss; uint16_t channel; WMI_Unmarshal(item->node->buffer, "quqM", &WMIEvent, &toss, &channel, &connect_mac); } else { AJ_WarnPrintf(("AJ_WSL_NET_connect(): BAD WORK ITEM RECEIVED\n")); } AJ_WSL_WMI_FreeWorkItem(item); } } } else { status = AJ_WSL_WMI_WaitForWorkItem(0, AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_NETWORK, WSL_NET_CONNECT), &item, AJ_TIMER_FOREVER); if (item && (status == AJ_OK)) { AJ_WSL_WMI_FreeWorkItem(item); } } AJ_BufListFree(connect, 1); return status; } }
AJ_Status AJ_StartService2(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; uint8_t initial = TRUE; AJ_InitTimer(&timer); while (TRUE) { if (AJ_GetElapsedTime(&timer, TRUE) > timeout) { return AJ_ERR_TIMEOUT; } if (!initial || !connected) { initial = FALSE; AJ_InfoPrintf(("Attempting to connect to bus\n")); status = AJ_Connect(bus, daemonName, CONNECT_TIMEOUT); if (status != AJ_OK) { AJ_WarnPrintf(("Failed to connect to bus sleeping for %d seconds\n", CONNECT_PAUSE / 1000)); AJ_Sleep(CONNECT_PAUSE); continue; } AJ_InfoPrintf(("AllJoyn service connected to bus\n")); } /* * Kick things off by binding a session port */ status = AJ_BusBindSessionPort(bus, port, opts); if (status == AJ_OK) { break; } AJ_ErrPrintf(("Failed to send bind session port message\n")); AJ_Disconnect(bus); } while (!serviceStarted && (status == AJ_OK)) { AJ_Message msg; AJ_GetElapsedTime(&timer, TRUE); status = AJ_UnmarshalMsg(bus, &msg, UNMARSHAL_TIMEOUT); /* * TODO This is a temporary hack to work around buggy select imlpementations */ if (status == AJ_ERR_TIMEOUT) { if (AJ_GetElapsedTime(&timer, TRUE) < UNMARSHAL_TIMEOUT) { AJ_WarnPrintf(("Spurious timeout error - continuing\n")); status = AJ_OK; continue; } } if (status != AJ_OK) { break; } switch (msg.msgId) { case AJ_REPLY_ID(AJ_METHOD_BIND_SESSION_PORT): if (msg.hdr->msgType == AJ_MSG_ERROR) { status = AJ_ERR_FAILURE; } else { status = AJ_BusRequestName(bus, name, flags); } break; case AJ_REPLY_ID(AJ_METHOD_REQUEST_NAME): if (msg.hdr->msgType == AJ_MSG_ERROR) { status = AJ_ERR_FAILURE; } else { status = AJ_BusAdvertiseName(bus, name, AJ_TRANSPORT_ANY, AJ_BUS_START_ADVERTISING); } break; case AJ_REPLY_ID(AJ_METHOD_ADVERTISE_NAME): if (msg.hdr->msgType == AJ_MSG_ERROR) { status = AJ_ERR_FAILURE; } else { serviceStarted = TRUE; AJ_BusSetSignalRule2(bus, "NameOwnerChanged", "org.freedesktop.DBus", AJ_BUS_SIGNAL_ALLOW); } break; default: /* * Pass to the built-in bus message handlers */ status = AJ_BusHandleBusMessage(&msg); break; } AJ_CloseMsg(&msg); } if (status != AJ_OK) { AJ_WarnPrintf(("AllJoyn disconnect bus status=%s\n", AJ_StatusText(status))); AJ_Disconnect(bus); } return status; }
static AJ_Status StartClient(AJ_BusAttachment* bus, const char* daemonName, uint32_t timeout, uint8_t connected, const char* name, uint16_t port, const char** interfaces, uint32_t* sessionId, char* serviceName, const AJ_SessionOpts* opts) { AJ_Status status = AJ_OK; AJ_Time timer; uint8_t found = FALSE; uint8_t clientStarted = FALSE; uint32_t elapsed = 0; char* rule; size_t ruleLen; const char* base = "interface='org.alljoyn.About',sessionless='t'"; const char* impl = ",implements='"; const char** ifaces; AJ_InfoPrintf(("AJ_StartClient(bus=0x%p, daemonName=\"%s\", timeout=%d., connected=%d., interface=\"%p\", sessionId=0x%p, serviceName=0x%p, opts=0x%p)\n", bus, daemonName, timeout, connected, interfaces, sessionId, serviceName, opts)); AJ_InitTimer(&timer); if ((name == NULL && interfaces == NULL) || (name != NULL && interfaces != NULL)) { return AJ_ERR_INVALID; } while (elapsed < timeout) { if (!connected) { status = AJ_FindBusAndConnect(bus, daemonName, AJ_CONNECT_TIMEOUT); elapsed = AJ_GetElapsedTime(&timer, TRUE); if (status != AJ_OK) { elapsed += AJ_CONNECT_PAUSE; if (elapsed > timeout) { break; } AJ_WarnPrintf(("AJ_StartClient(): Failed to connect to bus, sleeping for %d seconds\n", AJ_CONNECT_PAUSE / 1000)); AJ_Sleep(AJ_CONNECT_PAUSE); continue; } AJ_InfoPrintf(("AJ_StartClient(): AllJoyn client connected to bus\n")); } if (name != NULL) { /* * Kick things off by finding the service names */ status = AJ_BusFindAdvertisedName(bus, name, AJ_BUS_START_FINDING); AJ_InfoPrintf(("AJ_StartClient(): AJ_BusFindAdvertisedName()\n")); } else { /* * Kick things off by finding all services that implement the interface */ ruleLen = strlen(base) + 1; ifaces = interfaces; while (*ifaces != NULL) { ruleLen += strlen(impl) + strlen(*ifaces) + 1; ifaces++; } rule = (char*) AJ_Malloc(ruleLen); if (rule == NULL) { status = AJ_ERR_RESOURCES; break; } strcpy(rule, base); ifaces = interfaces; while (*ifaces != NULL) { strcat(rule, impl); if ((*ifaces)[0] == '$') { strcat(rule, &(*ifaces)[1]); } else { strcat(rule, *ifaces); } strcat(rule, "'"); ifaces++; } status = AJ_BusSetSignalRule(bus, rule, AJ_BUS_SIGNAL_ALLOW); AJ_InfoPrintf(("AJ_StartClient(): Client SetSignalRule: %s\n", rule)); AJ_Free(rule); } if (status == AJ_OK) { break; } if (!connected) { AJ_WarnPrintf(("AJ_StartClient(): Client disconnecting from bus: status=%s.\n", AJ_StatusText(status))); AJ_Disconnect(bus); } } if (elapsed > timeout) { AJ_WarnPrintf(("AJ_StartClient(): Client timed-out trying to connect to bus: status=%s.\n", AJ_StatusText(status))); return AJ_ERR_TIMEOUT; } timeout -= elapsed; if (status != AJ_OK) { return status; } *sessionId = 0; if (serviceName != NULL) { *serviceName = '\0'; } while (!clientStarted && (status == AJ_OK)) { AJ_Message msg; status = AJ_UnmarshalMsg(bus, &msg, AJ_UNMARSHAL_TIMEOUT); if ((status == AJ_ERR_TIMEOUT) && !found) { /* * Timeouts are expected until we find a name or service */ if (timeout < AJ_UNMARSHAL_TIMEOUT) { return status; } timeout -= AJ_UNMARSHAL_TIMEOUT; status = AJ_OK; continue; } if (status == AJ_ERR_NO_MATCH) { // Ignore unknown messages status = AJ_OK; continue; } if (status != AJ_OK) { AJ_ErrPrintf(("AJ_StartClient(): status=%s\n", AJ_StatusText(status))); break; } switch (msg.msgId) { case AJ_REPLY_ID(AJ_METHOD_FIND_NAME): case AJ_REPLY_ID(AJ_METHOD_FIND_NAME_BY_TRANSPORT): if (msg.hdr->msgType == AJ_MSG_ERROR) { AJ_ErrPrintf(("AJ_StartClient(): AJ_METHOD_FIND_NAME: %s\n", msg.error)); status = AJ_ERR_FAILURE; } else { uint32_t disposition; AJ_UnmarshalArgs(&msg, "u", &disposition); if ((disposition != AJ_FIND_NAME_STARTED) && (disposition != AJ_FIND_NAME_ALREADY)) { AJ_ErrPrintf(("AJ_StartClient(): AJ_ERR_FAILURE\n")); status = AJ_ERR_FAILURE; } } break; case AJ_SIGNAL_FOUND_ADV_NAME: { AJ_Arg arg; AJ_UnmarshalArg(&msg, &arg); AJ_InfoPrintf(("FoundAdvertisedName(%s)\n", arg.val.v_string)); found = TRUE; status = AJ_BusJoinSession(bus, arg.val.v_string, port, opts); } break; case AJ_SIGNAL_ABOUT_ANNOUNCE: { uint16_t version, port; AJ_InfoPrintf(("AJ_StartClient(): AboutAnnounce from (%s)\n", msg.sender)); if (!found) { found = TRUE; AJ_UnmarshalArgs(&msg, "qq", &version, &port); status = AJ_BusJoinSession(bus, msg.sender, port, opts); if (serviceName != NULL) { strncpy(serviceName, msg.sender, AJ_MAX_NAME_SIZE); serviceName[AJ_MAX_NAME_SIZE] = '\0'; } if (status != AJ_OK) { AJ_ErrPrintf(("AJ_StartClient(): BusJoinSession failed (%s)\n", AJ_StatusText(status))); } } } break; case AJ_REPLY_ID(AJ_METHOD_JOIN_SESSION): { uint32_t replyCode; if (msg.hdr->msgType == AJ_MSG_ERROR) { AJ_ErrPrintf(("AJ_StartClient(): AJ_METHOD_JOIN_SESSION: %s\n", msg.error)); status = AJ_ERR_FAILURE; } else { status = AJ_UnmarshalArgs(&msg, "uu", &replyCode, sessionId); if (replyCode == AJ_JOINSESSION_REPLY_SUCCESS) { clientStarted = TRUE; } else { AJ_ErrPrintf(("AJ_StartClient(): AJ_METHOD_JOIN_SESSION reply (%d)\n", replyCode)); status = AJ_ERR_FAILURE; } } } break; case AJ_SIGNAL_SESSION_LOST_WITH_REASON: /* * Force a disconnect */ { uint32_t id, reason; AJ_UnmarshalArgs(&msg, "uu", &id, &reason); AJ_InfoPrintf(("Session lost. ID = %u, reason = %u", id, reason)); } AJ_ErrPrintf(("AJ_StartClient(): AJ_SIGNAL_SESSION_LOST_WITH_REASON: AJ_ERR_READ\n")); status = AJ_ERR_READ; break; default: /* * Pass to the built-in bus message handlers */ AJ_InfoPrintf(("AJ_StartClient(): AJ_BusHandleBusMessage()\n")); status = AJ_BusHandleBusMessage(&msg); break; } AJ_CloseMsg(&msg); } if (status != AJ_OK && !connected) { AJ_WarnPrintf(("AJ_StartClient(): Client disconnecting from bus: status=%s\n", AJ_StatusText(status))); AJ_Disconnect(bus); } return status; }
AJ_Status AJ_FindBusAndConnect(AJ_BusAttachment* bus, const char* serviceName, uint32_t timeout) { AJ_Status status; AJ_Service service; AJ_Time connectionTimer; int32_t connectionTime; uint8_t finished = FALSE; #ifdef AJ_SERIAL_CONNECTION AJ_Time start, now; AJ_InitTimer(&start); #endif AJ_InfoPrintf(("AJ_FindBusAndConnect(bus=0x%p, serviceName=\"%s\", timeout=%d, selection timeout=%d.)\n", bus, serviceName, timeout, selectionTimeout)); /* * Clear the bus struct */ memset(bus, 0, sizeof(AJ_BusAttachment)); bus->isProbeRequired = TRUE; /* * Clear stale name->GUID mappings */ AJ_GUID_ClearNameMap(); /* * Discover a daemon or service to connect to */ if (!serviceName) { serviceName = daemonService; } while (finished == FALSE) { finished = TRUE; connectionTime = (int32_t) timeout; #if AJ_CONNECT_LOCALHOST service.ipv4port = 9955; #if HOST_IS_LITTLE_ENDIAN service.ipv4 = 0x0100007F; // 127.0.0.1 #endif #if HOST_IS_BIG_ENDIAN service.ipv4 = 0x7f000001; // 127.0.0.1 #endif service.addrTypes = AJ_ADDR_TCP4; #elif defined(ARDUINO) service.ipv4port = 9955; service.ipv4 = 0x6501A8C0; // 192.168.1.101 service.addrTypes = AJ_ADDR_TCP4; AJ_InitTimer(&connectionTimer); AJ_InfoPrintf(("AJ_FindBusAndConnect(): Connection timer started\n")); status = AJ_Discover(serviceName, &service, timeout, selectionTimeout); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): AJ_Discover status=%s\n", AJ_StatusText(status))); goto ExitConnect; } #elif defined(AJ_SERIAL_CONNECTION) // don't bother with discovery, we are connected to a daemon. // however, take this opportunity to bring up the serial connection status = AJ_Serial_Up(); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): AJ_Serial_Up status=%s\n", AJ_StatusText(status))); } #else AJ_InitTimer(&connectionTimer); AJ_InfoPrintf(("AJ_FindBusAndConnect(): Connection timer started\n")); status = AJ_Discover(serviceName, &service, timeout, selectionTimeout); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): AJ_Discover status=%s\n", AJ_StatusText(status))); goto ExitConnect; } #endif // this calls into platform code that will decide whether to use UDP or TCP, based on what is available status = AJ_Net_Connect(bus, &service); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): AJ_Net_Connect status=%s\n", AJ_StatusText(status))); goto ExitConnect; } #ifdef AJ_SERIAL_CONNECTION // run the state machine for long enough to (hopefully) do the SLAP handshake do { AJ_StateMachine(); AJ_InitTimer(&now); } while (AJ_SerialLinkParams.linkState != AJ_LINK_ACTIVE && AJ_GetTimeDifference(&now, &start) < timeout); if (AJ_SerialLinkParams.linkState != AJ_LINK_ACTIVE) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): Failed to establish active SLAP connection in %u msec\n", timeout)); AJ_SerialShutdown(); return AJ_ERR_TIMEOUT; } #endif status = AJ_Authenticate(bus); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): AJ_Authenticate status=%s\n", AJ_StatusText(status))); #if !AJ_CONNECT_LOCALHOST && !defined(ARDUINO) && !defined(AJ_SERIAL_CONNECTION) if ((status == AJ_ERR_ACCESS_ROUTING_NODE) || (status == AJ_ERR_OLD_VERSION)) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): Blacklisting routing node\n")); AddRoutingNodeToBlacklist(&service, AJ_ADDR_TCP4); } AJ_Disconnect(bus); // try again finished = FALSE; connectionTime -= AJ_GetElapsedTime(&connectionTimer, FALSE); // select a new node from the response list while (connectionTime > 0) { status = AJ_SelectRoutingNodeFromResponseList(&service); if (status == AJ_ERR_END_OF_DATA) { status = AJ_ERR_TIMEOUT; AJ_InfoPrintf(("Exhausted all the retries from the response list\n")); finished = FALSE; break; } AJ_InfoPrintf(("Retrying with a new selection from the routing node response list\n")); status = AJ_Net_Connect(bus, &service); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): AJ_Net_Connect status=%s\n", AJ_StatusText(status))); goto ExitConnect; } status = AJ_Authenticate(bus); if (status == AJ_OK) { finished = TRUE; break; } if ((status == AJ_ERR_ACCESS_ROUTING_NODE) || (status == AJ_ERR_OLD_VERSION)) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): Blacklisting another routing node\n")); AddRoutingNodeToBlacklist(&service, AJ_ADDR_TCP4); } AJ_Disconnect(bus); connectionTime -= AJ_GetElapsedTime(&connectionTimer, FALSE); } #endif } if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): AJ_Authenticate status=%s\n", AJ_StatusText(status))); goto ExitConnect; } status = SetSignalRules(bus); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): SetSignalRules status=%s\n", AJ_StatusText(status))); goto ExitConnect; } AJ_InitRoutingNodeResponselist(); } ExitConnect: AJ_InitRoutingNodeResponselist(); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_FindBusAndConnect(): status=%s\n", AJ_StatusText(status))); AJ_Disconnect(bus); } return status; }
AJ_Status AJ_StartClient2(AJ_BusAttachment* bus, const char* daemonName, uint32_t timeout, uint8_t connected, const char* name, uint16_t port, uint32_t* sessionId, const AJ_SessionOpts* opts ) { AJ_Status status = AJ_OK; AJ_Time timer; AJ_Time unmarshalTimer; uint8_t foundName = FALSE; uint8_t clientStarted = FALSE; uint8_t initial = TRUE; AJ_InitTimer(&timer); while (TRUE) { if (AJ_GetElapsedTime(&timer, TRUE) > timeout) { return AJ_ERR_TIMEOUT; } if (!initial || !connected) { initial = FALSE; AJ_InfoPrintf(("Attempting to connect to bus\n")); status = AJ_Connect(bus, daemonName, CONNECT_TIMEOUT); if (status != AJ_OK) { AJ_WarnPrintf(("Failed to connect to bus sleeping for %d seconds\n", CONNECT_PAUSE / 1000)); AJ_Sleep(CONNECT_PAUSE); continue; } AJ_InfoPrintf(("AllJoyn client connected to bus\n")); } /* * Kick things off by finding the service names */ status = AJ_BusFindAdvertisedName(bus, name, AJ_BUS_START_FINDING); if (status == AJ_OK) { break; } AJ_WarnPrintf(("FindAdvertisedName failed\n")); AJ_Disconnect(bus); } *sessionId = 0; while (!clientStarted && (status == AJ_OK)) { AJ_Message msg; if (AJ_GetElapsedTime(&timer, TRUE) > timeout) { return AJ_ERR_TIMEOUT; } status = AJ_UnmarshalMsg(bus, &msg, UNMARSHAL_TIMEOUT); /* * TODO This is a temporary hack to work around buggy select imlpementations */ AJ_InitTimer(&unmarshalTimer); if (status == AJ_ERR_TIMEOUT && (AJ_GetElapsedTime(&unmarshalTimer, TRUE) < UNMARSHAL_TIMEOUT || !foundName)) { /* * Timeouts are expected until we find a name */ status = AJ_OK; continue; } if (status != AJ_OK) { break; } switch (msg.msgId) { case AJ_REPLY_ID(AJ_METHOD_FIND_NAME): case AJ_REPLY_ID(AJ_METHOD_FIND_NAME_BY_TRANSPORT): if (msg.hdr->msgType == AJ_MSG_ERROR) { status = AJ_ERR_FAILURE; } else { uint32_t disposition; AJ_UnmarshalArgs(&msg, "u", &disposition); if ((disposition != AJ_FIND_NAME_STARTED) && (disposition != AJ_FIND_NAME_ALREADY)) { status = AJ_ERR_FAILURE; } } break; case AJ_SIGNAL_FOUND_ADV_NAME: { AJ_Arg arg; AJ_UnmarshalArg(&msg, &arg); AJ_InfoPrintf(("FoundAdvertisedName(%s)\n", arg.val.v_string)); foundName = TRUE; status = AJ_BusJoinSession(bus, arg.val.v_string, port, opts); } break; case AJ_REPLY_ID(AJ_METHOD_JOIN_SESSION): { uint32_t replyCode; if (msg.hdr->msgType == AJ_MSG_ERROR) { status = AJ_ERR_FAILURE; } else { status = AJ_UnmarshalArgs(&msg, "uu", &replyCode, sessionId); if (replyCode == AJ_JOINSESSION_REPLY_SUCCESS) { clientStarted = TRUE; AJ_BusSetSignalRule2(bus, "NameOwnerChanged", "org.freedesktop.DBus", AJ_BUS_SIGNAL_ALLOW); } else { status = AJ_ERR_FAILURE; } } } break; case AJ_SIGNAL_SESSION_LOST: /* * Force a disconnect */ status = AJ_ERR_READ; break; default: /* * Pass to the built-in bus message handlers */ status = AJ_BusHandleBusMessage(&msg); break; } AJ_CloseMsg(&msg); } if (status != AJ_OK) { AJ_WarnPrintf(("AllJoyn disconnect bus status=%s\n", AJ_StatusText(status))); AJ_Disconnect(bus); } return status; }
static void* TriggerThread(void* arg) { fd_set readFds; fd_set exceptFds; resetFd = eventfd(0, O_NONBLOCK); // Use O_NONBLOCK instead of EFD_NONBLOCK due to bug in OpenWrt's uCLibc FD_ZERO(&readFds); AJ_InfoPrintf(("Started TriggerThread\n")); while (TRUE) { int ret; int i; int maxFd = resetFd; FD_SET(resetFd, &readFds); /* * Initialize the except FDs from the trigger list */ FD_ZERO(&exceptFds); for (i = 0; i < MAX_TRIGGERS; ++i) { if (triggers[i]) { FD_SET(triggers[i]->fd, &exceptFds); maxFd = max(maxFd, triggers[i]->fd); } } ret = select(maxFd + 1, &readFds, NULL, &exceptFds, NULL); if (ret < 0) { AJ_ErrPrintf(("Error: select returned %d\n", ret)); break; } /* * Need to clear the reset event by reading from the file descriptor. */ if (FD_ISSET(resetFd, &readFds)) { uint64_t u64; read(resetFd, &u64, sizeof(u64)); } /* * Figure out which GPIOs were triggered */ pthread_mutex_lock(&mutex); for (i = 0; i < MAX_TRIGGERS; ++i) { GPIO* gpio = triggers[i]; if (gpio && FD_ISSET(gpio->fd, &exceptFds)) { char buf[2]; /* * Consume the value */ pread(gpio->fd, buf, sizeof(buf), 0); /* * */ if (gpio->debounceMillis) { if (!BIT_IS_SET(trigSet, i)) { AJ_InitTimer(&gpio->timer); } else if (AJ_GetElapsedTime(&gpio->timer, TRUE) < gpio->debounceMillis) { continue; } } AJ_InfoPrintf(("Trigger on pin %d\n", gpio->pinId)); /* * Record which trigger fired and the leve */ BIT_SET(trigSet, i); if (buf[0] == '0') { BIT_CLR(trigLevel, i); } else { BIT_SET(trigLevel, i); } } } pthread_mutex_unlock(&mutex); if (trigSet) { AJ_Net_Interrupt(); } } close(resetFd); pthread_mutex_destroy(&mutex); resetFd = -1; return NULL; }
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; }
static AJ_Status MarshalMsg(AJ_Message* msg, uint8_t msgType, uint32_t msgId, uint8_t flags) { AJ_Status status = AJ_OK; AJ_IOBuffer* ioBuf = &msg->bus->sock.tx; uint8_t fieldId; uint8_t secure = FALSE; /* * Use the msgId to lookup information in the object and interface descriptions to * initialize the message header fields. */ status = AJ_InitMessageFromMsgId(msg, msgId, msgType, &secure); if (status != AJ_OK) { return status; } AJ_IO_BUF_RESET(ioBuf); msg->hdr = (AJ_MsgHeader*)ioBuf->bufStart; memset(msg->hdr, 0, sizeof(AJ_MsgHeader)); ioBuf->writePtr += sizeof(AJ_MsgHeader); msg->hdr->endianess = HOST_ENDIANESS; msg->hdr->msgType = msgType; msg->hdr->flags = flags; if (secure) { msg->hdr->flags |= AJ_FLAG_ENCRYPTED; } /* * The wire-protocol calls this flag NO_AUTO_START we toggle the meaning in the API * so the default flags value can be zero. */ msg->hdr->flags ^= AJ_FLAG_AUTO_START; /* * Serial number cannot be zero (wire-spec wierdness) */ do { msg->hdr->serialNum = msg->bus->serial++; } while (msg->bus->serial == 1); /* * Marshal the header fields */ for (fieldId = AJ_HDR_OBJ_PATH; fieldId <= AJ_HDR_SESSION_ID; ++fieldId) { char typeId = TypeForHdr[fieldId]; char buf[4]; const char* fieldSig = &buf[2]; AJ_Arg hdrVal; /* * Skip field id's that are not currently used. */ if (typeId == AJ_ARG_INVALID) { continue; } InitArg(&hdrVal, typeId, NULL); switch (fieldId) { case AJ_HDR_OBJ_PATH: if ((msgType == AJ_MSG_METHOD_CALL) || (msgType == AJ_MSG_SIGNAL)) { hdrVal.val.v_objPath = msg->objPath; } break; case AJ_HDR_INTERFACE: hdrVal.val.v_string = msg->iface; break; case AJ_HDR_MEMBER: if (msgType != AJ_MSG_ERROR) { int32_t len = AJ_StringFindFirstOf(msg->member, " "); hdrVal.val.v_string = msg->member; hdrVal.len = (len >= 0) ? len : 0; } break; case AJ_HDR_ERROR_NAME: if (msgType == AJ_MSG_ERROR) { hdrVal.val.v_string = msg->error; } break; case AJ_HDR_REPLY_SERIAL: if ((msgType == AJ_MSG_METHOD_RET) || (msgType == AJ_MSG_ERROR)) { hdrVal.val.v_uint32 = &msg->replySerial; } break; case AJ_HDR_DESTINATION: hdrVal.val.v_string = msg->destination; break; case AJ_HDR_SENDER: hdrVal.val.v_string = AJ_GetUniqueName(msg->bus); break; case AJ_HDR_SIGNATURE: hdrVal.val.v_signature = msg->signature; break; case AJ_HDR_TIMESTAMP: if (msg->ttl) { AJ_Time timer; timer.seconds = 0; timer.milliseconds = 0; msg->timestamp = AJ_GetElapsedTime(&timer, FALSE); hdrVal.val.v_uint32 = &msg->timestamp; } break; case AJ_HDR_TIME_TO_LIVE: if (msg->ttl) { hdrVal.val.v_uint32 = &msg->ttl; } break; case AJ_HDR_SESSION_ID: if (msg->sessionId) { hdrVal.val.v_uint32 = &msg->sessionId; } break; case AJ_HDR_HANDLES: case AJ_HDR_COMPRESSION_TOKEN: default: continue; } /* * Ignore empty fields. */ if (!hdrVal.val.v_data) { continue; } /* * Custom marshal the header field - signature is "(yv)" so starts off with STRUCT aligment. */ buf[0] = fieldId; buf[1] = 1; buf[2] = typeId; buf[3] = 0; WriteBytes(msg, buf, 4, PadForType(AJ_ARG_STRUCT, ioBuf)); /* * Now marshal the field value */ Marshal(msg, &fieldSig, &hdrVal); } if (status == AJ_OK) { /* * Write the header length */ msg->hdr->headerLen = (uint32_t)((ioBuf->writePtr - ioBuf->bufStart) - sizeof(AJ_MsgHeader)); /* * Header must be padded to an 8 byte boundary */ status = WritePad(msg, (8 - msg->hdr->headerLen) & 7); } return status; }