diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java index 61f8d1624..4ddb89ac0 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/RemoteSessionManagementServiceImpl.java @@ -100,104 +100,13 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme // if session initiated using operation id means request came from device if (operationId != null) { - RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance() - .getActiveDeviceClientSessionMap().get((authenticationInfo.getTenantDomain() + "/" + - deviceType + "/" + deviceId)); - if (activeSession != null) { - RemoteSession clientRemote = RemoteSessionManagementDataHolder.getInstance() - .getSessionMap().get(activeSession.getMySession().getId()); - if (clientRemote != null) { - if (clientRemote.getOperationId().equals(operationId)) { - RemoteSession deviceRemote = new RemoteSession(session, authenticationInfo - .getTenantDomain(), deviceType, deviceId); - deviceRemote.setOperationId(operationId); - deviceRemote.setPeerSession(clientRemote); - clientRemote.setPeerSession(deviceRemote); - RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session - .getId(), deviceRemote); - // Send Remote connect response - JSONObject message = new JSONObject(); - message.put(RemoteSessionConstants.REMOTE_CONNECT_CODE, RemoteSessionConstants - .REMOTE_CONNECT); - deviceRemote.sendMessageToPeer(message.toString()); - log.info("Device session opened for session id: " + session.getId() + - " device Type : " + deviceType + " , " + "deviceId : " + deviceId); - } else { - throw new RemoteSessionManagementException("Device and Operation information " + - "does not matched with client information for operation id: " + - operationId + " device Type : " + deviceType + " , " + "deviceId : " + - deviceId); - } - } else { - throw new RemoteSessionManagementException("Device session is inactive for " + - "operation id: " + operationId + " device Type : " + deviceType + " , " + - "deviceId : " + deviceId); - } - - - } else { - throw new RemoteSessionManagementException("Device session is inactive for operation " + - "id: " + operationId + " device Type : " + deviceType + " , " + "deviceId : " + - deviceId); - } + // create new device session + initializeDeviceSession(session, authenticationInfo.getTenantDomain(), deviceType, deviceId, + operationId); } else { - RemoteSession clientRemote = new RemoteSession(session, authenticationInfo - .getTenantDomain(), deviceType, deviceId); - // Create new remote control operation to start the session - RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance() - .getActiveDeviceClientSessionMap().putIfAbsent((authenticationInfo - .getTenantDomain() + "/" + deviceType + "/" + deviceId), - clientRemote); - if (activeSession != null && activeSession.getMySession().isOpen() && activeSession - .getPeerSession() == null) { - throw new RemoteSessionManagementException("Another client session waiting on device " + - "to connect."); - } else { - // if there is pending session exists but already closed, then we need to remove it. - if (activeSession != null) { - endSession(activeSession.getMySession(), "Remote session closed due to new session" + - " request"); - // Use put if absent for adding session to waiting list since we need to overcome - // multithreaded session requests. - activeSession = RemoteSessionManagementDataHolder.getInstance() - .getActiveDeviceClientSessionMap().putIfAbsent((authenticationInfo - .getTenantDomain() + "/" + deviceType + "/" + - deviceId), clientRemote); - } - - // If another client tried to start session same time then active session will be - // exist. So we are adding session request only no parallel sessions added to map - if (activeSession == null) { - - // Create operation if session initiated by client - Operation operation = new ConfigOperation(); - operation.setCode(RemoteSessionConstants.REMOTE_CONNECT); - operation.setEnabled(true); - operation.setControl(Operation.Control.NO_REPEAT); - JSONObject payload = new JSONObject(); - payload.put("serverUrl", RemoteSessionManagementDataHolder.getInstance() - .getServerUrl()); - operation.setPayLoad(payload.toString()); - String date = new SimpleDateFormat(RemoteSessionConstants.DATE_FORMAT_NOW).format - (new Date()); - operation.setCreatedTimeStamp(date); - List deviceIdentifiers = new ArrayList<>(); - deviceIdentifiers.add(new DeviceIdentifier(deviceId, deviceType)); - Activity activity = RemoteSessionManagementDataHolder.getInstance() - .getDeviceManagementProviderService().addOperation(deviceType, operation, - deviceIdentifiers); - clientRemote.setOperationId(activity.getActivityId() - .replace(DeviceManagementConstants.OperationAttributes.ACTIVITY, "")); - RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session.getId - (), clientRemote); - log.info("Client remote session opened for session id: " + session.getId() + - " device Type : " + deviceType + " , " + "deviceId : " + deviceId); - - } else { - throw new RemoteSessionManagementException("Another client session waiting on " + - "device to connect."); - } - } + // create new client session + initializeClientSession(session, authenticationInfo.getTenantDomain(), deviceType, + deviceId); } log.info("Current remote sessions count: " + RemoteSessionManagementDataHolder.getInstance() .getSessionMap().size()); @@ -278,15 +187,28 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme */ @Override public void endSession(Session session, String closeReason) { - log.info("Closing session: "+session.getId()+" due to:"+ closeReason); + + log.info("Closing session: " + session.getId() + " due to:" + closeReason); RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(session .getId()); if (remoteSession != null) { - String operationId = remoteSession.getOperationId(); + //String operationId = remoteSession.getOperationId(); + String deviceKey = remoteSession.getTenantDomain() + "/" + remoteSession.getDeviceType() + "/" + + remoteSession.getDeviceId(); + RemoteSession lastSession = RemoteSessionManagementDataHolder.getInstance() + .getActiveDeviceClientSessionMap().get(deviceKey); + if (lastSession != null && lastSession.getMySession().getId().equals(session.getId())) { + RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap().remove + (deviceKey); + } if (remoteSession.getPeerSession() != null) { Session peerSession = remoteSession.getPeerSession().getMySession(); if (peerSession != null) { RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(peerSession.getId()); + if (lastSession != null && lastSession.getMySession().getId().equals(peerSession.getId())) { + RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap().remove + (deviceKey); + } if (peerSession.isOpen()) { try { peerSession.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, closeReason)); @@ -298,28 +220,125 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme } } } - if (remoteSession.getMySession() != null) { - Session mySession = remoteSession.getMySession(); - if (mySession.isOpen()) { - try { - mySession.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, closeReason)); - } catch (IOException ex) { - if (log.isDebugEnabled()) { - log.error("Failed to disconnect the client.", ex); - } + } + } + + + /** + * Starting new client session + * + * @param session Web socket Session + * @param tenantDomain Tenant domain + * @param deviceType Device Type + * @param deviceId Device Id + * @throws RemoteSessionManagementException throws when session has errors with accessing device resources + * @throws OperationManagementException throws when error occured during new operation + * @throws InvalidDeviceException throws when incorrect device identifier + */ + private void initializeClientSession(Session session, String tenantDomain, String deviceType, String deviceId) throws RemoteSessionManagementException, + OperationManagementException, InvalidDeviceException { + + RemoteSession clientRemote = new RemoteSession(session, tenantDomain, deviceType, deviceId, RemoteSessionConstants + .CONNECTION_TYPE.CLIENT); + String deviceKey = tenantDomain + "/" + deviceType + "/" + deviceId; + // Create new remote control operation to start the session + RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap + ().putIfAbsent(deviceKey, clientRemote); + if (activeSession != null && activeSession.getMySession().isOpen() && activeSession + .getPeerSession() == null) { + throw new RemoteSessionManagementException("Another client session waiting on device to connect."); + } else { + // if there is pending session exists but already closed, then we need to remove it. + if (activeSession != null) { + RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap().remove + (deviceKey); + try { + activeSession.getMySession().close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "Remote " + + "session closed due to new session request")); + } catch (IOException ex) { + if (log.isDebugEnabled()) { + log.error("Failed to disconnect the client.", ex); } } + // Use put if absent for adding session to waiting list since we need to overcome + // multithreaded session requests. + activeSession = RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap() + .putIfAbsent(deviceKey, clientRemote); + } + // If another client tried to start session same time then active session will be + // exist. So we are adding session request only no parallel sessions added to map + if (activeSession == null) { + + // Create operation if session initiated by client + Operation operation = new ConfigOperation(); + operation.setCode(RemoteSessionConstants.REMOTE_CONNECT); + operation.setEnabled(true); + operation.setControl(Operation.Control.NO_REPEAT); + JSONObject payload = new JSONObject(); + payload.put("serverUrl", RemoteSessionManagementDataHolder.getInstance().getServerUrl()); + operation.setPayLoad(payload.toString()); + String date = new SimpleDateFormat(RemoteSessionConstants.DATE_FORMAT_NOW).format(new Date()); + operation.setCreatedTimeStamp(date); + List deviceIdentifiers = new ArrayList<>(); + deviceIdentifiers.add(new DeviceIdentifier(deviceId, deviceType)); + Activity activity = RemoteSessionManagementDataHolder.getInstance(). + getDeviceManagementProviderService().addOperation(deviceType, operation, deviceIdentifiers); + clientRemote.setOperationId(activity.getActivityId().replace(DeviceManagementConstants + .OperationAttributes.ACTIVITY, "")); + RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session.getId(), clientRemote); + log.info("Client remote session opened for session id: " + session.getId() + " device Type : " + + deviceType + " , " + "deviceId : " + deviceId); + } else { + throw new RemoteSessionManagementException("Another client session waiting on " + + "device to connect."); } - if (operationId != null) { - String deviceIdentifier = remoteSession.getTenantDomain() + "/" + remoteSession - .getDeviceType() + "/" + remoteSession.getDeviceId(); - RemoteSession lastSession = RemoteSessionManagementDataHolder.getInstance() - .getActiveDeviceClientSessionMap().get(deviceIdentifier); - if (lastSession != null && lastSession.getMySession().getId().equals(session.getId())) { - RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap().remove - (deviceIdentifier); + } + } + + /** + * Starting new device session + * + * @param session Web socket Session + * @param tenantDomain Tenant domain + * @param deviceType Device Type + * @param deviceId Device Id + * @param operationId Operation id + * @throws RemoteSessionManagementException throws when session has errors with accessing device resources + */ + private void initializeDeviceSession(Session session, String tenantDomain, String deviceType, String deviceId, + String operationId) throws RemoteSessionManagementException { + String deviceKey = tenantDomain + "/" + deviceType + "/" + deviceId; + RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance() + .getActiveDeviceClientSessionMap().get(deviceKey); + if (activeSession != null) { + RemoteSession clientRemote = RemoteSessionManagementDataHolder.getInstance().getSessionMap().get + (activeSession.getMySession().getId()); + if (clientRemote != null) { + if (clientRemote.getOperationId().equals(operationId)) { + RemoteSession deviceRemote = new RemoteSession(session, tenantDomain, deviceType, deviceId, + RemoteSessionConstants.CONNECTION_TYPE.DEVICE); + deviceRemote.setOperationId(operationId); + deviceRemote.setPeerSession(clientRemote); + clientRemote.setPeerSession(deviceRemote); + RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session.getId(), deviceRemote); + // Send Remote connect response + JSONObject message = new JSONObject(); + message.put(RemoteSessionConstants.REMOTE_CONNECT_CODE, RemoteSessionConstants.REMOTE_CONNECT); + deviceRemote.sendMessageToPeer(message.toString()); + log.info("Device session opened for session id: " + session.getId() + " device Type : " + + deviceType + " , " + "deviceId : " + deviceId); + } else { + throw new RemoteSessionManagementException("Device and Operation information " + + "does not matched with client information for operation id: " + operationId + " device " + + "Type : " + deviceType + " , " + "deviceId : " + deviceId); } + } else { + throw new RemoteSessionManagementException("Device session is inactive for " + "operation id: " + + operationId + " device Type : " + deviceType + " , " + "deviceId : " + deviceId); } + } else { + throw new RemoteSessionManagementException("Device session is inactive for operation " + "id: " + + operationId + " device Type : " + deviceType + " , " + "deviceId : " + deviceId); } } diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/constants/RemoteSessionConstants.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/constants/RemoteSessionConstants.java index 2e899d715..33684eac2 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/constants/RemoteSessionConstants.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/constants/RemoteSessionConstants.java @@ -31,6 +31,10 @@ public class RemoteSessionConstants { public static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss"; public static final int MAX_BUFFER_SIZE = 640 * 1024; + public enum CONNECTION_TYPE { + CLIENT, DEVICE + } + public static final String QUERY_STRING = "queryString"; public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection"; public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost"; diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/dto/RemoteSession.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/dto/RemoteSession.java index fe9292619..5b2337c33 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/dto/RemoteSession.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/src/main/java/org/wso2/carbon/device/mgt/extensions/remote.session/dto/RemoteSession.java @@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.extensions.remote.session.dto; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants; import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException; import org.wso2.carbon.device.mgt.extensions.remote.session.internal.RemoteSessionManagementDataHolder; @@ -41,12 +42,15 @@ public class RemoteSession { private int maxMessagesPerSecond; private int messageAllowance; private double messageRatePerSecond; + private RemoteSessionConstants.CONNECTION_TYPE connectionType; - public RemoteSession(Session session, String tenantDomain, String deviceType, String deviceId) { + public RemoteSession(Session session, String tenantDomain, String deviceType, String deviceId, + RemoteSessionConstants.CONNECTION_TYPE connectionType) { this.mySession = session; this.deviceType = deviceType; this.deviceId = deviceId; this.tenantDomain = tenantDomain; + this.connectionType = connectionType; maxMessagesPerSecond = RemoteSessionManagementDataHolder.getInstance().getMaxMessagesPerSecond(); messageAllowance = maxMessagesPerSecond; messageRatePerSecond = (double) maxMessagesPerSecond / 1000; @@ -136,4 +140,8 @@ public class RemoteSession { public String getDeviceId() { return deviceId; } + + public RemoteSessionConstants.CONNECTION_TYPE getConnectionType() { + return connectionType; + } }