Merge branch 'master' into extended-easysetup
[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.Arrays;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.Timer;
32 import java.util.TimerTask;
33
34 import org.iotivity.cloud.base.device.Device;
35 import org.iotivity.cloud.base.exception.ServerException;
36 import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
37 import org.iotivity.cloud.base.protocols.IRequest;
38 import org.iotivity.cloud.base.protocols.IResponse;
39 import org.iotivity.cloud.base.protocols.MessageBuilder;
40 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
41 import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
42 import org.iotivity.cloud.base.resource.Resource;
43 import org.iotivity.cloud.ciserver.Constants;
44 import org.iotivity.cloud.util.Cbor;
45
46 /**
47  *
48  * This class provides a set of APIs to use KeepAlive Resource for ensuring the
49  * connection.
50  *
51  */
52 public class KeepAliveResource extends Resource {
53     private int[]                          mIntervals      = null;
54     private Timer                          mTimer          = new Timer();
55     private Cbor<HashMap<String, Integer>> mCbor           = new Cbor<>();
56     private HashMap<Device, Long>          mConnectionPool = new HashMap<>();
57
58     public KeepAliveResource(int[] intervals) {
59         super(Arrays.asList(Constants.PREFIX_OIC, Constants.KEEP_ALIVE_URI));
60         mIntervals = intervals;
61     }
62
63     @Override
64     public void onDefaultRequestReceived(Device srcDevice, IRequest request)
65             throws ServerException {
66
67         IResponse response = null;
68
69         switch (request.getMethod()) {
70             case GET:
71                 response = handleGetPingConfig(request);
72                 mConnectionPool.put(srcDevice, System.currentTimeMillis()
73                         + (mIntervals[0] * (long) 60000));
74                 break;
75
76             case PUT:
77                 response = handlePutPingConfig(srcDevice, request);
78                 break;
79
80             default:
81                 throw new BadRequestException(
82                         request.getMethod() + " request type is not support");
83         }
84
85         srcDevice.sendResponse(response);
86     }
87
88     public void startSessionChecker() {
89         mTimer.schedule(new KeepAliveTask(), 30000, 60000);
90     }
91
92     public void stopSessionChecker() {
93         mTimer.cancel();
94     }
95
96     /**
97      * API for making interval and first response to Resource
98      * 
99      * @param request
100      *            ChannelHandlerContext of request message
101      */
102     private IResponse handleGetPingConfig(IRequest request) {
103
104         HashMap<String, int[]> payloadData = new HashMap<>();
105         payloadData.put("inarray", mIntervals);
106
107         return MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
108                 ContentFormat.APPLICATION_CBOR,
109                 mCbor.encodingPayloadToCbor(payloadData));
110     }
111
112     private IResponse handlePutPingConfig(Device srcDevice, IRequest request) {
113
114         HashMap<String, Integer> payloadData = mCbor
115                 .parsePayloadFromCbor(request.getPayload(), HashMap.class);
116         if (payloadData != null) {
117             if (payloadData.containsKey("in")) {
118                 mConnectionPool.put(srcDevice, System.currentTimeMillis()
119                         + (payloadData.get("in") * (long) 60000));
120             }
121         }
122         return MessageBuilder.createResponse(request, ResponseStatus.VALID);
123     }
124
125     /**
126      * API for managing session
127      */
128     private class KeepAliveTask extends TimerTask {
129
130         @Override
131         public void run() {
132             Map<Device, Long> map = Collections
133                     .synchronizedMap(mConnectionPool);
134             Set<Device> keySet = map.keySet();
135             ArrayList<Device> deleteList = new ArrayList<>();
136             Iterator<Device> iterator = null;
137             synchronized (map) {
138                 iterator = keySet.iterator();
139                 Long currentTime = System.currentTimeMillis();
140                 // check interval
141                 while (iterator.hasNext()) {
142                     Device key = iterator.next();
143                     if (map.containsKey(key)) {
144                         if (map.get(key) != null) {
145                             Long lifeTime = (Long) map.get(key);
146                             if (lifeTime != null) {
147                                 if (lifeTime < currentTime) {
148                                     deleteList.add(key);
149                                 }
150                             }
151                         }
152                     }
153                 }
154
155             }
156             iterator = deleteList.iterator();
157             // remove session
158             while (iterator.hasNext()) {
159                 Device key = iterator.next();
160                 mConnectionPool.remove(key);
161                 key.getCtx().fireChannelInactive();
162                 key.getCtx().close();
163             }
164         }
165     }
166 }