1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.coap.codec;
21
22 import java.nio.ByteBuffer;
23 import java.nio.ByteOrder;
24
25 import org.apache.mina.coap.CoapMessage;
26 import org.apache.mina.coap.CoapOption;
27 import org.apache.mina.codec.StatelessProtocolEncoder;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31
32
33
34
35
36
37
38 public class CoapEncoder implements StatelessProtocolEncoder<CoapMessage, ByteBuffer> {
39
40 private static final Logger LOG = LoggerFactory.getLogger(CoapEncoder.class);
41
42 private static final int HEADER_SIZE = 4;
43
44
45
46
47 @Override
48 public Void createEncoderState() {
49 return null;
50 }
51
52
53
54
55 @Override
56 public ByteBuffer encode(CoapMessage message, Void context) {
57
58 LOG.debug("encoding {}", message);
59
60
61 int size = HEADER_SIZE + message.getToken().length;
62
63 int delta = 0;
64 for (CoapOption opt : message.getOptions()) {
65
66 int code = opt.getType().getCode();
67 delta = code - delta;
68 if (delta < 13) {
69 size += 1;
70 } else if (delta < 256 + 13) {
71 size += 2;
72 } else if (delta < 65536 + 269) {
73 size += 3;
74 }
75
76
77 int optLength = opt.getData().length;
78 if (optLength < 13) {
79 size += 0;
80 } else if (optLength < 256 + 13) {
81 size += 1;
82 } else if (optLength < 65536 + 269) {
83 size += 2;
84 }
85
86
87 size += optLength;
88 }
89
90
91 if (message.getPayload() != null && message.getPayload().length > 0) {
92
93 size += 1;
94 size += message.getPayload().length;
95 }
96
97 ByteBuffer buffer = ByteBuffer.allocate(size);
98
99 buffer.order(ByteOrder.BIG_ENDIAN);
100
101
102 buffer.put((byte) (((message.getVersion() & 0x03) << 6) | (message.getType().getCode() & 0x03) << 4 | (message
103 .getToken().length & 0x0F)));
104 buffer.put((byte) message.getCode());
105 buffer.putShort((short) message.getId());
106 buffer.put(message.getToken());
107
108
109 int lastOptCode = 0;
110
111 for (CoapOption opt : message.getOptions()) {
112 int optionDelta = opt.getType().getCode() - lastOptCode;
113 int deltaQuartet = getQuartet(optionDelta);
114 int optionLength = opt.getData().length;
115
116 int optionQuartet = getQuartet(optionLength);
117
118 buffer.put((byte) ((deltaQuartet << 4) | optionQuartet));
119
120
121 if (deltaQuartet == 13) {
122 buffer.put((byte) (optionDelta - 13));
123 } else if (deltaQuartet == 14) {
124 buffer.putShort((short) (optionDelta - 269));
125 }
126
127 if (optionQuartet == 13) {
128 buffer.put((byte) (optionLength - 13));
129 } else if (optionQuartet == 14) {
130 buffer.putShort((short) (optionLength - 269));
131 }
132 buffer.put(opt.getData());
133
134 lastOptCode = opt.getType().getCode();
135 }
136
137 if (message.getPayload() != null && message.getPayload().length > 0) {
138 buffer.put((byte) 0xFF);
139 buffer.put(message.getPayload());
140 }
141
142 buffer.flip();
143 return buffer;
144 }
145
146 private int getQuartet(int value) {
147 if (value <= 12) {
148 return value;
149 } else if (value <= 255 + 13) {
150 return 13;
151 } else {
152 return 14;
153 }
154 }
155 }