Пример #1
0
void handleDataMessage(MQTT::MessageData& md) {

    TEMBOO_TRACE("data: ");

    MQTT::Message& msg = md.message;

    char* c;
    unsigned int count;
    for (c = (char*)msg.payload, count = 0; *c != '\0' && isdigit(*c) && count < msg.payloadlen; c++) {
        count++;
        if (count > 5) {
            TEMBOO_TRACELN(" long");
            return;
        }
    }

    if (count == 0) {
        TEMBOO_TRACELN(" short");
        return;
    }

    if (TAG_VALUE_SEPARATOR != *c) {
        TEMBOO_TRACELN(" bad msg");
        return;
    }

    // Replace the : with \0 so we can use strtoul.
    *c = '\0';

    unsigned long requestId = strtoul((char*)msg.payload, NULL, 10);
    if (UINT16_MAX < requestId) {
        TEMBOO_TRACELN(" bad id");
        return;
    }

    if ((NULL == g_currentChoreo) || (g_currentChoreo->getRequestId() != (uint16_t)requestId)) {
        TEMBOO_TRACE(" stale id: ");
        TEMBOO_TRACELN(requestId);
        return;
    }

    g_currentChoreo->setResponseData(c + 1, msg.payloadlen - strlen((char*)msg.payload) - 1);
    TEMBOO_TRACELN(" ok");

}
Пример #2
0
void handleTimeMessage(MQTT::MessageData& md) {
    
    TEMBOO_TRACE("time: ");

    MQTT::Message& msg = md.message;
    
    // Time messages should be <= 10 characters long.
    if (msg.payloadlen > 10) {
        TEMBOO_TRACELN("long");
        return;
    }

    if (msg.payloadlen == 0) {
        TEMBOO_TRACELN("short");
        return;
    }

    // Payload should consist only of digits (0 - 9)
    for (unsigned int i = 0; i < msg.payloadlen; i++) {
        if (! isdigit(((char*)msg.payload)[i])) {
            TEMBOO_TRACELN("!digit");
            return;
        }
    }

    char timeStr[11];
    memcpy(timeStr, msg.payload, msg.payloadlen);
    timeStr[msg.payloadlen] = '\0';

    TEMBOO_TRACE(timeStr);

    uint32_t t = strtoul(timeStr, NULL, 10);
    TembooMQTTSession::setTime(t);

    TEMBOO_TRACELN(" ok");
}
Пример #3
0
int TembooSession::executeChoreo(
        const char* accountName, 
        const char* appKeyName, 
        const char* appKeyValue, 
        const char* path, 
        const ChoreoInputSet& inputSet, 
        const ChoreoOutputSet& outputSet, 
        const ChoreoPreset& preset) {

    DataFormatter fmt(&inputSet, &outputSet, &preset);
    char auth[HMAC_HEX_SIZE_BYTES + 1];
    char buffer[11];
    
    // We use the current time-of-day as salt on the app key.
    // We keep track of time-of-day by getting the current time
    // from the server and applying an offset (the length of time
    // we've been running.) 
    uint32toa((uint32_t)TembooSession::getTime(), buffer);

    uint16_t contentLength = getAuth(fmt, appKeyValue, buffer, auth);

    m_client.stop();
    m_client.flush();

    int connected = 0;
    TEMBOO_TRACE("Connecting: ");

    // reserve space for the "host" string sufficient to hold either the 
    // (dotted-quad) IP address + port, or the default <account>.temboolive.com
    // host string.
    int hostLen = (m_addr == INADDR_NONE ? (strlen_P(TEMBOO_DOMAIN) + strlen(accountName) + 1):21);
    char host[hostLen];

    // If no explicit IP address was specified (the normal case), construct
    // the "host" string from the account name and the temboo domain name.
    if (m_addr == INADDR_NONE) {
        strcpy(host, accountName);
        strcat_P(host, TEMBOO_DOMAIN);
        TEMBOO_TRACELN(host);
        connected = m_client.connect(host, m_port);
    } else {

        // If an IP address was explicitly specified (presumably for testing purposes),
        // convert it to a dotted-quad text string.
        host[0] = '\0';
        for(int i = 0; i < 4; i++) {
            uint16toa(m_addr[i], &host[strlen(host)]);
            strcat(host, ".");
        }

        // replace the last '.' with ':'
        host[strlen(host)-1] = ':';
        
        // append the port number
        uint16toa(m_port, &host[strlen(host)]);
        
        TEMBOO_TRACELN(host);
        connected = m_client.connect(m_addr, m_port);
    }

    if (connected) {

        TEMBOO_TRACELN("OK. req:");
        qsendProgmem(POST);
        qsendProgmem(BASE_CHOREO_URI);
        qsend(path);
        qsendProgmem(SDK_ID);
        qsendlnProgmem(POSTAMBLE);
        
        // Send our custom authentication header
        // (app-key-name:hmac)
        qsendProgmem(HEADER_AUTH);
        qsend(appKeyName);
        qsend(":");
        qsendln(auth);
        
        // send the standard host header
        qsendProgmem(HEADER_HOST);
        qsendln(host);
        
        // send the standard accept header
        qsendlnProgmem(HEADER_ACCEPT);
        
        // send our custom account name neader
        qsendProgmem(HEADER_ORG);
        qsend(accountName);
        qsendlnProgmem(HEADER_DOM);
        
        // send the standard content type header
        qsendlnProgmem(HEADER_CONTENT_TYPE);
        
        // send our custom client time header
        qsendProgmem(HEADER_TIME);
        qsendln(buffer);
        
        // send the standard content length header
        qsendProgmem(HEADER_CONTENT_LENGTH);
        qsendln(uint16toa(contentLength, buffer));

        qsendProgmem(EOL);
        
        // Format and send the body of the request
        fmt.reset();
        while(fmt.hasNext()) {
            qsend(fmt.next());
        }

        qsendProgmem(EOL);
        qflush();
        return 0;
    } else {
        TEMBOO_TRACELN("FAIL");
        return 1;
    }
}
Пример #4
0
void handleAckMessage(MQTT::MessageData& md) {
    
    TEMBOO_TRACE("ack: ");

    MQTT::Message& msg = md.message;
    
    // Expected max length is 11 (for 65535:65535)
    if (msg.payloadlen > 11) {
        TEMBOO_TRACELN("long");
        return;
    }

    if (msg.payloadlen == 0) {
        TEMBOO_TRACELN("short");
        return;
    }

    // Copy the payload and nul terminate it;
    char ackStr[12]; 
    memcpy(ackStr, msg.payload, msg.payloadlen);
    ackStr[msg.payloadlen] = '\0';

    TEMBOO_TRACE(ackStr);
    
    if (!validateUint16PairMessage(ackStr)) {
        TEMBOO_TRACELN(" bad msg");
        return;
    }
    
    char* next;
    unsigned long ackCode = TEMBOO_ERROR_FAILURE;
    unsigned long requestId = strtoul(ackStr, &next, 10);
    
    // validate only checks that the request ID 
    // has at least 1 but no more than 6 digits.
    // so we have to check the actual value here.
    if (UINT16_MAX < requestId) {
        TEMBOO_TRACELN(" bad id");
        return;
    }

    // If the request ID in the message doesn't match the
    // current request ID, then it's a stale ack.
    if ((NULL == g_currentChoreo) || (g_currentChoreo->getRequestId() != (uint16_t)requestId)) {
        TEMBOO_TRACE(" stale id: ");
        TEMBOO_TRACELN(ackStr);
        return;
    }

    next++;
    ackCode = strtoul(next, NULL, 10);

    // Validate only checks that the ack code
    // has at least 1 but no more than 6 digits,
    // so we have to check the actual value here.
    if (UINT16_MAX < ackCode) {
        TEMBOO_TRACELN(" bad code");
        return;
    }

    // FINALLY, everything's OK. 
    // pass the value to the waiting choreo.
    g_currentChoreo->setAckCode(ackCode);
    TEMBOO_TRACELN(" ok");

}
Пример #5
0
int TembooSession::executeChoreo(
        const char* accountName, 
        const char* appKeyName, 
        const char* appKeyValue, 
        const char* path, 
        const ChoreoInputSet& inputSet, 
        const ChoreoOutputSet& outputSet, 
        const ChoreoPreset& preset) {

    DataFormatter fmt(&inputSet, &outputSet, &preset);
    char auth[HMAC_HEX_SIZE_BYTES + 1];
    char buffer[11];
    
    // We use the current time-of-day as salt on the app key.
    // We keep track of time-of-day by getting the current time
    // from the server and applying an offset (the length of time
    // we've been running.) 
    uint32toa((uint32_t)TembooSession::getTime(), buffer);

    uint16_t contentLength = getAuth(fmt, appKeyValue, buffer, auth);

    m_client.stop();
    m_client.flush();

    int connected = 0;
    TEMBOO_TRACE("Connecting: ");

    // reserve space for the "host" string sufficient to hold either the 
    // (dotted-quad) IP address + port, or the default <account>.temboolive.com
    // host string.
    int hostLen = strlen_P(TEMBOO_DOMAIN) + strlen(accountName) + 1;
    char host[hostLen];
    
    // Construct the "host" string from the account name and the temboo domain name.

    strcpy(host, accountName);
    strcat_P(host, TEMBOO_DOMAIN);
    
    bool useProxy = false;
    
    if (m_addr == INADDR_NONE) {
        TEMBOO_TRACELN(host);
        connected = m_client.connect(host, m_port);
    } else {
        
        TEMBOO_TRACELN(host);
        connected = m_client.connect(m_addr, m_port);
        
        useProxy = true;
    }

    if (connected) {

        TEMBOO_TRACELN("OK. req:");
        qsendProgmem(POST);
        if(useProxy) {
            qsendProgmem(HTTP);
            qsend(host);
        }
        qsendProgmem(BASE_CHOREO_URI);
        qsend(path);
        qsendProgmem(SDK_ID);
        qsendlnProgmem(POSTAMBLE);
        
        // Send our custom authentication header
        // (app-key-name:hmac)
        qsendProgmem(HEADER_AUTH);
        qsend(appKeyName);
        qsend(":");
        qsendln(auth);
        
        // send the standard host header
        qsendProgmem(HEADER_HOST);
        qsendln(host);
        
        // send the standard accept header
        qsendlnProgmem(HEADER_ACCEPT);
        
        // send our custom account name neader
        qsendProgmem(HEADER_ORG);
        qsend(accountName);
        qsendlnProgmem(HEADER_DOM);
        
        // send the standard content type header
        qsendlnProgmem(HEADER_CONTENT_TYPE);
        
        // send our custom client time header
        qsendProgmem(HEADER_TIME);
        qsendln(buffer);
        
        // send the standard content length header
        qsendProgmem(HEADER_CONTENT_LENGTH);
        qsendln(uint16toa(contentLength, buffer));

        qsendProgmem(EOL);
        
        // Format and send the body of the request
        fmt.reset();
        while(fmt.hasNext()) {
            qsend(fmt.next());
        }

        qsendProgmem(EOL);
        qflush();
        return 0;
    } else {
        TEMBOO_TRACELN("FAIL");
        return 1;
    }
}