[IOT-1533] fixed KeepAlive resource for receiving PUT, POST Message
[platform/upstream/iotivity.git] / cloud / interface / src / main / java / org / iotivity / cloud / ciserver / resources / KeepAliveResource.java
index a2424a0..8e89806 100644 (file)
 package org.iotivity.cloud.ciserver.resources;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.Timer;
 import java.util.TimerTask;
 
-import org.iotivity.cloud.base.Resource;
-import org.iotivity.cloud.base.SessionManager;
-import org.iotivity.cloud.base.protocols.coap.CoapRequest;
-import org.iotivity.cloud.base.protocols.coap.CoapResponse;
-import org.iotivity.cloud.base.protocols.coap.enums.CoapStatus;
+import org.iotivity.cloud.base.device.Device;
+import org.iotivity.cloud.base.exception.ServerException;
+import org.iotivity.cloud.base.exception.ServerException.BadRequestException;
+import org.iotivity.cloud.base.protocols.IRequest;
+import org.iotivity.cloud.base.protocols.IResponse;
+import org.iotivity.cloud.base.protocols.MessageBuilder;
+import org.iotivity.cloud.base.protocols.enums.ContentFormat;
+import org.iotivity.cloud.base.protocols.enums.ResponseStatus;
+import org.iotivity.cloud.base.resource.Resource;
 import org.iotivity.cloud.ciserver.Constants;
 import org.iotivity.cloud.util.Cbor;
