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; }
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; }
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; }
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; }