Fix terminate sequence and observe option parser
[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         cbor = new Cbor<HashMap<String, Integer>>();
73     }
74     
75     public void startSessionChecker()
76     {
77         timer.schedule(new KeepAliveTask(), 30000, 60000);
78     }
79     
80     public void stopSessionChecker()
81     {
82         timer.cancel();
83     }
84
85     /**
86      * API for receiving message(message to keepalive resource)
87      * 
88      * @param ctx
89      *            ChannelHandlerContext of request message
90      * @param request
91      *            CoAP request message
92      */
93     @Override
94     public void onRequestReceived(ChannelHandlerContext ctx,
95             CoapRequest request) {
96
97         CoapResponse response = null;
98
99         switch (request.getRequestMethod()) {
100             // First message to KeepAlive from resource
101             case GET:
102                 if (intervals != null) {
103                     response = makePingConfigMessage(request);
104                     connectPool.put(ctx, System.currentTimeMillis()
105                             + (intervals[0] * (long) 60000));
106                 }
107                 break;
108             // interval Message to KeepAlive After receiving GET Message
109             case PUT:
110                 HashMap<String, Integer> payloadData = null;
111                 payloadData = cbor.parsePayloadFromCbor(request.getPayload(),
112                         new HashMap<String, Integer>().getClass());
113
114                 Logger.d("Receive payloadData : " + payloadData);
115                 Logger.d("interval : " + payloadData.get("in"));
116
117                 connectPool.put(ctx, System.currentTimeMillis()
118                         + (payloadData.get("in") * (long) 60000));
119
120                 response = makeResponse(request);
121                 break;
122
123             case POST:
124                 break;
125
126             case DELETE:
127                 break;
128         }
129
130         ctx.writeAndFlush(response);
131     }
132
133     /**
134      * API for making response to Resource
135      * 
136      * @param request
137      *            ChannelHandlerContext of request message
138      */
139     private CoapResponse makeResponse(CoapRequest request) {
140         CoapResponse response = new CoapResponse(CoapStatus.VALID);
141         response.setToken(request.getToken());
142
143         return response;
144     }
145
146     /**
147      * API for making interval and first response to Resource
148      * 
149      * @param request
150      *            ChannelHandlerContext of request message
151      */
152     private CoapResponse makePingConfigMessage(CoapRequest request) {
153         CoapResponse response = new CoapResponse(CoapStatus.CONTENT);
154         response.setToken(request.getToken());
155
156         HashMap<String, int[]> payloadData = new HashMap<String, int[]>();
157         payloadData.put("inarray", intervals);
158
159         byte[] cborData = cbor.encodingPayloadToCbor(payloadData);
160
161         response.setPayload(cborData);
162
163         Logger.d("Send payloadData : " + payloadData);
164
165         return response;
166     }
167
168     /**
169      * API for managing session
170      */
171     public class KeepAliveTask extends TimerTask {
172
173         @Override
174         public void run() {
175             Map<ChannelHandlerContext, Long> map = Collections
176                     .synchronizedMap(connectPool);
177             Set<ChannelHandlerContext> keySet = map.keySet();
178             ArrayList<ChannelHandlerContext> deleteList = new ArrayList<ChannelHandlerContext>();
179             Iterator<ChannelHandlerContext> iterator = null;
180             synchronized (map) {
181                 iterator = keySet.iterator();
182                 Long currentTime = System.currentTimeMillis();
183                 // check interval
184                 while (iterator.hasNext()) {
185                     ChannelHandlerContext key = iterator.next();
186                     Long lifeTime = (Long) map.get(key);
187                     Logger.d("KeepAliveTask Operating : "
188                             + key.channel().toString() + ", Time : "
189                             + (lifeTime - currentTime));
190                     if (lifeTime < currentTime) {
191                         deleteList.add(key);
192                     }
193                 }
194
195             }
196             iterator = deleteList.iterator();
197             // remove session
198             while (iterator.hasNext()) {
199                 ChannelHandlerContext key = iterator.next();
200                 Logger.d("KeepAliveTask Remove");
201                 connectPool.remove(key);
202                 sessionManager.removeSessionByChannel(key);
203                 key.close();
204             }
205         }
206     }
207 }