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.ArrayList;
26 import org.iotivity.cloud.base.OICConstants;
27 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
28 import org.iotivity.cloud.util.Cbor;
29 import org.iotivity.cloud.util.Log;
31 import com.google.gson.Gson;
33 import io.netty.channel.ChannelDuplexHandler;
34 import io.netty.channel.ChannelHandler.Sharable;
35 import io.netty.channel.ChannelHandlerContext;
36 import io.netty.channel.ChannelPromise;
40 * This class provides a set of APIs to print out logs for CoAP request and
45 public class CoapLogHandler extends ChannelDuplexHandler {
47 private Cbor<Object> mCbor = new Cbor<>();
48 private Gson mGson = new Gson();
50 static final int MAX_LOGLEN = 100;
53 public void channelActive(ChannelHandlerContext ctx) throws Exception {
54 Log.v(ctx.channel().id().asLongText().substring(26)
55 + " Connected, Address: "
56 + ctx.channel().remoteAddress().toString());
58 ctx.fireChannelActive();
62 public void channelInactive(ChannelHandlerContext ctx) throws Exception {
63 Log.v(ctx.channel().id().asLongText().substring(26)
64 + " Disconnected, Address: "
65 + ctx.channel().remoteAddress().toString());
67 ctx.fireChannelInactive();
71 public void write(ChannelHandlerContext ctx, Object msg,
72 ChannelPromise promise) {
76 if (msg instanceof CoapRequest) {
77 log = composeCoapRequest(
78 ctx.channel().id().asLongText().substring(26),
80 } else if (msg instanceof CoapResponse) {
81 log = composeCoapResponse(ctx.channel().id().asLongText()
82 .substring(26), (CoapResponse) msg);
89 ctx.writeAndFlush(msg);
93 public void channelRead(ChannelHandlerContext ctx, Object msg)
98 if (msg instanceof CoapRequest) {
99 log = composeCoapRequest(
100 ctx.channel().id().asLongText().substring(26),
102 } else if (msg instanceof CoapResponse) {
103 log = composeCoapResponse(ctx.channel().id().asLongText()
104 .substring(26), (CoapResponse) msg);
111 ctx.fireChannelRead(msg);
114 private String composeCoapRequest(String channelId, CoapRequest request) {
115 StringBuilder strBuilder = new StringBuilder();
117 strBuilder.append(channelId);
118 strBuilder.append(" " + request.getTokenString());
120 switch (request.getMethod()) {
122 strBuilder.append(" DELETE ");
125 switch (request.getObserve()) {
127 strBuilder.append(" GET OBSERVE ");
130 strBuilder.append(" GET OBSERVE CANCEL ");
133 strBuilder.append(" GET ");
138 strBuilder.append(" POST ");
141 strBuilder.append(" PUT ");
145 strBuilder.append(request.getUriPath());
146 String query = request.getUriQuery();
148 strBuilder.append("/?" + query);
151 if (request.getPayloadSize() > 0) {
152 strBuilder.append(" CT:" + request.getContentFormat());
153 strBuilder.append(" SZ:" + request.getPayloadSize() + " P:"
154 + getJsonPayloadString(request));
157 return strBuilder.toString();
160 private String composeCoapResponse(String channelId,
161 CoapResponse response) {
162 StringBuilder strBuilder = new StringBuilder();
164 strBuilder.append(channelId);
165 strBuilder.append(" " + response.getTokenString());
167 switch (response.getStatus()) {
169 strBuilder.append(" 5.02 Bad Gateway");
172 strBuilder.append(" 4.02 Bad Option");
175 strBuilder.append(" 4.00 Bad Request");
178 strBuilder.append(" 2.04 Changed");
181 strBuilder.append(" 2.05 Content");
184 strBuilder.append(" 2.01 Created");
187 strBuilder.append(" 2.02 Deleted");
190 strBuilder.append(" 4.03 Forbidden");
192 case GATEWAY_TIMEOUT:
193 strBuilder.append(" 5.04 Gateway Timeout");
195 case INTERNAL_SERVER_ERROR:
196 strBuilder.append(" 5.00 Internal Server Error");
198 case METHOD_NOT_ALLOWED:
199 strBuilder.append(" 4.05 Method Not Allowed");
202 strBuilder.append(" 4.06 Not Acceptable");
205 strBuilder.append(" 4.04 Not Found");
207 case NOT_IMPLEMENTED:
208 strBuilder.append(" 5.01 Not Implemented");
210 case PRECONDITION_FAILED:
211 strBuilder.append(" 4.12 Precondition Failed");
213 case PROXY_NOT_SUPPORTED:
214 strBuilder.append(" 5.05 Proxying Not Supported");
216 case REQUEST_ENTITY_TOO_LARGE:
217 strBuilder.append(" 4.13 Request Entity Too Large");
219 case SERVICE_UNAVAILABLE:
220 strBuilder.append(" 5.03 Service Unavailable");
223 strBuilder.append(" 4.01 Unauthorized");
225 case UNSUPPORTED_CONTENT_FORMAT:
226 strBuilder.append(" 4.15 Unsupported Content-Format");
229 strBuilder.append(" 2.03 Valid");
235 switch (response.getObserve()) {
237 strBuilder.append(" OBSERVE");
240 strBuilder.append(" OBSERVE CANCEL");
242 case SEQUENCE_NUMBER:
243 strBuilder.append(" OBSERVE SEQ:");
244 strBuilder.append(response.getSequenceNumber());
250 if (response.getPayloadSize() > 0) {
251 strBuilder.append(" CT:" + response.getContentFormat());
252 strBuilder.append(" SZ:" + response.getPayloadSize() + " P:"
253 + getJsonPayloadString(response));
256 return strBuilder.toString();
259 private String getJsonPayloadString(CoapMessage coapMessage) {
260 String jsonPayload = null;
261 if (coapMessage.getContentFormat() == ContentFormat.APPLICATION_CBOR) {
263 Object mapPayload = mCbor.parsePayloadFromCbor(
264 coapMessage.getPayload(), Object.class);
265 if (coapMessage.getUriPath()
266 .contains(OICConstants.WELL_KNOWN_FULL_URI)) {
267 jsonPayload = mGson.toJson((ArrayList<Object>) mapPayload);
268 return jsonPayload.length() <= MAX_LOGLEN ? jsonPayload
269 : jsonPayload.substring(0, MAX_LOGLEN);
271 jsonPayload = mGson.toJson(mapPayload);
272 return jsonPayload.length() <= MAX_LOGLEN ? jsonPayload
273 : jsonPayload.substring(0, MAX_LOGLEN);