2 *******************************************************************
4 * Copyright 2016 Samsung Electronics All Rights Reserved.
6 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 package org.iotivity.cloud.base.protocols.coap;
24 import java.util.List;
26 import io.netty.buffer.ByteBuf;
27 import io.netty.buffer.Unpooled;
28 import io.netty.channel.ChannelHandlerContext;
29 import io.netty.handler.codec.MessageToByteEncoder;
31 public class CoapEncoder extends MessageToByteEncoder<CoapMessage> {
34 protected void encode(ChannelHandlerContext ctx, CoapMessage msg,
35 ByteBuf out) throws Exception {
37 CoapMessage coapMessage = (CoapMessage) msg;
39 ByteBuf optBuf = Unpooled.directBuffer();
44 encodeOptions(optBuf, coapMessage);
45 long length = optBuf.readableBytes();
47 if (coapMessage.getPayloadSize() > 0) {
48 // + 1 means 8bits delimiter
49 length += 1 + coapMessage.getPayloadSize();
52 calcShimHeader(coapMessage, out, length);
54 out.writeByte(coapMessage.getCode());
56 if (coapMessage.getTokenLength() > 0) {
57 out.writeBytes(coapMessage.getToken());
61 if (optBuf.readableBytes() > 0) {
62 out.writeBytes(optBuf);
67 if (coapMessage.getPayloadSize() > 0) {
69 out.writeBytes(coapMessage.getPayload());
73 private void calcShimHeader(CoapMessage coapMessage, ByteBuf byteBuf,
76 byteBuf.writeByte(((int) length & 0x0F) << 4
77 | (coapMessage.getTokenLength() & 0x0F));
78 } else if (length < 269) {
79 byteBuf.writeShort((13 & 0x0F) << 12
80 | (coapMessage.getTokenLength() & 0x0F) << 8
81 | (((int) length - 13) & 0xFF));
82 } else if (length < 65805) {
84 (14 & 0x0F) << 4 | (coapMessage.getTokenLength() & 0x0F));
85 byteBuf.writeShort(((int) length - 269) & 0xFFFF);
86 } else if (length < Integer.MAX_VALUE * 2) {
88 (15 & 0x0F) << 4 | (coapMessage.getTokenLength() & 0x0F));
89 byteBuf.writeLong((length - 65805) & 0xFFFFFFFF);
91 throw new IllegalArgumentException(
92 "Length must be less than 4GB " + length);
96 private void encodeOptions(ByteBuf byteBuf, CoapMessage coapMessage)
100 for (int i = 0; i < 40; i++) {
101 List<byte[]> values = coapMessage.getOption(i);
102 if (values != null) {
103 for (byte[] value : values) {
104 writeOption(i - preOptionNum,
105 value != null ? value.length : 0, byteBuf, value);
112 private void writeOption(int optionDelta, int optionLength, ByteBuf byteBuf,
115 if (optionDelta < 13) {
116 if (optionLength < 13) {
118 ((optionDelta & 0xFF) << 4) | (optionLength & 0xFF));
119 } else if (optionLength < 269) {
120 byteBuf.writeByte(((optionDelta << 4) & 0xFF) | (13 & 0xFF));
121 byteBuf.writeByte((optionLength - 13) & 0xFF);
123 byteBuf.writeByte(((optionDelta << 4) & 0xFF) | (14 & 0xFF));
124 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
125 byteBuf.writeByte((optionLength - 269) & 0xFF);
129 else if (optionDelta < 269) {
130 if (optionLength < 13) {
131 byteBuf.writeByte(((13 & 0xFF) << 4) | (optionLength & 0xFF));
132 byteBuf.writeByte((optionDelta - 13) & 0xFF);
133 } else if (optionLength < 269) {
134 byteBuf.writeByte(((13 & 0xFF) << 4) | (13 & 0xFF));
135 byteBuf.writeByte((optionDelta - 13) & 0xFF);
136 byteBuf.writeByte((optionLength - 13) & 0xFF);
138 byteBuf.writeByte((13 & 0xFF) << 4 | (14 & 0xFF));
139 byteBuf.writeByte((optionDelta - 13) & 0xFF);
140 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
141 byteBuf.writeByte((optionLength - 269) & 0xFF);
145 else if (optionDelta < 65805) {
147 if (optionLength < 13) {
148 byteBuf.writeByte(((14 & 0xFF) << 4) | (optionLength & 0xFF));
149 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
150 byteBuf.writeByte((optionDelta - 269) & 0xFF);
153 else if (optionLength < 269) {
154 byteBuf.writeByte(((14 & 0xFF) << 4) | (13 & 0xFF));
155 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
156 byteBuf.writeByte((optionDelta - 269) & 0xFF);
157 byteBuf.writeByte((optionLength - 13) & 0xFF);
161 byteBuf.writeByte(((14 & 0xFF) << 4) | (14 & 0xFF));
162 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
163 byteBuf.writeByte((optionDelta - 269) & 0xFF);
164 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
165 byteBuf.writeByte((optionLength - 269) & 0xFF);
168 throw new IllegalArgumentException(
169 "Unsupported option delta " + optionDelta);
172 if (optionLength > 0) {
173 byteBuf.writeBytes(value);