Merge branch 'master' into windows-port
[platform/upstream/iotivity.git] / cloud / interface / src / main / java / org / iotivity / cloud / ciserver / resources / KeepAliveResource.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.ciserver.resources;
23
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.Timer;
31 import java.util.TimerTask;
32
33 import org.iotivity.cloud.base.Resource;
34 import org.iotivity.cloud.base.SessionManager;
35 import org.iotivity.cloud.base.protocols.coap.CoapRequest;
36 import org.iotivity.cloud.base.protocols.coap.CoapResponse;
37 import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
38 import org.iotivity.cloud.ciserver.Constants;
39 import org.iotivity.cloud.util.Cbor;
40 import org.iotivity.cloud.util.Logger;
41
42 import io.netty.channel.ChannelHandlerContext;
43
44 /**
45  *
46  * This class provides a set of APIs to use KeepAlive Resource for ensuring the
47  * connection.
48  *
49  */
50 public class KeepAliveResource extends Resource {
51
52     private int[]                                intervals;
53     private HashMap<ChannelHandlerContext, Long> connectPool;
54     private Timer                                timer;
55     private Cbor<HashMap<String, Integer>>       cbor;
56     private SessionManager                       sessionManager = null;
57
58     public void setIntervals(int[] intervals) {
59         this.intervals = intervals;
60     }
61
62     public int[] getIntervals() {
63         return this.intervals;
64     }
65
66     public KeepAliveResource(SessionManager sessionManager, int[] intervals) {
67         setUri(Constants.KEEP_ALIVE_URI);
68         setIntervals(intervals);
69         this.sessionManager = sessionManager;
70         connectPool = new HashMap<ChannelHandlerContext, Long>();
71         timer = new Timer();
72         timer.schedule(new KeepAliveTask(), 30000, 60000);
73         cbor = new Cbor<HashMap<String, Integer>>();
74     }
75
76     /**
77      * API for receiving message(message to keepalive resource)
78      * 
79      * @param ctx
80      *            ChannelHandlerContext of request message
81      * @param request
82      *            CoAP request message
83      */
84     @Override
85     public void onRequestReceived(ChannelHandlerContext ctx,
86             CoapRequest request) {
87
88         CoapResponse response = null;
89
90         switch (request.getRequestMethod()) {
91             // First message to KeepAlive from resource
92             case GET:
93                 if (intervals != null) {
94                     response = makePingConfigMessage(request);
95                     connectPool.put(ctx, System.currentTimeMillis()
96                             + (intervals[0] * (long) 60000));
97                 }
98                 break;
99             // interval Message to KeepAlive After receiving GET Message
100             case PUT:
101                 HashMap<String, Integer> payloadData = null;
102                 payloadData = cbor.parsePayloadFromCbor(request.getPayload(),
103                         new HashMap<String, Integer>().getClass());
104
105                 Logger.d("Receive payloadData : " + payloadData);
106                 Logger.d("interval : " + payloadData.get("in"));
107
108                 connectPool.put(ctx, System.currentTimeMillis()
109                         + (payloadData.get("in") * (long) 60000));
110
111                 response = makeResponse(request);
112                 break;
113
114             case POST:
115                 break;
116
117             case DELETE:
118                 break;
119         }
120
121         ctx.writeAndFlush(response);
122     }
123
124     /**
125      * API for making response to Resource
126      * 
127      * @param request
128      *            ChannelHandlerContext of request message
129      */
130     private CoapResponse makeResponse(CoapRequest request) {
131         CoapResponse response = new CoapResponse(CoapStatus.VALID);
132         response.setToken(request.getToken());
133
134         return response;
135     }
136
137     /**
138      * API for making interval and first response to Resource
139      * 
140      * @param request
141      *            ChannelHandlerContext of request message
142      */
143     private CoapResponse makePingConfigMessage(CoapRequest request) {
144         CoapResponse response = new CoapResponse(CoapStatus.CONTENT);
145         response.setToken(request.getToken());
146
147         HashMap<String, int[]> payloadData = new HashMap<String, int[]>();
148         payloadData.put("inarray", intervals);
149
150         byte[] cborData = cbor.encodingPayloadToCbor(payloadData);
151
152         response.setPayload(cborData);
153
154         Logger.d("Send payloadData : " + payloadData);
155
156         return response;
157     }
158
159     /**
160      * API for managing session
161      */
162     public class KeepAliveTask extends TimerTask {
163
164         @Override
165         public void run() {
166             Map<ChannelHandlerContext, Long> map = Collections
167                     .synchronizedMap(connectPool);
168             Set<ChannelHandlerContext> keySet = map.keySet();
169             ArrayList<ChannelHandlerContext> deleteList = new ArrayList<ChannelHandlerContext>();
170             Iterator<ChannelHandlerContext> iterator = null;
171             synchronized (map) {
172                 iterator = keySet.iterator();
173                 Long currentTime = System.currentTimeMillis();
174                 // check interval
175                 while (iterator.hasNext()) {
176                     ChannelHandlerContext key = iterator.next();
177                     Long lifeTime = (Long) map.get(key);
178                     Logger.d("KeepAliveTask Operating : "
179                             + key.channel().toString() + ", Time : "
180                             + (lifeTime - currentTime));
181                     if (lifeTime < currentTime) {
182                         deleteList.add(key);
183                     }
184                 }
185
186             }
187             iterator = deleteList.iterator();
188             // remove session
189             while (iterator.hasNext()) {
190                 ChannelHandlerContext key = iterator.next();
191                 Logger.d("KeepAliveTask Remove");
192                 connectPool.remove(key);
193                 sessionManager.removeSessionByChannel(key);
194                 key.close();
195             }
196         }
197     }
198 }