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;
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
/*
 * 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
}
Esempio n. 4
0
/*
 * 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;
}
Esempio n. 5
0
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);								 										
	}
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
/**
 * 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;
}
Esempio n. 8
0
/**
 * 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;
    }
}
Esempio n. 9
0
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);
}
Esempio n. 10
0
/*
 * 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);
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
/**
 * 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;
    }
}
Esempio n. 17
0
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;
}
Esempio n. 18
0
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");
        }
    }

}
Esempio n. 19
0
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;
}
Esempio n. 20
0
/*
 * 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;
}
Esempio n. 21
0
// 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;
}
Esempio n. 22
0
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;
}
Esempio n. 23
0
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;
}
Esempio n. 24
0
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;
}
Esempio n. 25
0
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;
}
Esempio n. 26
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;
}
Esempio n. 27
0
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;
}
Esempio n. 28
0
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(&currentContext, sizeof(currentContext));

        uint8_t currentMaxAps = 0;
        AJ_RandBytes(&currentMaxAps, 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(&current_ip_address, &current_subnet_mask, &current_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);
    }
}
Esempio n. 29
0
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;
}
Esempio n. 30
0
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;
}