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 public void encode(CoapMessage msg, ByteBuf out) throws Exception {
74 encode(null, msg, out);
77 private void calcShimHeader(CoapMessage coapMessage, ByteBuf byteBuf,
80 byteBuf.writeByte(((int) length & 0x0F) << 4
81 | (coapMessage.getTokenLength() & 0x0F));
82 } else if (length < 269) {
83 byteBuf.writeShort((13 & 0x0F) << 12
84 | (coapMessage.getTokenLength() & 0x0F) << 8
85 | (((int) length - 13) & 0xFF));
86 } else if (length < 65805) {
88 (14 & 0x0F) << 4 | (coapMessage.getTokenLength() & 0x0F));
89 byteBuf.writeShort(((int) length - 269) & 0xFFFF);
90 } else if (length < 4294967294L) {
92 (15 & 0x0F) << 4 | (coapMessage.getTokenLength() & 0x0F));
93 byte[] size = new byte[4];
94 long payload = length - 65805;
95 for (int i = 3; i > -1; i--) {
96 size[i] = (byte) (payload & 0xFF);
99 byteBuf.writeBytes(size);
101 throw new IllegalArgumentException(
102 "Length must be less than 4GB " + length);
106 private void encodeOptions(ByteBuf byteBuf, CoapMessage coapMessage)
108 int preOptionNum = 0;
110 for (int i = 0; i < 40; i++) {
111 List<byte[]> values = coapMessage.getOption(i);
112 if (values != null) {
113 if (values.size() > 0) {
114 for (byte[] value : values) {
115 writeOption(i - preOptionNum,
116 value != null ? value.length : 0, byteBuf,
122 writeOption(i - preOptionNum, 0, byteBuf, null);
129 private void writeOption(int optionDelta, int optionLength, ByteBuf byteBuf,
132 if (optionDelta < 13) {
133 if (optionLength < 13) {
135 ((optionDelta & 0xFF) << 4) | (optionLength & 0xFF));
136 } else if (optionLength < 269) {
137 byteBuf.writeByte(((optionDelta << 4) & 0xFF) | (13 & 0xFF));
138 byteBuf.writeByte((optionLength - 13) & 0xFF);
140 byteBuf.writeByte(((optionDelta << 4) & 0xFF) | (14 & 0xFF));
141 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
142 byteBuf.writeByte((optionLength - 269) & 0xFF);
146 else if (optionDelta < 269) {
147 if (optionLength < 13) {
148 byteBuf.writeByte(((13 & 0xFF) << 4) | (optionLength & 0xFF));
149 byteBuf.writeByte((optionDelta - 13) & 0xFF);
150 } else if (optionLength < 269) {
151 byteBuf.writeByte(((13 & 0xFF) << 4) | (13 & 0xFF));
152 byteBuf.writeByte((optionDelta - 13) & 0xFF);
153 byteBuf.writeByte((optionLength - 13) & 0xFF);
155 byteBuf.writeByte((13 & 0xFF) << 4 | (14 & 0xFF));
156 byteBuf.writeByte((optionDelta - 13) & 0xFF);
157 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
158 byteBuf.writeByte((optionLength - 269) & 0xFF);
162 else if (optionDelta < 65805) {
164 if (optionLength < 13) {
165 byteBuf.writeByte(((14 & 0xFF) << 4) | (optionLength & 0xFF));
166 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
167 byteBuf.writeByte((optionDelta - 269) & 0xFF);
170 else if (optionLength < 269) {
171 byteBuf.writeByte(((14 & 0xFF) << 4) | (13 & 0xFF));
172 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
173 byteBuf.writeByte((optionDelta - 269) & 0xFF);
174 byteBuf.writeByte((optionLength - 13) & 0xFF);
178 byteBuf.writeByte(((14 & 0xFF) << 4) | (14 & 0xFF));
179 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
180 byteBuf.writeByte((optionDelta - 269) & 0xFF);
181 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
182 byteBuf.writeByte((optionLength - 269) & 0xFF);
185 throw new IllegalArgumentException(
186 "Unsupported option delta " + optionDelta);
189 if (optionLength > 0) {
190 byteBuf.writeBytes(value);