示例#1
0
文件: aj_msg.c 项目: reignme/ajtcl
AJ_Status AJ_DeliverMsg(AJ_Message* msg)
{
    AJ_Status status = AJ_OK;
    AJ_IOBuffer* ioBuf = &msg->bus->sock.tx;

    /*
     * If the header has already been marshaled (due to partial delivery) it will be NULL
     */
    if (msg->hdr) {
        /*
         * Write the final body length to the header
         */
        msg->hdr->bodyLen = msg->bodyBytes;
        AJ_DumpMsg("SENDING", msg, TRUE);
        if (msg->hdr->flags & AJ_FLAG_ENCRYPTED) {
            status = EncryptMessage(msg);
        }
    } else {
        /*
         * Check that the entire body was written
         */
        if (msg->bodyBytes) {
            status = AJ_ERR_MARSHAL;
        }
    }
    if (status == AJ_OK) {
        //#pragma calls = AJ_Net_Send
        status = ioBuf->send(ioBuf);
    }
    memset(msg, 0, sizeof(AJ_Message));
    return status;
}
示例#2
0
文件: aj_msg.c 项目: reignme/ajtcl
AJ_Status AJ_DeliverMsgPartial(AJ_Message* msg, uint32_t bytesRemaining)
{
    AJ_IOBuffer* ioBuf = &msg->bus->sock.tx;
    uint8_t typeId = msg->signature[msg->sigOffset];
    size_t pad;

    AJ_ASSERT(!msg->outer);

    if (!msg->hdr || !bytesRemaining) {
        return AJ_ERR_UNEXPECTED;
    }
    /*
     * Partial delivery not currently supported for messages that must be encrypted.
     */
    if (msg->hdr->flags & AJ_FLAG_ENCRYPTED) {
        return AJ_ERR_SECURITY;
    }
    /*
     * There must be arguments to marshal
     */
    if (!typeId) {
        return AJ_ERR_SIGNATURE;
    }
    /*
     * Pad to the start of the argument.
     */
    pad = PadForType(typeId, ioBuf);
    if (pad) {
        AJ_Status status = WritePad(msg, pad);
        if (status != AJ_OK) {
            return status;
        }
    }
    /*
     * Set the body length in the header buffer.
     */
    msg->hdr->bodyLen = (uint32_t)(msg->bodyBytes + pad + bytesRemaining);
    AJ_DumpMsg("SENDING(partial)", msg, FALSE);
    /*
     * The buffer space occupied by the header is going to be overwritten
     * so the header is going to become invalid.
     */
    msg->hdr = NULL;
    /*
     * From now on we are going to count down the remaining body bytes
     */
    msg->bodyBytes = (uint32_t)bytesRemaining;
    /*
     * Standard signature matching is now meaningless
     */
    msg->signature = "";
    msg->sigOffset = 0;;

    return AJ_OK;
}
示例#3
0
LampResponseCode LAMP_UnmarshalState(LampStateContainer* state, AJ_Message* msg)
{
    AJ_Arg array1, struct1;
    AJ_Status status = AJ_UnmarshalContainer(msg, &array1, AJ_ARG_ARRAY);
    LampResponseCode responseCode = LAMP_OK;

    AJ_DumpMsg("LAMP_UnmarshalState", msg, TRUE);

    // initialize
    memset(state, 0, sizeof(LampStateContainer));

    do {
        char* field;
        char* sig;

        status = AJ_UnmarshalContainer(msg, &struct1, AJ_ARG_DICT_ENTRY);
        if (status != AJ_OK) 
		{
            break;
        }

        status = AJ_UnmarshalArgs(msg, "s", &field);
        if (status != AJ_OK) 
		{
            printf("AJ_UnmarshalArgs: %s\n", AJ_StatusText(status));
            return LAMP_ERR_MESSAGE;
        }

        // Process the field!
        status = AJ_UnmarshalVariant(msg, (const char**) &sig);
        if (status != AJ_OK) 
		{
            AJ_ErrPrintf(("AJ_UnmarshalVariant: %s\n", AJ_StatusText(status)));
            return LAMP_ERR_MESSAGE;
        }

        if (0 == strcmp(field, "OnOff")) 
		{
            uint32_t onoff;
            status = AJ_UnmarshalArgs(msg, "b", &onoff);
            state->state.onOff = onoff ? TRUE : FALSE;
            state->stateFieldIndicators |= LAMP_STATE_ON_OFF_FIELD_INDICATOR;
        } 
		else if (0 == strcmp(field, "Hue")) 
		{
            status = AJ_UnmarshalArgs(msg, "u", &state->state.hue);
            state->stateFieldIndicators |= LAMP_STATE_HUE_FIELD_INDICATOR;
        }
		else if (0 == strcmp(field, "Saturation"))
		{
            status = AJ_UnmarshalArgs(msg, "u", &state->state.saturation);
            state->stateFieldIndicators |= LAMP_STATE_SATURATION_FIELD_INDICATOR;
        } 
		else if (0 == strcmp(field, "ColorTemp")) 
		{
            status = AJ_UnmarshalArgs(msg, "u", &state->state.colorTemp);
            state->stateFieldIndicators |= LAMP_STATE_COLOR_TEMP_FIELD_INDICATOR;
        } 
		else if (0 == strcmp(field, "Brightness")) 
		{
            status = AJ_UnmarshalArgs(msg, "u", &state->state.brightness);
            state->stateFieldIndicators |= LAMP_STATE_BRIGHTNESS_FIELD_INDICATOR;
        } 
		else 
		{
            AJ_ErrPrintf(("Unknown field: %s\n", field));
            responseCode = LAMP_ERR_MESSAGE;
            AJ_SkipArg(msg);
        }

        status = AJ_UnmarshalCloseContainer(msg, &struct1);
        // if field invalid, throw the whole thing out and return the error
    } while (status == AJ_OK && responseCode == LAMP_OK);
    AJ_UnmarshalCloseContainer(msg, &array1);

    return responseCode;
}
示例#4
0
文件: aj_msg.c 项目: reignme/ajtcl
AJ_Status AJ_UnmarshalMsg(AJ_BusAttachment* bus, AJ_Message* msg, uint32_t timeout)
{
    AJ_Status status;
    AJ_IOBuffer* ioBuf = &bus->sock.rx;
    uint8_t* endOfHeader;
    uint32_t hdrPad;
    /*
     * Clear message then set the bus
     */
    memset(msg, 0, sizeof(AJ_Message));
    msg->msgId = AJ_INVALID_MSG_ID;
    msg->bus = bus;
    /*
     * Move any unconsumed data to the start of the I/O buffer
     */
    AJ_IOBufRebase(ioBuf);
    /*
     * Load the message header
     */
    while (AJ_IO_BUF_AVAIL(ioBuf) < sizeof(AJ_MsgHeader)) {
        //#pragma calls = AJ_Net_Recv
        status = ioBuf->recv(ioBuf, sizeof(AJ_MsgHeader) - AJ_IO_BUF_AVAIL(ioBuf), timeout);
        if (status != AJ_OK) {
            /*
             * If there were no messages to receive check if we have any methods call that have
             * timed-out and if so generate an internal error message to allow the application to
             * proceed.
             */
            if ((status == AJ_ERR_TIMEOUT) && AJ_TimedOutMethodCall(msg)) {
                msg->hdr = (AJ_MsgHeader*)&internalErrorHdr;
                msg->error = AJ_ErrTimeout;
                msg->sender = AJ_GetUniqueName(msg->bus);
                msg->destination = msg->sender;
                status = AJ_OK;
            }

            return status;
        }
    }
    /*
     * Header was unmarsalled directly into the rx buffer
     */
    msg->hdr = (AJ_MsgHeader*)ioBuf->bufStart;
    ioBuf->readPtr += sizeof(AJ_MsgHeader);
    /*
     * Quick sanity check on the header - unrecoverable error if this check fails
     */
    if ((msg->hdr->endianess != AJ_LITTLE_ENDIAN) && (msg->hdr->endianess != AJ_BIG_ENDIAN)) {
        return AJ_ERR_READ;
    }
    /*
     * Endian swap header info - conventiently they are contiguous in the header
     */
    EndianSwap(msg, AJ_ARG_INT32, &msg->hdr->bodyLen, 3);
    msg->bodyBytes = msg->hdr->bodyLen;
    /*
     * The header is null padded to an 8 bytes boundary
     */
    hdrPad = (8 - msg->hdr->headerLen) & 7;
    /*
     * Load the header
     */
    status = LoadBytes(ioBuf, msg->hdr->headerLen + hdrPad, 0);
    if (status != AJ_OK) {
        return status;
    }
#ifndef NDEBUG
    /*
     * Check that messages are getting closed
     */
    AJ_ASSERT(!currentMsg);
    currentMsg = msg;
#endif
    /*
     * Assume an empty signature
     */
    msg->signature = "";
    /*
     * We have the header in the buffer now we can unmarshal the header fields
     */
    endOfHeader = ioBuf->bufStart + sizeof(AJ_MsgHeader) + msg->hdr->headerLen;
    while (ioBuf->readPtr < endOfHeader) {
        const char* fieldSig;
        uint8_t fieldId;
        AJ_Arg hdrVal;
        /*
         * Custom unmarshal the header field - signature is "(yv)" so starts off with STRUCT aligment.
         */
        status = LoadBytes(ioBuf, 4, PadForType(AJ_ARG_STRUCT, ioBuf));
        if (status != AJ_OK) {
            break;
        }
        fieldId = ioBuf->readPtr[0];
        fieldSig = (const char*)&ioBuf->readPtr[2];
        ioBuf->readPtr += 4;
        /*
         * Now unmarshal the field value
         */
        status = Unmarshal(msg, &fieldSig, &hdrVal);
        if (status != AJ_OK) {
            break;
        }
        /*
         * Check the field has the type we expect - we ignore fields we don't know
         */
        if ((fieldId <= AJ_HDR_SESSION_ID) && (TypeForHdr[fieldId] != hdrVal.typeId)) {
            status = AJ_ERR_UNMARSHAL;
            break;
        }
        /*
         * Set the field value in the message
         */
        switch (fieldId) {
        case AJ_HDR_OBJ_PATH:
            msg->objPath = hdrVal.val.v_objPath;
            break;

        case AJ_HDR_INTERFACE:
            msg->iface = hdrVal.val.v_string;
            break;

        case AJ_HDR_MEMBER:
            msg->member = hdrVal.val.v_string;
            break;

        case AJ_HDR_ERROR_NAME:
            msg->error = hdrVal.val.v_string;
            break;

        case AJ_HDR_REPLY_SERIAL:
            msg->replySerial = *(hdrVal.val.v_uint32);
            break;

        case AJ_HDR_DESTINATION:
            msg->destination = hdrVal.val.v_string;
            break;

        case AJ_HDR_SENDER:
            msg->sender = hdrVal.val.v_string;
            break;

        case AJ_HDR_SIGNATURE:
            msg->signature = hdrVal.val.v_signature;
            break;

        case AJ_HDR_TIMESTAMP:
            msg->timestamp = *(hdrVal.val.v_uint32);
            break;

        case AJ_HDR_TIME_TO_LIVE:
            msg->ttl = *(hdrVal.val.v_uint32);
            break;

        case AJ_HDR_SESSION_ID:
            msg->sessionId = *(hdrVal.val.v_uint32);
            break;

        case AJ_HDR_HANDLES:
        case AJ_HDR_COMPRESSION_TOKEN:
        default:
            /* Ignored */
            break;
        }
    }
    if (status == AJ_OK) {
        AJ_ASSERT(ioBuf->readPtr == endOfHeader);
        /*
         * Consume the header pad bytes.
         */
        ioBuf->readPtr += hdrPad;
        /*
         * If the message is encrypted load the entire message body and decrypt it.
         */
        if (msg->hdr->flags & AJ_FLAG_ENCRYPTED) {
            status = LoadBytes(ioBuf, msg->hdr->bodyLen, 0);
            if (status == AJ_OK) {
                status = DecryptMessage(msg);
            }
        }
        /*
         * Toggle the AUTO_START flag so in the API no flags == 0
         *
         * Note we must do this after decrypting the message or message authentication will fail.
         */
        msg->hdr->flags ^= AJ_FLAG_AUTO_START;
        /*
         * If the message looks good try to identify it.
         */
        if (status == AJ_OK) {
            status = AJ_IdentifyMessage(msg);
        }
    } else {
        /*
         * Consume entire header
         */
        ioBuf->readPtr = endOfHeader + hdrPad;
    }
    if (status == AJ_OK) {
        AJ_DumpMsg("RECEIVED", msg, FALSE);
    } else {
        /*
         * Silently discard message unless in debug mode
         */
        AJ_ErrPrintf(("Discarding bad message %s\n", AJ_StatusText(status)));
        AJ_DumpMsg("DISCARDING", msg, FALSE);
        AJ_CloseMsg(msg);
    }

    return status;
}