-import org.iotivity.cloud.util.Logger;
-
-import io.netty.channel.ChannelHandlerContext;
 
 /**
  *
@@ -48,90 +49,46 @@ import io.netty.channel.ChannelHandlerContext;
  *
  */
 public class KeepAliveResource extends Resource {
-
-    private int[]                                intervals;
-    private HashMap<ChannelHandlerContext, Long> connectPool;
-    private Timer                                timer;
-    private Cbor<HashMap<String, Integer>>       cbor;
-    private SessionManager                       sessionManager = null;
-
-    public void setIntervals(int[] intervals) {
-        this.intervals = intervals;
-    }
-
-    public int[] getIntervals() {
-        return this.intervals;
+    private int[]                         mIntervals      = null;
+    private Timer                         mTimer          = new Timer();
+    private Cbor<HashMap<String, Object>> mCbor           = new Cbor<>();
+    private HashMap<Device, Long>         mConnectionPool = new HashMap<>();
+
+    public KeepAliveResource(int[] intervals) {
+        super(Arrays.asList(Constants.PREFIX_OIC, Constants.KEEP_ALIVE_URI));
+        mIntervals = intervals;
     }
 
-    public KeepAliveResource(SessionManager sessionManager, int[] intervals) {
-        setUri(Constants.KEEP_ALIVE_URI);
-        setIntervals(intervals);
-        this.sessionManager = sessionManager;
-        connectPool = new HashMap<ChannelHandlerContext, Long>();
-        timer = new Timer();
-        timer.schedule(new KeepAliveTask(), 30000, 60000);
-        cbor = new Cbor<HashMap<String, Integer>>();
-    }
-
-    /**
-     * API for receiving message(message to keepalive resource)
-     * 
-     * @param ctx
-     *            ChannelHandlerContext of request message
-     * @param request
-     *            CoAP request message
-     */
     @Override
-    public void onRequestReceived(ChannelHandlerContext ctx,
-            CoapRequest request) {
+    public void onDefaultRequestReceived(Device srcDevice, IRequest request)
+            throws ServerException {
 
-        CoapResponse response = null;
+        IResponse response = null;
 
-        switch (request.getRequestMethod()) {
-            // First message to KeepAlive from resource
+        switch (request.getMethod()) {
             case GET:
-                if (intervals != null) {
-                    response = makePingConfigMessage(request);
-                    connectPool.put(ctx, System.currentTimeMillis()
-                            + (intervals[0] * (long) 60000));
-                }
-                break;
-            // interval Message to KeepAlive After receiving GET Message
-            case PUT:
-                HashMap<String, Integer> payloadData = null;
-                payloadData = cbor.parsePayloadFromCbor(request.getPayload(),
-                        new HashMap<String, Integer>().getClass());
-
-                Logger.d("Receive payloadData : " + payloadData);
-                Logger.d("interval : " + payloadData.get("in"));
-
-                connectPool.put(ctx, System.currentTimeMillis()
-                        + (payloadData.get("in") * (long) 60000));
-
-                response = makeResponse(request);
+                response = handlePingConfig(request);
                 break;
 
+            case PUT:
             case POST:
+                response = handlePingConfig(srcDevice, request);
                 break;
 
-            case DELETE:
-                break;
+            default:
+                throw new BadRequestException(
+                        request.getMethod() + " request type is not support");
         }
 
-        ctx.writeAndFlush(response);
+        srcDevice.sendResponse(response);
     }
 
-    /**
-     * API for making response to Resource
-     * 
-     * @param request
-     *            ChannelHandlerContext of request message
-     */
-    private CoapResponse makeResponse(CoapRequest request) {
-        CoapResponse response = new CoapResponse(CoapStatus.VALID);
-        response.setToken(request.getToken());
+    public void startSessionChecker(int startTime, int intervalTime) {
+        mTimer.schedule(new KeepAliveTask(), startTime, intervalTime);
+    }
 
-        return response;
+    public void stopSessionChecker() {
+        mTimer.cancel();
     }
 
     /**
@@ -140,58 +97,57 @@ public class KeepAliveResource extends Resource {
      * @param request
      *            ChannelHandlerContext of request message
      */
-    private CoapResponse makePingConfigMessage(CoapRequest request) {
-        CoapResponse response = new CoapResponse(CoapStatus.CONTENT);
-        response.setToken(request.getToken());
+    private IResponse handlePingConfig(IRequest request) {
+
+        HashMap<String, int[]> payloadData = new HashMap<>();
+        payloadData.put(Constants.REQ_PING_ARRAY, mIntervals);
+
+        return MessageBuilder.createResponse(request, ResponseStatus.CONTENT,
+                ContentFormat.APPLICATION_CBOR,
+                mCbor.encodingPayloadToCbor(payloadData));
+    }
 
-        HashMap<String, int[]> payloadData = new HashMap<String, int[]>();
-        payloadData.put("inarray", intervals);
+    private IResponse handlePingConfig(Device srcDevice, IRequest request) {
 
-        byte[] cborData = cbor.encodingPayloadToCbor(payloadData);
+        HashMap<String, Object> payloadData = mCbor
+                .parsePayloadFromCbor(request.getPayload(), HashMap.class);
 
-        response.setPayload(cborData);
+        checkPayloadException(Constants.REQ_PING, payloadData);
 
-        Logger.d("Send payloadData : " + payloadData);
+        Long pingTime = Integer.valueOf(
+                payloadData.get(Constants.REQ_PING).toString()) * (long) 60000;
+        Long connectionTime = System.currentTimeMillis() + pingTime;
+        mConnectionPool.put(srcDevice, connectionTime);
 
-        return response;
+        return MessageBuilder.createResponse(request, ResponseStatus.VALID);
     }
 
     /**
      * API for managing session
      */
-    public class KeepAliveTask extends TimerTask {
+    private class KeepAliveTask extends TimerTask {
 
         @Override
         public void run() {
-            Map<ChannelHandlerContext, Long> map = Collections
-                    .synchronizedMap(connectPool);
-            Set<ChannelHandlerContext> keySet = map.keySet();
-            ArrayList<ChannelHandlerContext> deleteList = new ArrayList<ChannelHandlerContext>();
-            Iterator<ChannelHandlerContext> iterator = null;
+            Map<Device, Long> map = Collections
+                    .synchronizedMap(mConnectionPool);
+
+            List<Device> deleteList = new ArrayList<>();
+
             synchronized (map) {
-                iterator = keySet.iterator();
                 Long currentTime = System.currentTimeMillis();
-                // check interval
-                while (iterator.hasNext()) {
-                    ChannelHandlerContext key = iterator.next();
-                    Long lifeTime = (Long) map.get(key);
-                    Logger.d("KeepAliveTask Operating : "
-                            + key.channel().toString() + ", Time : "
-                            + (lifeTime - currentTime));
-                    if (lifeTime < currentTime) {
-                        deleteList.add(key);
+                for (Device device : map.keySet()) {
+                    Long lifeTime = (Long) map.get(device);
+                    if (lifeTime != null && lifeTime < currentTime) {
+                        deleteList.add(device);
                     }
                 }
-
             }
-            iterator = deleteList.iterator();
-            // remove session
-            while (iterator.hasNext()) {
-                ChannelHandlerContext key = iterator.next();
-                Logger.d("KeepAliveTask Remove");
-                connectPool.remove(key);
-                sessionManager.removeSessionByChannel(key);
-                key.close();
+
+            for (Device device : deleteList) {
+                mConnectionPool.remove(device);
+                device.getCtx().fireChannelInactive();
+                device.getCtx().close();
             }
         }
     }