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 is called from the receive side with the sequence number of * the last packet received. */ void AJ_SerialTx_ReceivedSeq(uint8_t seq) { /* * If we think we have already acked this sequence number we don't adjust * the ack count. */ if (!SEQ_GT(currentTxAck, seq)) { currentTxAck = (seq + 1) & 0x7; } #ifdef ALWAYS_ACK AJ_SerialTX_EnqueueCtrl(NULL, 0, AJ_SERIAL_ACK); #else ++pendingAcks; /* * If there are no packets to send we are allowed to accumulate a * backlog of pending ACKs up to a maximum equal to the window size. * In any case we are required to send an ack within a timeout * period so if this is the first pending ack we need to prime a timer. */ if (pendingAcks == 1) { AJ_InitTimer(&ackTime); AJ_TimeAddOffset(&ackTime, AJ_SerialLinkParams.txAckTimeout); return; } /* * If we have hit our pending ACK limit send a explicit ACK packet immediately. */ if (pendingAcks == AJ_SerialLinkParams.windowSize) { AJ_SerialTX_EnqueueCtrl(NULL, 0, AJ_SERIAL_ACK); } #endif }
/* * 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; }
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); } }
static AJ_Status TimerStart(const uint8_t index) { g_timer_runs = TRUE; AJ_InitTimer(&g_aj_timer_time); AJTS_Server_Timer_RunStateChanged(&busAttachment, AJTS_TIMER_OBJECT_INDEX, TRUE); printf("TimerStart Called on index %d\n", index); return AJ_OK; }
/** * This function resets the transmit side of the transport. */ AJ_Status AJ_SerialTX_Reset(void) { TxPkt volatile* pkt; /* * Hold the timeouts. */ AJ_InitTimer(&resendTime); AJ_TimeAddOffset(&resendTime, AJ_TIMER_FOREVER); AJ_InitTimer(&ackTime); AJ_TimeAddOffset(&ackTime, AJ_TIMER_FOREVER); /* * Put ACL packets back on the free list. */ while (txSent != NULL) { pkt = txSent; txSent = txSent->next; if (pkt->type == AJ_SERIAL_DATA) { pkt->next = txFreeList; txFreeList = pkt; } } while (txQueue != NULL) { pkt = txQueue; txQueue = txQueue->next; if (pkt->type == AJ_SERIAL_DATA) { pkt->next = txFreeList; txFreeList = pkt; } } /* * Re-initialize global state. */ txSeqNum = 0; pendingAcks = 0; currentTxAck = 0; txSeqNum = 0; resendPrimed = FALSE; return AJ_OK; }
/** * This function is called by the receive layer when a data packet or an explicit ACK * has been received. The ACK value is one greater (modulo 8) than the seq number of the * last packet successfully received. */ void AJ_SerialTx_ReceivedAck(uint8_t ack) { TxPkt volatile* ackedPkt = NULL; if (txSent == NULL) { return; } /* * Remove acknowledged packets from sent queue. */ while ((txSent != NULL) && SEQ_GT(ack, txSent->seq)) { ackedPkt = txSent; txSent = txSent->next; //AJ_AlwaysPrintf("Releasing seq=%d (acked by %d)\n", ackedPkt->seq, ack); AJ_ASSERT(ackedPkt->type == AJ_SERIAL_DATA); /* * Return pkt to ACL free list. */ ackedPkt->next = txFreeList; txFreeList = ackedPkt; /* * If all packet have been ack'd, halt the resend timer and return. */ if (txSent == NULL) { AJ_InitTimer(&resendTime); AJ_TimeAddOffset(&resendTime, AJ_TIMER_FOREVER); resendPrimed = FALSE; return; } } /* * Reset the resend timer if one or more packets were ack'd. */ if (ackedPkt != NULL) { AJ_InitTimer(&resendTime); AJ_TimeAddOffset(&resendTime, AJ_SerialLinkParams.txResendTimeout); resendPrimed = TRUE; } }
static void AJ_GlobalTimerInit(void) { sigev.sigev_notify = SIGEV_THREAD; sigev.sigev_notify_function = &AJ_GlobalTimerHandler; // int create; timer_create(CLOCK_MONOTONIC, &sigev, &globalTimer); // AJ_DebugTimerPrintf("global timer create returned %d id is 0x%lX\n", create, (long)globalTimer); AJ_InitTimer(&globalClock); }
/* * Send a explicit ACK (acknowledgement). */ void SendAck() { if (pendingAcks) { pendingAcks = 0; AJ_SerialTX_EnqueueCtrl(NULL, 0, AJ_SERIAL_ACK); } /* * Disable explicit ack. */ AJ_InitTimer(&ackTime); AJ_TimeAddOffset(&ackTime, AJ_TIMER_FOREVER); }
static AJ_Status SetDateTime(const uint8_t index, const TS_Date* date, const TS_Time* time, const int16_t* utcOffset) { AJ_InitTimer(&g_aj_time); memcpy(&g_ts_date, date, sizeof(TS_Date)); memcpy(&g_ts_time, time, sizeof(TS_Time)); g_utcOffset = *utcOffset; g_isSet = TRUE; printf("SetDateTime Called on index %d\n", index); return AJ_OK; }
AJ_Status AJOBS_ControllerAPI_DoScanInfo() { AJ_Status status = AJ_OK; memset(obScanInfos, 0, sizeof(obScanInfos)); obScanInfoCount = 0; // Scan neighbouring networks and save info -> Call OBM_WiFiScanResult(). status = AJ_WiFiScan(NULL, WiFiScanResult, AJOBS_MAX_SCAN_INFOS); if (status == AJ_OK) { AJ_InitTimer(&obLastScan); } return status; }
AJ_Timer* AJ_TimerInit(uint32_t timeout, AJ_TimerCallback timerCallback, void* context, uint32_t timerId) { AJ_Timer* timer; timer = (AJ_Timer*) AJ_Malloc(sizeof(AJ_Timer)); timer->id = timerId; timer->next = NULL; timer->callback = timerCallback; timer->context = context; AJ_InitTimer(&(timer->timeNextRaised)); AJ_TimeAddOffset(&(timer->timeNextRaised), timeout); return timer; }
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; }
AJ_Status AJS_TargetIO_PinEnableTrigger(void* pinCtx, int pinFunction, AJS_IO_PinTriggerCondition condition, int32_t* trigId, uint8_t debounce) { int i; AJ_Status status; GPIO* gpio = (GPIO*)pinCtx; const char* dev = pinInfo[gpio->pinId].gpioDev; const char* val; InitTriggerThread(); if (condition == AJS_IO_PIN_TRIGGER_ON_RISE) { val = "rising"; } else if (condition == AJS_IO_PIN_TRIGGER_ON_FALL) { val = "falling"; } else { val = "both"; } status = SetDeviceProp(dev, gpio_root, "edge", val); if (status == AJ_OK) { pthread_mutex_lock(&mutex); for (i = 0; i < MAX_TRIGGERS; ++i) { if (!triggers[i]) { triggers[i] = gpio; gpio->trigId = i; break; } } gpio->debounceMillis = debounce; AJ_InitTimer(&gpio->timer); pthread_mutex_unlock(&mutex); if (i == MAX_TRIGGERS) { (void)SetDeviceProp(dev, gpio_root, "edge", "node"); status = AJ_ERR_RESOURCES; } *trigId = gpio->trigId; } if (status == AJ_OK) { /* * Let the trigger thread know there has been a change */ ResetTriggerThread(); AJ_InfoPrintf(("AJS_TargetIO_PinEnableTrigger pinId %d\n", gpio->pinId)); } return status; }
/** * This function is called if an acknowledgement is not received within the required * timeout period. */ void ResendPackets() { TxPkt volatile* last; /* * Re-register the send timeout callback, it will not be primed until it * is needed. */ resendPrimed = FALSE; AJ_InitTimer(&resendTime); AJ_TimeAddOffset(&resendTime, AJ_TIMER_FOREVER); /* * No resends if the link is not up. */ if (AJ_SerialLinkParams.linkState != AJ_LINK_ACTIVE) { return; } /* * To preserve packet order, all unacknowleged packets must be resent. This * simply means moving packets on txSent to the head of txQueue. */ if (txSent != NULL) { last = txSent; while (last->next != NULL) { last = last->next; } /* * Put resend packets after the unreliable packet. */ if (txQueue == txUnreliable) { last->next = txQueue->next; txQueue->next = last; } else { last->next = txQueue; txQueue = txSent; } txSent = NULL; } }
AJ_Status AJ_TimerRefresh(uint32_t timerId, uint32_t timeout) { AJ_DebugTimerPrintf("AJ_TimerRefresh id 0x%lx timeout %ld\n", timerId, timeout); // BUGBUG take a lock AJ_Timer* iter = NULL; iter = AJ_TimerRemoveFromList(&TimerList, timerId); if (!iter) { iter = AJ_TimerRemoveFromList(&InactiveTimerList, timerId); } if (iter) { // set the trigger time to now + timeout. AJ_InitTimer(&(iter->timeNextRaised)); AJ_TimeAddOffset(&(iter->timeNextRaised), timeout); // move a timer from the active to the inactive list. AJ_TimerInsertInList(&TimerList, iter); } if (!iter) { // look on the inactive list and insert it into the active list AJ_Printf("ERROR! refreshing a non existant timer %u!\n", timerId); } if (TimerList) { // restart the global timer, in case we were stopped. AJ_GlobalTimerStart(); } // BUGBUG release a lock AJ_DebugCheckTimerList(TimerList); return AJ_OK; }
static void AJ_GlobalTimerHandler(sigval_t value) { if (!TimerList) { AJ_GlobalTimerStop(); AJ_Printf("turn off alarm, there is no timer\n"); } else { AJ_Time now; AJ_InitTimer(&now); AJ_Timer* top = TimerList; // if tops time < now, then run the callback... if (AJ_CompareTime(top->timeNextRaised, now) < 1) { TimerList = top->next; // move to the top of the inactive timer list, semi-MRU top->next = InactiveTimerList; InactiveTimerList = top; (top->callback)(top->id, top->context); } else { // AJ_Printf("AJ_GlobalTimerHandler without something to do yet.\n"); } } }
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; }
/* * 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; }
// TODO: deprecate this function; replace it with AJ_FindBusAndConnect AJ_Status AJ_Connect(AJ_BusAttachment* bus, const char* serviceName, uint32_t timeout) { AJ_Status status; AJ_Service service; bus->isAuthenticated = FALSE; #ifdef AJ_SERIAL_CONNECTION AJ_Time start, now; AJ_InitTimer(&start); #endif AJ_InfoPrintf(("AJ_Connect(bus=0x%p, serviceName=\"%s\", timeout=%d, selectionTimeout=%d.)\n", bus, serviceName, timeout, selectionTimeout)); /* * Clear the bus struct */ memset(bus, 0, sizeof(AJ_BusAttachment)); /* * Clear stale name->GUID mappings */ AJ_GUID_ClearNameMap(); #if !(defined(ARDUINO) || defined(__linux) || defined(_WIN32) || defined(__MACH__)) /* * Get an IP address. We don't want to break this older version * of AJ_Connect, so acquire an IP if we don't already have one. * * This does not work on non-embedded platforms! */ { uint32_t ip, mask, gw; status = AJ_AcquireIPAddress(&ip, &mask, &gw, AJ_DHCP_TIMEOUT); if (status != AJ_OK) { AJ_ErrPrintf(("AJ_Net_Up(): AJ_AcquireIPAddress Failed\n")); } } #endif /* * Discover a daemon or service to connect to */ if (!serviceName) { serviceName = daemonService; } #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; status = AJ_Discover(serviceName, &service, timeout, selectionTimeout); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): 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 // in a way that depends on the target status = AJ_Serial_Up(); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): AJ_Serial_Up status=%s\n", AJ_StatusText(status))); } #else status = AJ_Discover(serviceName, &service, timeout, selectionTimeout); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): AJ_Discover status=%s\n", AJ_StatusText(status))); goto ExitConnect; } #endif status = AJ_Net_Connect(bus, &service); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): 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(("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_Connect(): AJ_Authenticate status=%s\n", AJ_StatusText(status))); goto ExitConnect; } status = SetSignalRules(bus); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): SetSignalRules status=%s\n", AJ_StatusText(status))); goto ExitConnect; } ExitConnect: if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): status=%s\n", AJ_StatusText(status))); AJ_Disconnect(bus); } AJ_InitRoutingNodeResponselist(); return status; }
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; }
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_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; }
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_FindBusAndConnect(AJ_BusAttachment* bus, const char* serviceName, uint32_t timeout) { AJ_Status status; AJ_Service service; #ifdef AJ_SERIAL_CONNECTION AJ_Time start, now; AJ_InitTimer(&start); #endif AJ_InfoPrintf(("AJ_Connect(bus=0x%p, serviceName=\"%s\", timeout=%d.)\n", bus, serviceName, timeout)); /* * 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; } #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_IPV4; #elif defined ARDUINO service.ipv4port = 9955; service.ipv4 = 0x6501A8C0; // 192.168.1.101 service.addrTypes = AJ_ADDR_IPV4; status = AJ_Discover(serviceName, &service, timeout); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): 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_Connect(): AJ_Serial_Up status=%s\n", AJ_StatusText(status))); } #else status = AJ_Discover(serviceName, &service, timeout); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): AJ_Discover status=%s\n", AJ_StatusText(status))); goto ExitConnect; } #endif status = AJ_Net_Connect(&bus->sock, service.ipv4port, service.addrTypes & AJ_ADDR_IPV4, &service.ipv4); if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): 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(("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_Connect(): AJ_Authenticate status=%s\n", AJ_StatusText(status))); goto ExitConnect; } // 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); ExitConnect: if (status != AJ_OK) { AJ_InfoPrintf(("AJ_Connect(): status=%s\n", AJ_StatusText(status))); AJ_Disconnect(bus); } return status; }
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_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; }
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; }