diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/pom.xml b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/pom.xml index df24036b57..a2b67a2933 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/pom.xml +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/pom.xml @@ -23,10 +23,11 @@ org.wso2.carbon.devicemgt-plugins remote-session-extension - 4.0.35-SNAPSHOT + 4.0.54-SNAPSHOT ../pom.xml + 4.0.0 org.wso2.carbon.device.mgt.extensions.remote.session.endpoint war diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/ClientSessionSubscriptionEndpoint.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/ClientSessionSubscriptionEndpoint.java index 61c5dac64e..66ab3e89f1 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/ClientSessionSubscriptionEndpoint.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/ClientSessionSubscriptionEndpoint.java @@ -43,8 +43,6 @@ import java.io.IOException; public class ClientSessionSubscriptionEndpoint extends SubscriptionEndpoint { private static final Log log = LogFactory.getLog(ClientSessionSubscriptionEndpoint.class); - private RemoteSessionConstants.CONNECTION_MODES connectionMode = RemoteSessionConstants.CONNECTION_MODES.CLIENT_MODE; - /** * Web socket onOpen - When client sends a message * diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/DeviceSessionSubscriptionEndpoint.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/DeviceSessionSubscriptionEndpoint.java index 3f2ae343a6..9c771f74d1 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/DeviceSessionSubscriptionEndpoint.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/DeviceSessionSubscriptionEndpoint.java @@ -43,8 +43,6 @@ import java.io.IOException; public class DeviceSessionSubscriptionEndpoint extends SubscriptionEndpoint { private static final Log log = LogFactory.getLog(DeviceSessionSubscriptionEndpoint.class); - private RemoteSessionConstants.CONNECTION_MODES connectionMode = RemoteSessionConstants.CONNECTION_MODES.DEVICE_MODE; - /** * Web socket onOpen - When client sends a message * diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/SubscriptionEndpoint.java b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/SubscriptionEndpoint.java index a6466d313b..53cd4def73 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/SubscriptionEndpoint.java +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session.endpoint/src/main/java/org/wso2/carbon/device/mgt/extensions/remote/session/endpoint/SubscriptionEndpoint.java @@ -108,9 +108,6 @@ public class SubscriptionEndpoint { } try { ServiceHolder.getInstance().getRemoteSessionManagementService().endSession(session); - if (session.isOpen()) { - session.close(new CloseReason(CloseReason.CloseCodes.PROTOCOL_ERROR, "Unexpected Error Occurred")); - } } catch (IOException ex) { if (log.isDebugEnabled()) { log.error("Failed to disconnect the client.", ex); diff --git a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/pom.xml b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/pom.xml index 8545ae269d..a8033555f7 100644 --- a/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/pom.xml +++ b/components/extensions/remote-session-extension/org.wso2.carbon.device.mgt.extensions.remote.session/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.devicemgt-plugins remote-session-extension - 4.0.35-SNAPSHOT + 4.0.54-SNAPSHOT ../pom.xml 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/RemoteSessionManagementService.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/RemoteSessionManagementService.java index c370584ce4..0cff39b89d 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/RemoteSessionManagementService.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/RemoteSessionManagementService.java @@ -21,6 +21,7 @@ import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSess import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException; import javax.websocket.Session; +import java.io.IOException; /** * Class @{@link RemoteSessionManagementService} use for managing remote sessions @@ -40,7 +41,7 @@ public interface RemoteSessionManagementService { RemoteSessionInvalidException, RemoteSessionManagementException; /** - * Initialize session based on web socket request .this method use by the device to connect + * Initialize session based on web socket request . This method use by the device to connect * * @param session Web socket RemoteSession * @param deviceType Device Type @@ -79,6 +80,6 @@ public interface RemoteSessionManagementService { * * @param session Web socket RemoteSession */ - public void endSession(Session session); + public void endSession(Session session) throws IOException; } 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 9fe986580d..437452ae7d 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 @@ -33,13 +33,16 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.ConfigOperation; import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.AuthenticationInfo; import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.OAuthAuthenticator; import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants; -import org.wso2.carbon.device.mgt.extensions.remote.session.dto.RemoteSession; +import org.wso2.carbon.device.mgt.extensions.remote.session.dto.ClientSession; +import org.wso2.carbon.device.mgt.extensions.remote.session.dto.DeviceSession; +import org.wso2.carbon.device.mgt.extensions.remote.session.dto.common.RemoteSession; import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionInvalidException; import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException; import org.wso2.carbon.device.mgt.extensions.remote.session.internal.RemoteSessionManagementDataHolder; import javax.websocket.CloseReason; import javax.websocket.Session; +import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -69,6 +72,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme List sessionQueryParamList = new LinkedList<>(); sessionQueryParamList.add(session.getQueryString()); sessionQueryParam.put(RemoteSessionConstants.QUERY_STRING, sessionQueryParamList); + // Validate the token OAuthAuthenticator oAuthAuthenticator = RemoteSessionManagementDataHolder.getInstance().getOauthAuthenticator(); AuthenticationInfo authenticationInfo = oAuthAuthenticator.isAuthenticated(sessionQueryParam); @@ -84,12 +88,19 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); deviceIdentifier.setId(deviceId); deviceIdentifier.setType(deviceType); + // Check authorization for user boolean userAuthorized = RemoteSessionManagementDataHolder.getInstance() .getDeviceAccessAuthorizationService() .isUserAuthorized(deviceIdentifier, authenticationInfo.getUsername()); if (userAuthorized) { log.info("Operation ID: " + operationId); + // set common settings for session + session.setMaxBinaryMessageBufferSize(MAX_BUFFER_SIZE); + session.setMaxTextMessageBufferSize(MAX_BUFFER_SIZE); + session.setMaxIdleTimeout(RemoteSessionManagementDataHolder.getInstance().getMaxIdleTimeout()); + + // if session initiated using operatiod id means request came from device if (operationId != null) { Session pendingSession = RemoteSessionManagementDataHolder.getInstance() .getDeviceRequestMap().get((authenticationInfo.getTenantDomain() + "/" + deviceType @@ -101,11 +112,10 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme if (clientRemote != null) { if (clientRemote.getOperationId().equals(operationId)) { - RemoteSession deviceRemote = new RemoteSession(authenticationInfo.getTenantDomain - (), deviceType, deviceId, operationId, RemoteSessionConstants - .CONNECTION_MODES.DEVICE_MODE); - deviceRemote.setPeerSession(pendingSession); - clientRemote.setPeerSession(session); + RemoteSession deviceRemote = new DeviceSession(session, authenticationInfo + .getTenantDomain(), deviceType, deviceId, operationId); + deviceRemote.setPeerSession(clientRemote); + clientRemote.setPeerSession(deviceRemote); RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session .getId(), deviceRemote); RemoteSessionManagementDataHolder.getInstance().getDeviceRequestMap().remove( @@ -115,9 +125,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme message.put("code", RemoteSessionConstants.REMOTE_CONNECT); message.put("operation_response", "connected"); deviceRemote.sendMessageToPeer(message.toString()); - // set buffer sizes - session.setMaxBinaryMessageBufferSize(MAX_BUFFER_SIZE); - session.setMaxTextMessageBufferSize(MAX_BUFFER_SIZE); + } else { throw new RemoteSessionManagementException("Device and Operation information does" + " not matched with client information for operation id: " + operationId + @@ -136,6 +144,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme "id: " + operationId + " device Type : " + deviceType + " , " + "deviceId : " + deviceId); } + } else { // Create new remote control operation to start the session Session pendingSession = RemoteSessionManagementDataHolder.getInstance().getDeviceRequestMap().get( @@ -148,27 +157,29 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme session); if (lastSession == 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(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); log.info("Activity id: " + activity.getActivityId()); - RemoteSession clientRemote = new RemoteSession(authenticationInfo.getTenantDomain(), - deviceType, deviceId, activity.getActivityId().replace(DeviceManagementConstants - .OperationAttributes.ACTIVITY, ""), RemoteSessionConstants - .CONNECTION_MODES.CLIENT_MODE); + + RemoteSession clientRemote = new ClientSession(session, authenticationInfo + .getTenantDomain(), deviceType, deviceId, activity.getActivityId().replace(DeviceManagementConstants + .OperationAttributes.ACTIVITY, "")); RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session.getId(), clientRemote); - session.setMaxBinaryMessageBufferSize(MAX_BUFFER_SIZE); - session.setMaxTextMessageBufferSize(MAX_BUFFER_SIZE); } } } @@ -209,7 +220,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme * Implements the behaviour of sending message to peer connection * * @param session Web socket RemoteSession - * @param message Message needs to send to peer connection + * @param message String message needs to send to peer connection * @throws RemoteSessionInvalidException throws when session cannot be made due to invalid data * @throws RemoteSessionManagementException throws when session has error with accessing device resources */ @@ -219,7 +230,7 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme JSONObject jsonObject = new JSONObject(message); RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().get(session.getId()); if (remoteSession != null) { - if (remoteSession.getConnection_mode().equals(RemoteSessionConstants.CONNECTION_MODES.CLIENT_MODE)) { + if (remoteSession instanceof ClientSession) { jsonObject.put("id", remoteSession.getOperationId()); } remoteSession.sendMessageToPeer(jsonObject.toString()); @@ -230,6 +241,14 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme } + /** + * Implements the behaviour of sending message to peer connection + * + * @param session Web socket RemoteSession + * @param message Byte message needs to send to peer connection + * @throws RemoteSessionInvalidException throws when session cannot be made due to invalid data + * @throws RemoteSessionManagementException throws when session has error with accessing device resources + */ @Override public void sendMessageToPeer(Session session, byte[] message) throws RemoteSessionInvalidException, RemoteSessionManagementException { @@ -249,14 +268,17 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme * @param session Web socket RemoteSession */ @Override - public void endSession(Session session) { + public void endSession(Session session) throws IOException { RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(session.getId()); if (remoteSession != null) { String operationId = remoteSession.getOperationId(); - Session peerSession = remoteSession.getPeerSession(); + Session peerSession = remoteSession.getPeerSession().getMySession(); if (peerSession != null) { RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(peerSession.getId()); + if (peerSession.isOpen()) { + peerSession.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "Remote session closed")); + } } if (operationId != null) { Session lastSession = RemoteSessionManagementDataHolder.getInstance().getDeviceRequestMap().get( 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/authentication/OAuthAuthenticator.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/authentication/OAuthAuthenticator.java index ca51bc157d..689dd159c9 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/authentication/OAuthAuthenticator.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/authentication/OAuthAuthenticator.java @@ -20,6 +20,9 @@ import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.oauth import java.util.List; import java.util.Map; +/** + * {@link OAuthAuthenticator} for validate tokens to web socket api + */ public class OAuthAuthenticator { OAuthTokenValidator oAuthTokenValidator; 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 693d26d353..15f9141d52 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 @@ -24,24 +24,18 @@ package org.wso2.carbon.device.mgt.extensions.remote.session.constants; public class RemoteSessionConstants { public static final String SCOPE_IDENTIFIER = "scopes"; - public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection"; - public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost"; public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationUrl"; public static final String TOKEN_VALIDATION_CONTEX = "/services/OAuth2TokenValidationService"; public static final String USERNAME = "username"; public static final String PASSWORD = "password"; - public static final String DEVICE_ID = "deviceId"; - public static final String DEVICE_TYPE = "deviceType"; public static final String REMOTE_CONNECT = "REMOTE_CONNECT"; + public static final String THROTTLE_OUT = "THROTTLE_OUT"; public static final String QUERY_STRING = "queryString"; - public static final String OPERATION_CODE = "operation_code"; - public static final String REMOTE_SESSION_DEVICE_ENDPOINT_CONTEXT = "/remote/session/devices"; - - // Constants for remote session Connection modes + public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection"; + public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost"; + public static final String DEFAULT_MAXIMUM_HTTP_CONNECTION_PER_HOST = "2"; + public static final String DEFAULT_MAXIMUM_TOTAL_HTTP_CONNECTIONS = "100"; - public enum CONNECTION_MODES { - CLIENT_MODE, DEVICE_MODE - } private RemoteSessionConstants() { } 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/ClientSession.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/ClientSession.java new file mode 100644 index 0000000000..70253479be --- /dev/null +++ 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/ClientSession.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.device.mgt.extensions.remote.session.dto; + +import org.wso2.carbon.device.mgt.extensions.remote.session.dto.common.RemoteSession; + +import javax.websocket.Session; + +/** + * {@link ClientSession} is the represent of client which will be connecting to the device + */ +public class ClientSession extends RemoteSession { + + + public ClientSession(Session session, String tenantDomain, String deviceType, String deviceId, String operationId) { + super(session, tenantDomain, deviceType, deviceId, operationId); + } + + + @Override + public boolean applyThrottlingPolicy() { + return false; + } +} 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/DeviceSession.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/DeviceSession.java new file mode 100644 index 0000000000..5e88dc0d9f --- /dev/null +++ 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/DeviceSession.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.device.mgt.extensions.remote.session.dto; + +import org.wso2.carbon.device.mgt.extensions.remote.session.dto.common.RemoteSession; +import org.wso2.carbon.device.mgt.extensions.remote.session.internal.RemoteSessionManagementDataHolder; + +import javax.websocket.Session; + +/** + * {@link DeviceSession} is the represent of device which will be connecting based on client request + */ +public class DeviceSession extends RemoteSession { + + + public DeviceSession(Session session, String tenantDomain, String deviceType, String deviceId, String operationId) { + super(session, tenantDomain, deviceType, deviceId, operationId); + } + + + @Override + public boolean applyThrottlingPolicy() { + if (RemoteSessionManagementDataHolder.getInstance().getMessagesPerSession() > 0) { + long minDurationMessagesPerSecond = 1000 / RemoteSessionManagementDataHolder.getInstance() + .getMessagesPerSession(); + if ((System.currentTimeMillis() - getLastMessageTimeStamp()) < minDurationMessagesPerSecond) { + return true; + } + } + return false; + } +} 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 deleted file mode 100644 index 7a351565bc..0000000000 --- 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 +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -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.RemoteSessionInvalidException; - -import javax.websocket.CloseReason; -import javax.websocket.Session; -import java.io.IOException; -import java.nio.ByteBuffer; - -public class RemoteSession { - - private static final Log log = LogFactory.getLog(RemoteSession.class); - private String tenantDomain, operationId, deviceType, deviceId; - private Session peerSession; - private RemoteSessionConstants.CONNECTION_MODES connection_mode; - private final Object writeLockObject = new Object(); - - - public RemoteSession(String tenantDomain, String deviceType, String deviceId, String operationId, RemoteSessionConstants.CONNECTION_MODES connection_mode) { - this.deviceType = deviceType; - this.deviceId = deviceId; - this.tenantDomain = tenantDomain; - this.operationId = operationId; - this.connection_mode = connection_mode; - } - - public void sendMessageToPeer(String message) throws RemoteSessionInvalidException { - if (peerSession != null && peerSession.isOpen()) { - synchronized (writeLockObject) { - try { - peerSession.getBasicRemote().sendText(message); - } catch (IOException e) { - log.warn("Send data to session failed due to ", e); - } - } - } else { - throw new RemoteSessionInvalidException("Peer Session already closed ", new CloseReason - (CloseReason.CloseCodes.CANNOT_ACCEPT, "Peer Session already closed ")); - } - } - - public void sendMessageToPeer(byte[] message) throws RemoteSessionInvalidException { - - if (peerSession != null && peerSession.isOpen()) { - synchronized (writeLockObject) { - try { - peerSession.getBasicRemote().sendBinary(ByteBuffer.wrap(message)); - } catch (IOException e) { - log.warn("Send data to session failed due to ", e); - } - } - } else { - throw new RemoteSessionInvalidException("Peer Session already closed ", new CloseReason - (CloseReason.CloseCodes.CANNOT_ACCEPT, "Peer Session already closed ")); - } - } - - public Session getPeerSession() { - return peerSession; - } - - public void setPeerSession(Session peerSession) { - this.peerSession = peerSession; - } - - public String getTenantDomain() { - return tenantDomain; - } - - public void setTenantDomain(String tenantDomain) { - this.tenantDomain = tenantDomain; - } - - public String getOperationId() { - return operationId; - } - - public void setOperationId(String operationId) { - this.operationId = operationId; - } - - public String getDeviceType() { - return deviceType; - } - - public void setDeviceType(String deviceType) { - this.deviceType = deviceType; - } - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public RemoteSessionConstants.CONNECTION_MODES getConnection_mode() { - return connection_mode; - } - - public void setConnection_mode(RemoteSessionConstants.CONNECTION_MODES connection_mode) { - this.connection_mode = connection_mode; - } -} 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/common/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/common/RemoteSession.java new file mode 100644 index 0000000000..cffea29e09 --- /dev/null +++ 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/common/RemoteSession.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.device.mgt.extensions.remote.session.dto.common; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONObject; +import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants; +import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionInvalidException; +import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException; + +import javax.websocket.CloseReason; +import javax.websocket.Session; +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * {@link RemoteSession} will represent remote websocket session + * This class implements the behaviours of sending message to the session in multithreaded environment. + * + */ +public abstract class RemoteSession { + + private static final Log log = LogFactory.getLog(RemoteSession.class); + private String tenantDomain, operationId, deviceType, deviceId; + private long lastMessageTimeStamp = System.currentTimeMillis(); + ; + private RemoteSession peerSession; + private Session mySession; + private final Object writeLockObject = new Object(); + + protected RemoteSession(Session session, String tenantDomain, String deviceType, String deviceId, String + operationId) { + this.mySession = session; + this.deviceType = deviceType; + this.deviceId = deviceId; + this.tenantDomain = tenantDomain; + this.operationId = operationId; + } + + public void sendMessage(Object message) throws RemoteSessionInvalidException, RemoteSessionManagementException { + + if (message != null) { + boolean isMessageCountExceed = false; + if (mySession != null && mySession.isOpen()) { + synchronized (writeLockObject) { + try { + isMessageCountExceed = applyThrottlingPolicy(); + if (!isMessageCountExceed) { + if (message instanceof String) { + mySession.getBasicRemote().sendText(message.toString()); + } else { + mySession.getBasicRemote().sendBinary(ByteBuffer.wrap((byte[]) message)); + } + this.lastMessageTimeStamp = System.currentTimeMillis(); + } + } catch (IOException e) { + log.warn("Send data to session failed due to ", e); + } + } + } else { + throw new RemoteSessionInvalidException("Peer Session already closed ", new CloseReason + (CloseReason.CloseCodes.CANNOT_ACCEPT, "Peer Session already closed ")); + } + + if (isMessageCountExceed) { + JSONObject response = new JSONObject(); + response.put("code", RemoteSessionConstants.THROTTLE_OUT); + sendMessageToPeer(message.toString()); + } + } else { + throw new RemoteSessionManagementException("Message is empty"); + } + } + + public void sendMessageToPeer(Object message) throws RemoteSessionInvalidException, RemoteSessionManagementException { + peerSession.sendMessage(message); + } + + + public abstract boolean applyThrottlingPolicy(); + + + public Session getMySession() { + return mySession; + } + + public void setMySession(Session mySession) { + this.mySession = mySession; + } + + public RemoteSession getPeerSession() { + return peerSession; + } + + public void setPeerSession(RemoteSession peerSession) { + this.peerSession = peerSession; + } + + public String getTenantDomain() { + return tenantDomain; + } + + public void setTenantDomain(String tenantDomain) { + this.tenantDomain = tenantDomain; + } + + public String getOperationId() { + return operationId; + } + + public void setOperationId(String operationId) { + this.operationId = operationId; + } + + public String getDeviceType() { + return deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public long getLastMessageTimeStamp() { + return lastMessageTimeStamp; + } + + public void setLastMessageTimeStamp(long lastMessageTimeStamp) { + this.lastMessageTimeStamp = lastMessageTimeStamp; + } +} 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/internal/RemoteSessionManagementDataHolder.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/internal/RemoteSessionManagementDataHolder.java index 825ddc5cf4..c015e50e0a 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/internal/RemoteSessionManagementDataHolder.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/internal/RemoteSessionManagementDataHolder.java @@ -19,10 +19,9 @@ package org.wso2.carbon.device.mgt.extensions.remote.session.internal; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; -import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.OAuthAuthenticator; -import org.wso2.carbon.device.mgt.extensions.remote.session.dto.RemoteSession; +import org.wso2.carbon.device.mgt.extensions.remote.session.dto.common.RemoteSession; import javax.websocket.Session; import java.util.Map; @@ -35,6 +34,8 @@ public class RemoteSessionManagementDataHolder { private DeviceAccessAuthorizationService deviceAccessAuthorizationService; private boolean isEnabled; private String serverUrl; + private long maxIdleTimeout; + private int messagesPerSession; private OAuthAuthenticator oAuthAuthenticator; private Map deviceRequestMap = new ConcurrentHashMap(); private Map sessionMap = new ConcurrentHashMap(); @@ -98,4 +99,20 @@ public class RemoteSessionManagementDataHolder { public void setServerUrl(String serverUrl) { this.serverUrl = serverUrl; } + + public int getMessagesPerSession() { + return messagesPerSession; + } + + public void setMessagesPerSession(int messagesPerSession) { + this.messagesPerSession = messagesPerSession; + } + + public long getMaxIdleTimeout() { + return maxIdleTimeout; + } + + public void setMaxIdleTimeout(long maxIdleTimeout) { + this.maxIdleTimeout = maxIdleTimeout; + } } 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/listener/RemoteSessionManagerStartupListener.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/listener/RemoteSessionManagerStartupListener.java index 97339b3b38..a02b945ee4 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/listener/RemoteSessionManagerStartupListener.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/listener/RemoteSessionManagerStartupListener.java @@ -23,7 +23,8 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.ServerStartupObserver; import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; - +import org.wso2.carbon.device.mgt.core.config.keymanager.KeyManagerConfigurations; +import org.wso2.carbon.device.mgt.core.config.remote.session.RemoteSessionConfiguration; import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.OAuthAuthenticator; import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants; import org.wso2.carbon.device.mgt.extensions.remote.session.internal.RemoteSessionManagementDataHolder; @@ -33,8 +34,9 @@ import java.util.HashMap; import java.util.Map; /** - * Startup listener is been used to make sure the reciever gets activated after the server start up to avoid + * Startup listener is been used to make sure the receiver gets activated after the server start up to avoid * Bundle not loading issues. + * This will configure the values for remote session management */ public class RemoteSessionManagerStartupListener implements ServerStartupObserver { @@ -50,18 +52,41 @@ public class RemoteSessionManagerStartupListener implements ServerStartupObserve PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain( MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true); try { + RemoteSessionConfiguration rsConfig = DeviceConfigurationManager.getInstance().getDeviceManagementConfig + ().getRemoteSessionConfiguration(); + KeyManagerConfigurations kmConfig = DeviceConfigurationManager.getInstance().getDeviceManagementConfig() + .getKeyManagerConfigurations(); - RemoteSessionManagementDataHolder.getInstance().setEnabled(DeviceConfigurationManager.getInstance() - .getDeviceManagementConfig().getRemoteSessionConfiguration().getIsEnabled()); - RemoteSessionManagementDataHolder.getInstance().setServerUrl(DeviceConfigurationManager.getInstance() - .getDeviceManagementConfig().getRemoteSessionConfiguration().getRemoteSessionServerUrl()); + RemoteSessionManagementDataHolder.getInstance().setEnabled(rsConfig.isEnabled()); + RemoteSessionManagementDataHolder.getInstance().setServerUrl(rsConfig.getRemoteSessionServerUrl()); Map configProperties = new HashMap<>(); - configProperties.put(RemoteSessionConstants.TOKEN_VALIDATION_ENDPOINT_URL, "https://localhost:9443"); - configProperties.put(RemoteSessionConstants.USERNAME,"admin"); - configProperties.put(RemoteSessionConstants.PASSWORD,"admin"); - configProperties.put(RemoteSessionConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST,"2"); - configProperties.put(RemoteSessionConstants.MAXIMUM_TOTAL_HTTP_CONNECTION,"100"); - OAuthAuthenticator oAuthAuthenticator= new OAuthAuthenticator(); + + // Set max idle timeout in milliseconds + RemoteSessionManagementDataHolder.getInstance().setMaxIdleTimeout(rsConfig.getSessionIdleTimeOut()*60000); + + // Set max messages per second. + RemoteSessionManagementDataHolder.getInstance().setMessagesPerSession(rsConfig.getMaxMessagesPerSession()); + // Token validation related configuration + configProperties.put(RemoteSessionConstants.TOKEN_VALIDATION_ENDPOINT_URL, kmConfig.getServerUrl()); + configProperties.put(RemoteSessionConstants.USERNAME, kmConfig.getAdminUsername()); + configProperties.put(RemoteSessionConstants.PASSWORD, kmConfig.getAdminPassword()); + if (rsConfig.getMaxHTTPConnectionPerHost() > 0) { + + configProperties.put(RemoteSessionConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST, + String.valueOf(rsConfig.getMaxHTTPConnectionPerHost())); + } else { + configProperties.put(RemoteSessionConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST, RemoteSessionConstants + .DEFAULT_MAXIMUM_HTTP_CONNECTION_PER_HOST); + } + if (rsConfig.getMaxTotalHTTPConnections() > 0) { + configProperties.put(RemoteSessionConstants.MAXIMUM_TOTAL_HTTP_CONNECTION, String.valueOf(rsConfig + .getMaxTotalHTTPConnections())); + } else { + configProperties.put(RemoteSessionConstants.MAXIMUM_TOTAL_HTTP_CONNECTION, RemoteSessionConstants + .DEFAULT_MAXIMUM_TOTAL_HTTP_CONNECTIONS); + } + + OAuthAuthenticator oAuthAuthenticator = new OAuthAuthenticator(); oAuthAuthenticator.init(configProperties); RemoteSessionManagementDataHolder.getInstance().setOauthAuthenticator(oAuthAuthenticator); diff --git a/components/extensions/remote-session-extension/pom.xml b/components/extensions/remote-session-extension/pom.xml index 50cc9cdbf9..42b540708b 100644 --- a/components/extensions/remote-session-extension/pom.xml +++ b/components/extensions/remote-session-extension/pom.xml @@ -22,7 +22,7 @@ org.wso2.carbon.devicemgt-plugins extensions - 4.0.35-SNAPSHOT + 4.0.54-SNAPSHOT ../pom.xml diff --git a/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml index 44abb04940..728ba09e28 100644 --- a/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml +++ b/features/extensions-feature/org.wso2.carbon.device.mgt.remote.session.feature/pom.xml @@ -3,14 +3,14 @@ org.wso2.carbon.devicemgt-plugins extensions-feature - 4.0.35-SNAPSHOT + 4.0.54-SNAPSHOT ../pom.xml 4.0.0 org.wso2.carbon.device.mgt.remote.session.feature pom - 4.0.35-SNAPSHOT + 4.0.54-SNAPSHOT WSO2 Carbon - Remote Session Manager http://wso2.org This feature contains the core bundles required iot Remote Sessions @@ -55,7 +55,7 @@ ${project.build.directory}/maven-shared-archive-resources/webapps/ - remote-session.war + remote#session.war