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 if (values.size() > 0) {
104 for (byte[] value : values) {
105 writeOption(i - preOptionNum,
106 value != null ? value.length : 0, byteBuf,
112 writeOption(i - preOptionNum, 0, byteBuf, null);
119 private void writeOption(int optionDelta, int optionLength, ByteBuf byteBuf,
122 if (optionDelta < 13) {
123 if (optionLength < 13) {
125 ((optionDelta & 0xFF) << 4) | (optionLength & 0xFF));
126 } else if (optionLength < 269) {
127 byteBuf.writeByte(((optionDelta << 4) & 0xFF) | (13 & 0xFF));
128 byteBuf.writeByte((optionLength - 13) & 0xFF);
130 byteBuf.writeByte(((optionDelta << 4) & 0xFF) | (14 & 0xFF));
131 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
132 byteBuf.writeByte((optionLength - 269) & 0xFF);
136 else if (optionDelta < 269) {
137 if (optionLength < 13) {
138 byteBuf.writeByte(((13 & 0xFF) << 4) | (optionLength & 0xFF));
139 byteBuf.writeByte((optionDelta - 13) & 0xFF);
140 } else if (optionLength < 269) {
141 byteBuf.writeByte(((13 & 0xFF) << 4) | (13 & 0xFF));
142 byteBuf.writeByte((optionDelta - 13) & 0xFF);
143 byteBuf.writeByte((optionLength - 13) & 0xFF);
145 byteBuf.writeByte((13 & 0xFF) << 4 | (14 & 0xFF));
146 byteBuf.writeByte((optionDelta - 13) & 0xFF);
147 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
148 byteBuf.writeByte((optionLength - 269) & 0xFF);
152 else if (optionDelta < 65805) {
154 if (optionLength < 13) {
155 byteBuf.writeByte(((14 & 0xFF) << 4) | (optionLength & 0xFF));
156 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
157 byteBuf.writeByte((optionDelta - 269) & 0xFF);
160 else if (optionLength < 269) {
161 byteBuf.writeByte(((14 & 0xFF) << 4) | (13 & 0xFF));
162 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
163 byteBuf.writeByte((optionDelta - 269) & 0xFF);
164 byteBuf.writeByte((optionLength - 13) & 0xFF);
168 byteBuf.writeByte(((14 & 0xFF) << 4) | (14 & 0xFF));
169 byteBuf.writeByte(((optionDelta - 269) & 0xFF00) >>> 8);
170 byteBuf.writeByte((optionDelta - 269) & 0xFF);
171 byteBuf.writeByte(((optionLength - 269) & 0xFF00) >>> 8);
172 byteBuf.writeByte((optionLength - 269) & 0xFF);
175 throw new IllegalArgumentException(
176 "Unsupported option delta " + optionDelta);
179 if (optionLength > 0) {
180 byteBuf.writeBytes(value);