Object * Object::Parse(Context * ctx){ Object * ret = NULL; Header hdr; hdr.Read(ctx); if(hdr.GetFlag() == FLAG_ARRAY){ NativeType type = hdr.GetType(); if(type!=0){ int64_t count = hdr.GetLength() / Native::SizeForNative(type); Array * array = Array::WithType(type,(uint32_t)count); dynamic_cast<Object*>(array)->Read(hdr, ctx); ret = array; }else{ Array * array = Array::WithCapacity(); dynamic_cast<Object*>(array)->Read(hdr, ctx); ret = array; } }else if(hdr.GetFlag() == FLAG_MAP){ Map * obj = new Map(); dynamic_cast<Object*>(obj)->Read(hdr, ctx); ret = obj; }else if(hdr.GetFlag() == FLAG_OBJECT){ Native * obj = new Native(); dynamic_cast<Object*>(obj)->Read(hdr, ctx); ret = obj; } return ret; }
void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Header header; char uriPath[kMaxReceivedUriPath]; char *curUriPath = uriPath; const Header::Option *coapOption; SuccessOrExit(header.FromMessage(aMessage)); aMessage.MoveOffset(header.GetLength()); coapOption = header.GetCurrentOption(); while (coapOption != NULL) { switch (coapOption->mNumber) { case kCoapOptionUriPath: VerifyOrExit(coapOption->mLength < sizeof(uriPath) - static_cast<size_t>(curUriPath - uriPath), ;); memcpy(curUriPath, coapOption->mValue, coapOption->mLength); curUriPath[coapOption->mLength] = '/'; curUriPath += coapOption->mLength + 1; break; case kCoapOptionContentFormat: break; default: ExitNow(); } coapOption = header.GetNextOption(); }
ThreadError Client::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, otCoapResponseHandler aHandler, void *aContext) { ThreadError error; Header header; RequestMetadata requestMetadata; Message *storedCopy = NULL; uint16_t copyLength = 0; SuccessOrExit(error = header.FromMessage(aMessage)); // Set Message Id if it was not already set. if (header.GetMessageId() == 0) { header.SetMessageId(mMessageId++); aMessage.Write(0, Header::kMinHeaderLength, header.GetBytes()); } if (header.IsConfirmable()) { // Create a copy of entire message and enqueue it. copyLength = aMessage.GetLength(); } else if (header.IsNonConfirmable() && header.IsRequest() && (aHandler != NULL)) { // As we do not retransmit non confirmable messages, create a copy of header only, for token information. copyLength = header.GetLength(); } if (copyLength > 0) { requestMetadata = RequestMetadata(header.IsConfirmable(), aMessageInfo, aHandler, aContext); VerifyOrExit((storedCopy = CopyAndEnqueueMessage(aMessage, copyLength, requestMetadata)) != NULL, error = kThreadError_NoBufs); } SuccessOrExit(error = mSocket.SendTo(aMessage, aMessageInfo)); exit: if (error != kThreadError_None && storedCopy != NULL) { DequeueMessage(*storedCopy); } return error; }
void Client::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Header responseHeader; Header requestHeader; RequestMetadata requestMetadata; Message *message = NULL; ThreadError error; SuccessOrExit(error = responseHeader.FromMessage(aMessage)); aMessage.MoveOffset(responseHeader.GetLength()); message = FindRelatedRequest(responseHeader, aMessageInfo, requestHeader, requestMetadata); if (message == NULL) { ExitNow(); } switch (responseHeader.GetType()) { case kCoapTypeReset: if (responseHeader.IsEmpty()) { FinalizeCoapTransaction(*message, requestMetadata, NULL, NULL, kThreadError_Abort); } // Silently ignore non-empty reset messages (RFC 7252, p. 4.2). break; case kCoapTypeAcknowledgment: if (responseHeader.IsEmpty()) { // Empty acknowledgment. if (requestMetadata.mConfirmable) { requestMetadata.mAcknowledged = true; requestMetadata.UpdateIn(*message); } // Remove the message if response is not expected, otherwise await response. if (requestMetadata.mResponseHandler == NULL) { DequeueMessage(*message); } } else if (responseHeader.IsResponse() && responseHeader.IsTokenEqual(requestHeader)) { // Piggybacked response. FinalizeCoapTransaction(*message, requestMetadata, &responseHeader, &aMessage, kThreadError_None); } // Silently ignore acknowledgments carrying requests (RFC 7252, p. 4.2) // or with no token match (RFC 7252, p. 5.3.2) break; case kCoapTypeConfirmable: case kCoapTypeNonConfirmable: if (responseHeader.IsConfirmable()) { // Send empty ACK if it is a CON message. SendEmptyAck(aMessageInfo.GetPeerAddr(), aMessageInfo.mPeerPort, responseHeader.GetMessageId()); } FinalizeCoapTransaction(*message, requestMetadata, &responseHeader, &aMessage, kThreadError_None); break; } exit: if (error == kThreadError_None && message == NULL) { if (responseHeader.IsConfirmable() || responseHeader.IsNonConfirmable()) { // Successfully parsed a header but no matching request was found - reject the message by sending reset. SendReset(aMessageInfo.GetPeerAddr(), aMessageInfo.mPeerPort, responseHeader.GetMessageId()); } } }