[Simulator] Minor UI changes fixing the IOT-1087.
[platform/upstream/iotivity.git] / cloud / stack / src / main / java / org / iotivity / cloud / base / protocols / proxy / CoapHttpProxyHandler.java
1 /*
2  *******************************************************************
3  *
4  * Copyright 2016 Samsung Electronics All Rights Reserved.
5  *
6  *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  *
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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.base.protocols.proxy;
23
24 import java.nio.charset.StandardCharsets;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map.Entry;
28
29 import org.iotivity.cloud.base.SessionManager;
30 import org.iotivity.cloud.base.protocols.coap.CoapRequest;
31 import org.iotivity.cloud.base.protocols.coap.CoapResponse;
32 import org.iotivity.cloud.base.protocols.coap.enums.CoapMethod;
33 import org.iotivity.cloud.util.Cbor;
34 import org.iotivity.cloud.util.Logger;
35
36 import io.netty.buffer.Unpooled;
37 import io.netty.channel.ChannelDuplexHandler;
38 import io.netty.channel.ChannelFutureListener;
39 import io.netty.channel.ChannelHandler.Sharable;
40 import io.netty.channel.ChannelHandlerContext;
41 import io.netty.handler.codec.http.DefaultFullHttpResponse;
42 import io.netty.handler.codec.http.HttpHeaders;
43 import io.netty.handler.codec.http.HttpMethod;
44 import io.netty.handler.codec.http.HttpRequest;
45 import io.netty.handler.codec.http.HttpResponse;
46 import io.netty.handler.codec.http.HttpResponseStatus;
47 import io.netty.handler.codec.http.HttpVersion;
48 import io.netty.handler.codec.http.QueryStringDecoder;
49 import io.netty.util.AttributeKey;
50 import io.netty.util.CharsetUtil;
51
52 @Sharable
53 public class CoapHttpProxyHandler extends ChannelDuplexHandler {
54
55     // Proxy converts http request to coaprequest and coapresponse to
56     // httpresponse
57     private SessionManager sessionManager = null;
58
59     private static final AttributeKey<ChannelHandlerContext> keyHttpCtx = AttributeKey
60             .newInstance("httpCtx");
61
62     public CoapHttpProxyHandler(SessionManager sessionManager) {
63         this.sessionManager = sessionManager;
64     }
65
66     @Override
67     public void channelRead(ChannelHandlerContext ctx, Object msg)
68             throws Exception {
69
70         // in case of Receive Request from http
71         if (msg instanceof HttpRequest) {
72             // Check uri query param that contains coap device uuid
73             // then search those and create coapRequest and send
74             HttpRequest httpRequest = (HttpRequest) msg;
75             QueryStringDecoder queryStringDecoder = new QueryStringDecoder(
76                     httpRequest.getUri());
77
78             List<String> didList = queryStringDecoder.parameters().get("di");
79
80             if (didList != null) {
81                 ChannelHandlerContext coapClient = sessionManager
82                         .querySession(didList.get(0));
83
84                 if (coapClient != null) {
85                     List<String> uriList = queryStringDecoder.parameters()
86                             .get("href");
87                     if (uriList != null) {
88                         coapClient.channel().attr(keyHttpCtx).set(ctx);
89                         coapClient.writeAndFlush(httpRequestToCoAPRequest(
90                                 uriList.get(0), (HttpRequest) msg));
91
92                         return;
93                     }
94                 } else {
95                     Logger.d("Unable to find session: " + didList.get(0));
96                 }
97             }
98
99             // Prints available sessions to html
100
101             ctx.writeAndFlush(printsAvailableSessions())
102                     .addListener(ChannelFutureListener.CLOSE);
103             return;
104         }
105
106         if (msg instanceof CoapResponse) {
107             ctx.channel().attr(keyHttpCtx).get()
108                     .writeAndFlush(
109                             coapResponseToHttpResponse((CoapResponse) msg))
110                     .addListener(ChannelFutureListener.CLOSE);
111             return;
112         }
113
114         // Pass to upper-layer
115         super.channelRead(ctx, msg);
116     }
117
118     @Override
119     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
120         cause.printStackTrace();
121         ctx.close();
122     }
123
124     HttpResponse printsAvailableSessions() {
125
126         StringBuilder strBuilder = new StringBuilder();
127         List<String> sessions = sessionManager.getSessions();
128
129         strBuilder.append("<html>");
130         strBuilder.append("<b>Available sessions</b><br>");
131
132         for (String session : sessions) {
133             strBuilder.append(session);
134             strBuilder.append("<br>");
135         }
136
137         strBuilder.append("</html>");
138
139         HttpResponse response = new DefaultFullHttpResponse(
140                 HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
141                 Unpooled.copiedBuffer(strBuilder.toString(),
142                         CharsetUtil.UTF_8));
143         response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
144                 "text/html; charset=UTF-8");
145
146         return response;
147     }
148
149     HttpResponse httpRequestToSendError() {
150         HttpResponse response = new DefaultFullHttpResponse(
151                 HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND,
152                 Unpooled.copiedBuffer(
153                         "Failure: " + HttpResponseStatus.NOT_FOUND + "\r\n",
154                         CharsetUtil.UTF_8));
155         response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
156                 "text/html; charset=UTF-8");
157
158         return response;
159     }
160
161     CoapRequest httpRequestToCoAPRequest(String uri, HttpRequest httpRequest) {
162         CoapRequest coapRequest;
163
164         // TODO: coapRequest converter required
165         // coapRequest.getOptions().setUriQuery();
166         if (httpRequest.getMethod() == HttpMethod.GET) {
167             coapRequest = new CoapRequest(CoapMethod.GET);
168         } else if (httpRequest.getMethod() == HttpMethod.PUT) {
169             coapRequest = new CoapRequest(CoapMethod.PUT);
170         } else if (httpRequest.getMethod() == HttpMethod.POST) {
171             coapRequest = new CoapRequest(CoapMethod.POST);
172         } else if (httpRequest.getMethod() == HttpMethod.DELETE) {
173             coapRequest = new CoapRequest(CoapMethod.DELETE);
174         } else {
175             throw new IllegalArgumentException();
176         }
177
178         coapRequest.setUriPath(uri);
179
180         return coapRequest;
181     }
182
183     HttpResponse coapResponseToHttpResponse(CoapResponse coapResponse) {
184
185         Cbor<HashMap<String, Object>> cbor = new Cbor<HashMap<String, Object>>();
186
187         HashMap<String, Object> rep = cbor
188                 .parsePayloadFromCbor(coapResponse.getPayload(), HashMap.class);
189
190         StringBuilder strBuilder = new StringBuilder();
191
192         for (Entry<String, Object> entry : rep.entrySet()) {
193             String key = entry.getKey();
194             String value = entry.getValue().toString();
195             strBuilder.append("Key: " + key + " Value: " + value + "<br>");
196         }
197
198         HttpResponse httpResponse = new DefaultFullHttpResponse(
199                 HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
200                 Unpooled.wrappedBuffer(strBuilder.toString().getBytes(StandardCharsets.UTF_8)));
201
202         httpResponse.headers().set(HttpHeaders.Names.CONTENT_TYPE,
203                 "text/html; charset=UTF-8");
204
205         // TODO: httpResponse converter required
206
207         return httpResponse;
208     }
209 }