Merge branch 'remote-control' of https://github.com/warunalakshitha/carbon-device-mgt-plugins
commit
671a36e849
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<artifactId>remote-session-extension</artifactId>
|
||||
<version>4.0.88-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session.endpoint</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>WSO2 - Webapp for UI Remote Session</name>
|
||||
<url>http://wso2.org</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-websocket-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json.wso2</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>remote#session</finalName>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* deviceId 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.endpoint;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.HttpSessionConfigurator;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.ServiceHolder;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.OnClose;
|
||||
import javax.websocket.OnError;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class represents web socket endpoint to manage Remote Sessions
|
||||
*/
|
||||
@ServerEndpoint(value = "/clients/{deviceType}/{deviceId}", configurator = HttpSessionConfigurator.class)
|
||||
public class ClientSessionSubscriptionEndpoint extends SubscriptionEndpoint {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ClientSessionSubscriptionEndpoint.class);
|
||||
|
||||
/**
|
||||
* Web socket onOpen use when client connect to web socket url
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("deviceType") String deviceType, @PathParam("deviceId") String
|
||||
deviceId) {
|
||||
try {
|
||||
ServiceHolder.getInstance().getRemoteSessionManagementService().initializeSession(session, deviceType,
|
||||
deviceId);
|
||||
} catch (RemoteSessionManagementException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error("Error occurred while initializing session ", e);
|
||||
}
|
||||
try {
|
||||
session.close(e.getCloseReason());
|
||||
} catch (IOException ex) {
|
||||
log.error("Failed to disconnect the client.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onMessage use when client sends a string message
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(Session session, String message, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
super.onMessage(session, message, deviceType, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onMessage use when client sends a byte message
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
* @param message - Byte message which needs to send to peer
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(Session session, byte[] message, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
super.onMessage(session, message, deviceType, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onClose use to handle socket connection close
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
* @param reason - Status code for web-socket close.
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose(Session session, CloseReason reason, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
super.onClose(session, reason, deviceType, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onError use to handle socket connection error
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param throwable - Web socket exception
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
*/
|
||||
@OnError
|
||||
public void onError(Session session, Throwable throwable, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
super.onError(session, throwable, deviceType, deviceId);
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* deviceId 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.endpoint;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.HttpSessionConfigurator;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.ServiceHolder;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.OnClose;
|
||||
import javax.websocket.OnError;
|
||||
import javax.websocket.OnMessage;
|
||||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class represents web socket endpoint to manage Remote Sessions
|
||||
*/
|
||||
@ServerEndpoint(value = "/devices/{deviceType}/{deviceId}/{operationId}", configurator = HttpSessionConfigurator.class)
|
||||
public class DeviceSessionSubscriptionEndpoint extends SubscriptionEndpoint {
|
||||
|
||||
private static final Log log = LogFactory.getLog(DeviceSessionSubscriptionEndpoint.class);
|
||||
|
||||
/**
|
||||
* Web socket onOpen use when device connect to web socket url
|
||||
*
|
||||
* @param session - Web socket Session
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
* @param operationId - Operations Id
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("deviceType") String deviceType, @PathParam("deviceId") String
|
||||
deviceId, @PathParam("operationId") String operationId) {
|
||||
try {
|
||||
ServiceHolder.getInstance().getRemoteSessionManagementService().initializeSession(session, deviceType,
|
||||
deviceId, operationId);
|
||||
} catch (RemoteSessionManagementException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error("Error occurred while initializing session ", e);
|
||||
}
|
||||
try {
|
||||
session.close(e.getCloseReason());
|
||||
} catch (IOException ex) {
|
||||
log.error("Failed to disconnect the client.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onMessage use when device sends a string message
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param message - String message which needs to send to peer
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(Session session, String message, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
super.onMessage(session, message, deviceType, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onMessage use when device sends a byte message
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param message - Byte message which needs to send to peer
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(Session session, byte[] message, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
super.onMessage(session, message, deviceType, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onClose use to handle socket connection close
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
* @param reason - Status code for web-socket close.
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose(Session session, CloseReason reason, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
super.onClose(session, reason, deviceType, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onError use to handle socket connection error
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param throwable - Web socket exception
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
*/
|
||||
@OnError
|
||||
public void onError(Session session, Throwable throwable, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
super.onError(session, throwable, deviceType, deviceId);
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* deviceId 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.endpoint;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.utils.ServiceHolder;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.Session;
|
||||
import javax.websocket.server.PathParam;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class represents common web socket endpoint to manage Remote Sessions
|
||||
*/
|
||||
public class SubscriptionEndpoint {
|
||||
|
||||
private static final Log log = LogFactory.getLog(SubscriptionEndpoint.class);
|
||||
|
||||
/**
|
||||
* Web socket onMessage - When client sends a message
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param deviceType - DeviceType
|
||||
* @param message - String Message which needs to send to peer
|
||||
*/
|
||||
public void onMessage(Session session, String message, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Received message from client for RemoteSession id: " + session.getId() + " device type: " +
|
||||
deviceType + " device id: " + deviceId);
|
||||
}
|
||||
try {
|
||||
ServiceHolder.getInstance().getRemoteSessionManagementService().sendMessageToPeer(session, message);
|
||||
} catch (RemoteSessionManagementException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error("Error occurred while send message to peer session ", e);
|
||||
}
|
||||
try {
|
||||
session.close(e.getCloseReason());
|
||||
} catch (IOException ex) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error("Failed to disconnect the client.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onMessage use When client sends a message
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
* @param message - Byte Message which needs to send to peer
|
||||
*/
|
||||
public void onMessage(Session session, byte[] message, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Received message from client for RemoteSession id: " + session.getId() + " device type: " +
|
||||
deviceType + " device id: " + deviceId);
|
||||
}
|
||||
try {
|
||||
ServiceHolder.getInstance().getRemoteSessionManagementService().sendMessageToPeer(session, message);
|
||||
} catch (RemoteSessionManagementException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error("Error occurred while send message to peer session ", e);
|
||||
}
|
||||
try {
|
||||
session.close(e.getCloseReason());
|
||||
} catch (IOException ex) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error("Failed to disconnect the client.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onClose use to handle socket connection close
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
* @param reason - Status code for web-socket close.
|
||||
*/
|
||||
public void onClose(Session session, CloseReason reason, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
|
||||
ServiceHolder.getInstance().getRemoteSessionManagementService().endSession(session, "Remote session closed");
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("websocket closed due to " + reason.getReasonPhrase() + ", for session ID:" + session.getId
|
||||
() + ", for request URI - " + session.getRequestURI() + " device type: " + deviceType + " device " +
|
||||
"id: " + deviceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Web socket onError use to handle socket connection error
|
||||
*
|
||||
* @param session - Registered session.
|
||||
* @param throwable - Web socket exception
|
||||
* @param deviceType - DeviceType
|
||||
* @param deviceId - Device Identifier
|
||||
*/
|
||||
public void onError(Session session, Throwable throwable, @PathParam("deviceType") String deviceType, @PathParam
|
||||
("deviceId") String deviceId) {
|
||||
|
||||
if (throwable instanceof IOException) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error("Error occurred in session ID: " + session.getId() + " device type: " + deviceType +
|
||||
"device id: " + deviceId + ", for request URI - " + session.getRequestURI() +
|
||||
", " + throwable.getMessage(), throwable);
|
||||
}
|
||||
} else {
|
||||
log.error("Error occurred in session ID: " + session.getId() + " device type: " + deviceType + " device " +
|
||||
"id: " + deviceId + ", for request URI - " + session.getRequestURI() + ", " + throwable.getMessage
|
||||
(), throwable);
|
||||
}
|
||||
try {
|
||||
ServiceHolder.getInstance().getRemoteSessionManagementService().endSession(session, "Remote session closed");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
*
|
||||
* 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.endpoint.constants;
|
||||
|
||||
/**
|
||||
* This holds the constants related to remote session web socket endpoint
|
||||
*/
|
||||
public class Constants {
|
||||
public static final String HTTP_HEADERS = "HttpHeaders";
|
||||
|
||||
private Constants() {
|
||||
}
|
||||
}
|
@ -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.endpoint.utils;
|
||||
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.endpoint.constants.Constants;
|
||||
|
||||
import javax.websocket.HandshakeResponse;
|
||||
import javax.websocket.server.HandshakeRequest;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class for handle HTTP session
|
||||
*/
|
||||
public class HttpSessionConfigurator extends ServerEndpointConfig.Configurator {
|
||||
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
|
||||
Map<String, List<String>> httpHeaders = request.getHeaders();
|
||||
config.getUserProperties().put(Constants.HTTP_HEADERS, httpHeaders);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.endpoint.utils;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.RemoteSessionManagementService;
|
||||
|
||||
/**
|
||||
* Class for store remote management service instances
|
||||
*/
|
||||
public class ServiceHolder {
|
||||
|
||||
private static ServiceHolder instance;
|
||||
private static final Log log = LogFactory.getLog(ServiceHolder.class);
|
||||
|
||||
private ServiceHolder() {
|
||||
}
|
||||
|
||||
public synchronized static ServiceHolder getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ServiceHolder();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public RemoteSessionManagementService getRemoteSessionManagementService() {
|
||||
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||
RemoteSessionManagementService RemoteSessionManagementService =
|
||||
(RemoteSessionManagementService) ctx.getOSGiService(RemoteSessionManagementService.class, null);
|
||||
if (RemoteSessionManagementService == null) {
|
||||
String msg = "Remote Session Management service has not initialized.";
|
||||
log.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
return RemoteSessionManagementService;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<!DOCTYPE web-app PUBLIC
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtd/web-app_2_3.dtd" >
|
||||
|
||||
<web-app>
|
||||
<display-name>Remote Session</display-name>
|
||||
<filter>
|
||||
<filter-name>HttpHeaderSecurityFilter</filter-name>
|
||||
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
|
||||
<init-param>
|
||||
<param-name>hstsEnabled</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter>
|
||||
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
|
||||
<filter-class>org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter</filter-class>
|
||||
<init-param>
|
||||
<param-name>patterns</param-name>
|
||||
<param-value>text/html" ,application/json" ,text/plain</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>filterAction</param-name>
|
||||
<param-value>enforce</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>httpHeaders</param-name>
|
||||
<param-value>Cache-Control: no-store, no-cache, must-revalidate, private</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>HttpHeaderSecurityFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
</web-app>
|
@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<artifactId>remote-session-extension</artifactId>
|
||||
<version>4.0.88-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>WSO2 Carbon - Remote Session Manager Implementation</name>
|
||||
<description>WSO2 Carbon - Remote Session Manager Implementation</description>
|
||||
<url>http://wso2.org</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.wso2.carbon</groupId>
|
||||
<artifactId>org.wso2.carbon.logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wso2.carbon</groupId>
|
||||
<artifactId>org.wso2.carbon.core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.websocket</groupId>
|
||||
<artifactId>javax.websocket-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.wso2</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wso2.orbit.org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wso2.carbon.identity.inbound.auth.oauth2</groupId>
|
||||
<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-pool.wso2</groupId>
|
||||
<artifactId>commons-pool</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json.wso2</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</dependency>
|
||||
<!--dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-testng</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency-->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-scr-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||
<Bundle-Name>${project.artifactId}</Bundle-Name>
|
||||
<Bundle-Version>${carbon.devicemgt.plugins.version}</Bundle-Version>
|
||||
<Bundle-Description>Remote Session Manager Bundle</Bundle-Description>
|
||||
<Export-Package>
|
||||
!org.wso2.carbon.device.mgt.extensions.remote.session.internal,
|
||||
org.wso2.carbon.device.mgt.extensions.remote.session.*
|
||||
</Export-Package>
|
||||
<Import-Package>
|
||||
*;resolution:=optional
|
||||
</Import-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<log4j.configuration>file:src/test/resources/log4j.properties</log4j.configuration>
|
||||
</systemPropertyVariables>
|
||||
<suiteXmlFiles>
|
||||
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
|
||||
</suiteXmlFiles>
|
||||
</configuration>
|
||||
</plugin-->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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
|
||||
*/
|
||||
public interface RemoteSessionManagementService {
|
||||
|
||||
/**
|
||||
* Initialize session based on web socket request .This method is used by the device to connect
|
||||
*
|
||||
* @param session Web socket RemoteSession
|
||||
* @param deviceType Device Type
|
||||
* @param deviceId Device Id
|
||||
* @throws RemoteSessionManagementException throws when session has errors with accessing device resources
|
||||
*/
|
||||
void initializeSession(Session session, String deviceType, String deviceId) throws
|
||||
RemoteSessionManagementException;
|
||||
|
||||
/**
|
||||
* Initialize session based on web socket request . This method is used by the device to connect
|
||||
*
|
||||
* @param session Web socket RemoteSession
|
||||
* @param deviceType Device Type
|
||||
* @param deviceId Device Id
|
||||
* @param operationId Operation Id that device needs to connec
|
||||
* @throws RemoteSessionManagementException throws when session has errors with accessing device resources
|
||||
*/
|
||||
void initializeSession(Session session, String deviceType, String deviceId, String operationId) throws
|
||||
RemoteSessionManagementException;
|
||||
|
||||
/**
|
||||
* Send string message to connected remote device or client
|
||||
*
|
||||
* @param session Web socket RemoteSession
|
||||
* @param message Message needs to send to peer connection client
|
||||
* @throws RemoteSessionManagementException
|
||||
*/
|
||||
void sendMessageToPeer(Session session, String message) throws RemoteSessionManagementException;
|
||||
|
||||
/**
|
||||
* Send byte message to connected remote device or client
|
||||
*
|
||||
* @param session Web socket RemoteSession
|
||||
* @param message Message needs to send to peer connection
|
||||
* @throws RemoteSessionManagementException
|
||||
*/
|
||||
void sendMessageToPeer(Session session, byte[] message) throws RemoteSessionManagementException;
|
||||
|
||||
/**
|
||||
* Close the session
|
||||
*
|
||||
* @param session Web socket RemoteSession
|
||||
*/
|
||||
void endSession(Session session, String closeReason);
|
||||
|
||||
}
|
@ -0,0 +1,344 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.commons.collections.map.HashedMap;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONObject;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
|
||||
import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
|
||||
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
|
||||
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
|
||||
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
|
||||
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
|
||||
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
|
||||
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.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;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class @{@link RemoteSessionManagementServiceImpl} is the implementation of @{@link RemoteSessionManagementService}
|
||||
* which is used manage initial connection, sending messages to peer session, manage and close the session.
|
||||
*/
|
||||
public class RemoteSessionManagementServiceImpl implements RemoteSessionManagementService {
|
||||
|
||||
private static final Log log = LogFactory.getLog(RemoteSessionManagementServiceImpl.class);
|
||||
|
||||
@Override
|
||||
public void initializeSession(Session session, String deviceType, String deviceId, String operationId) throws
|
||||
RemoteSessionManagementException {
|
||||
|
||||
// Check whether required configurations are enabled
|
||||
if (!RemoteSessionManagementDataHolder.getInstance().isEnabled()) {
|
||||
throw new RemoteSessionManagementException("Remote session feature is disabled.");
|
||||
} else if (RemoteSessionManagementDataHolder.getInstance().getServerUrl() == null) {
|
||||
throw new RemoteSessionManagementException("Server url has not been configured.");
|
||||
}
|
||||
|
||||
// Read Query Parameters for obtain the token
|
||||
Map<String, List<String>> sessionQueryParam = new HashedMap();
|
||||
List<String> 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);
|
||||
|
||||
if (authenticationInfo != null && authenticationInfo.isAuthenticated()) {
|
||||
try {
|
||||
PrivilegedCarbonContext.startTenantFlow();
|
||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(authenticationInfo
|
||||
.getTenantDomain()
|
||||
, true);
|
||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(authenticationInfo.getUsername());
|
||||
if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) {
|
||||
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
|
||||
deviceIdentifier.setId(deviceId);
|
||||
deviceIdentifier.setType(deviceType);
|
||||
|
||||
// Check authorization of user for given device
|
||||
boolean userAuthorized = RemoteSessionManagementDataHolder.getInstance()
|
||||
.getDeviceAccessAuthorizationService()
|
||||
.isUserAuthorized(deviceIdentifier, authenticationInfo.getUsername());
|
||||
if (userAuthorized) {
|
||||
// set common settings for session
|
||||
session.setMaxBinaryMessageBufferSize(RemoteSessionConstants.MAX_BUFFER_SIZE);
|
||||
session.setMaxTextMessageBufferSize(RemoteSessionConstants.MAX_BUFFER_SIZE);
|
||||
session.setMaxIdleTimeout(RemoteSessionManagementDataHolder.getInstance().getMaxIdleTimeout());
|
||||
|
||||
// if session initiated using operation id means request came from device
|
||||
if (operationId != null) {
|
||||
// create new device session
|
||||
initializeDeviceSession(session, authenticationInfo.getTenantDomain(), deviceType, deviceId,
|
||||
operationId);
|
||||
} else {
|
||||
// create new client session
|
||||
initializeClientSession(session, authenticationInfo.getTenantDomain(), deviceType,
|
||||
deviceId);
|
||||
}
|
||||
log.info("Current remote sessions count: " + RemoteSessionManagementDataHolder.getInstance()
|
||||
.getSessionMap().size());
|
||||
|
||||
} else {
|
||||
throw new RemoteSessionManagementException("Missing device Id or type ");
|
||||
}
|
||||
} else {
|
||||
throw new RemoteSessionManagementException("Unauthorized Access for the device Type : " + deviceType
|
||||
+ " , deviceId : " + deviceId);
|
||||
}
|
||||
} catch (OperationManagementException | InvalidDeviceException e) {
|
||||
throw new RemoteSessionManagementException("Error occurred while adding initial operation for the " +
|
||||
"device Type : " + deviceType + " , deviceId : " + deviceId);
|
||||
} catch (DeviceAccessAuthorizationException e) {
|
||||
throw new RemoteSessionManagementException("Error occurred while device access authorization for the " +
|
||||
"device Type : " + deviceType + " , " + "deviceId : " + deviceId);
|
||||
} finally {
|
||||
PrivilegedCarbonContext.endTenantFlow();
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new RemoteSessionManagementException("Invalid token");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeSession(Session session, String deviceType, String deviceId) throws
|
||||
RemoteSessionManagementException {
|
||||
initializeSession(session, deviceType, deviceId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the behaviour of sending message to peer connection
|
||||
*
|
||||
* @param session Web socket RemoteSession
|
||||
* @param message String message needs to send to peer connection
|
||||
* @throws RemoteSessionManagementException 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, String message) throws RemoteSessionManagementException {
|
||||
JSONObject jsonObject = new JSONObject(message);
|
||||
RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().get(session
|
||||
.getId());
|
||||
if (remoteSession != null) {
|
||||
remoteSession.sendMessageToPeer(jsonObject.toString());
|
||||
} else {
|
||||
throw new RemoteSessionManagementException("Remote Session cannot be found ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 RemoteSessionManagementException 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 RemoteSessionManagementException {
|
||||
|
||||
RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().get(session
|
||||
.getId());
|
||||
if (remoteSession != null) {
|
||||
remoteSession.sendMessageToPeer(message);
|
||||
} else {
|
||||
throw new RemoteSessionManagementException("Remote Session cannot be found ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closing the session and cleanup the resources
|
||||
*
|
||||
* @param session Web socket Remote Session
|
||||
*/
|
||||
@Override
|
||||
public void endSession(Session session, String closeReason) {
|
||||
|
||||
RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(session
|
||||
.getId());
|
||||
if (remoteSession != null) {
|
||||
//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));
|
||||
} 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<DeviceIdentifier> 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed 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.authentication;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is returned after authentication.
|
||||
*/
|
||||
public class AuthenticationInfo {
|
||||
|
||||
/**
|
||||
* this variable is used to check whether the client is authenticated.
|
||||
*/
|
||||
private boolean authenticated;
|
||||
private String username;
|
||||
private String tenantDomain;
|
||||
|
||||
/**
|
||||
* To hold authentication related properties eg: scopes in oauth
|
||||
*/
|
||||
private Map<String, Object> properties;
|
||||
|
||||
/**
|
||||
* returns whether the client is authenticated
|
||||
*/
|
||||
public boolean isAuthenticated() {
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
public void setAuthenticated(boolean authenticated) {
|
||||
this.authenticated = authenticated;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the authenticated client username
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the authenticated client tenant domain
|
||||
*/
|
||||
public String getTenantDomain() {
|
||||
return tenantDomain;
|
||||
}
|
||||
|
||||
public void setTenantDomain(String tenantDomain) {
|
||||
this.tenantDomain = tenantDomain;
|
||||
}
|
||||
|
||||
public Map<String, Object> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public void setProperties(Map<String, Object> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed 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.authentication;
|
||||
|
||||
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.oauth.OAuthTokenValidator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link OAuthAuthenticator} for validate tokens to web socket api
|
||||
*/
|
||||
public class OAuthAuthenticator {
|
||||
OAuthTokenValidator oAuthTokenValidator;
|
||||
|
||||
public void init(Map<String, String> globalProperties) {
|
||||
oAuthTokenValidator = new OAuthTokenValidator(globalProperties);
|
||||
}
|
||||
|
||||
public AuthenticationInfo isAuthenticated(Map<String, List<String>> webSocketConnectionProperties) {
|
||||
return oAuthTokenValidator.validateToken(webSocketConnectionProperties);
|
||||
}
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* Licensed 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.authentication.oauth;
|
||||
|
||||
import org.apache.axis2.context.ServiceContext;
|
||||
import org.apache.axis2.transport.http.HTTPConstants;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.AuthenticationInfo;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
|
||||
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
|
||||
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
|
||||
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
|
||||
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
|
||||
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This acts as a contract point for OAuth token validation.
|
||||
*/
|
||||
public class OAuthTokenValidator {
|
||||
|
||||
private static String cookie;
|
||||
private GenericObjectPool stubs;
|
||||
private static Log log = LogFactory.getLog(OAuthTokenValidator.class);
|
||||
private static OAuthTokenValidator oAuthTokenValidator;
|
||||
|
||||
|
||||
public OAuthTokenValidator(Map<String, String> globalProperties) {
|
||||
this.stubs = new GenericObjectPool(new OAuthTokenValidatorStubFactory(globalProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets a string accessToken and validates it
|
||||
*
|
||||
* @param webSocketConnectionProperties WebSocket connection information including http headers
|
||||
* @return AuthenticationInfo with the validated results.
|
||||
*/
|
||||
public AuthenticationInfo validateToken(Map<String, List<String>> webSocketConnectionProperties) {
|
||||
String token = getTokenFromSession(webSocketConnectionProperties);
|
||||
if (token == null) {
|
||||
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||
authenticationInfo.setAuthenticated(false);
|
||||
return authenticationInfo;
|
||||
}
|
||||
OAuth2TokenValidationServiceStub tokenValidationServiceStub = null;
|
||||
try {
|
||||
Object stub = this.stubs.borrowObject();
|
||||
if (stub != null) {
|
||||
tokenValidationServiceStub = (OAuth2TokenValidationServiceStub) stub;
|
||||
if (cookie != null) {
|
||||
tokenValidationServiceStub._getServiceClient().getOptions().setProperty(
|
||||
HTTPConstants.COOKIE_STRING, cookie);
|
||||
}
|
||||
return getAuthenticationInfo(token, tokenValidationServiceStub);
|
||||
} else {
|
||||
log.warn("Stub initialization failed.");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
log.error("Error on connecting with the validation endpoint.", e);
|
||||
} catch (Exception e) {
|
||||
log.error("Error occurred in borrowing an validation stub from the pool.", e);
|
||||
|
||||
} finally {
|
||||
try {
|
||||
if (tokenValidationServiceStub != null) {
|
||||
this.stubs.returnObject(tokenValidationServiceStub);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Error occurred while returning the object back to the oauth token validation service " +
|
||||
"stub pool.", e);
|
||||
}
|
||||
}
|
||||
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||
authenticationInfo.setAuthenticated(false);
|
||||
return authenticationInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates an AuthenticationInfo object that is used for authorization. This method will validate the token
|
||||
* and
|
||||
* sets the required parameters to the object.
|
||||
*
|
||||
* @param token that needs to be validated.
|
||||
* @param tokenValidationServiceStub stub that is used to call the external service.
|
||||
* @return AuthenticationInfo This contains the information related to authenticated client.
|
||||
* @throws RemoteException that triggers when failing to call the external service..
|
||||
*/
|
||||
private AuthenticationInfo getAuthenticationInfo(String token,
|
||||
OAuth2TokenValidationServiceStub tokenValidationServiceStub)
|
||||
throws RemoteException {
|
||||
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||
OAuth2TokenValidationRequestDTO validationRequest = new OAuth2TokenValidationRequestDTO();
|
||||
OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken =
|
||||
new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
|
||||
accessToken.setTokenType(RemoteSessionConstants.OAuthTokenValidator.TOKEN_TYPE);
|
||||
accessToken.setIdentifier(token);
|
||||
validationRequest.setAccessToken(accessToken);
|
||||
boolean authenticated;
|
||||
OAuth2TokenValidationResponseDTO tokenValidationResponse;
|
||||
tokenValidationResponse = tokenValidationServiceStub.validate(validationRequest);
|
||||
if (tokenValidationResponse == null) {
|
||||
authenticationInfo.setAuthenticated(false);
|
||||
return authenticationInfo;
|
||||
}
|
||||
authenticated = tokenValidationResponse.getValid();
|
||||
if (authenticated) {
|
||||
String authorizedUser = tokenValidationResponse.getAuthorizedUser();
|
||||
String username = MultitenantUtils.getTenantAwareUsername(authorizedUser);
|
||||
String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser);
|
||||
authenticationInfo.setUsername(username);
|
||||
authenticationInfo.setTenantDomain(tenantDomain);
|
||||
String scopes[] = tokenValidationResponse.getScope();
|
||||
if (scopes != null) {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(RemoteSessionConstants.SCOPE_IDENTIFIER, scopes);
|
||||
authenticationInfo.setProperties(properties);
|
||||
}
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Token validation failed for token: " + token);
|
||||
}
|
||||
}
|
||||
ServiceContext serviceContext = tokenValidationServiceStub._getServiceClient()
|
||||
.getLastOperationContext().getServiceContext();
|
||||
cookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING);
|
||||
authenticationInfo.setAuthenticated(authenticated);
|
||||
return authenticationInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieving the token from the http header
|
||||
*
|
||||
* @param webSocketConnectionProperties WebSocket connection information including http headers
|
||||
* @return retrieved token
|
||||
*/
|
||||
private String getToken(Map<String, List<String>> webSocketConnectionProperties) {
|
||||
String cookieString = webSocketConnectionProperties.get(RemoteSessionConstants.OAuthTokenValidator.COOKIE)
|
||||
.get(0);
|
||||
String[] properties = cookieString.split(RemoteSessionConstants.OAuthTokenValidator.COOKIE_KEYPAIR_SEPERATOR);
|
||||
String token;
|
||||
for (String keyValuePair : properties) {
|
||||
if (RemoteSessionConstants.OAuthTokenValidator.TOKEN_IDENTIFIER.equals((keyValuePair.
|
||||
split(RemoteSessionConstants.OAuthTokenValidator.COOKIE_KEY_VALUE_SEPERATOR)[0]).trim())) {
|
||||
token = (keyValuePair.split(RemoteSessionConstants.OAuthTokenValidator.COOKIE_KEY_VALUE_SEPERATOR)
|
||||
[1]).trim();
|
||||
return token;
|
||||
}
|
||||
}
|
||||
log.error("WebSocket token should be specified in cookie");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieving the token from the http session
|
||||
*
|
||||
* @param webSocketConnectionProperties WebSocket connection information including http headers
|
||||
* @return retrieved token
|
||||
*/
|
||||
private String getTokenFromSession(Map<String, List<String>> webSocketConnectionProperties) {
|
||||
String queryString = webSocketConnectionProperties.get(RemoteSessionConstants.OAuthTokenValidator
|
||||
.QUERY_STRING).get(0);
|
||||
if (queryString != null) {
|
||||
String[] allQueryParamPairs = queryString.split(RemoteSessionConstants.OAuthTokenValidator
|
||||
.QUERY_STRING_SEPERATOR);
|
||||
for (String keyValuePair : allQueryParamPairs) {
|
||||
String[] queryParamPair = keyValuePair.split(RemoteSessionConstants.OAuthTokenValidator
|
||||
.QUERY_KEY_VALUE_SEPERATOR);
|
||||
if (queryParamPair.length != 2) {
|
||||
log.warn("Invalid query string [" + queryString + "] passed in.");
|
||||
break;
|
||||
}
|
||||
if (queryParamPair[0].equals(RemoteSessionConstants.OAuthTokenValidator.TOKEN_IDENTIFIER)) {
|
||||
return queryParamPair[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.authentication.oauth;
|
||||
|
||||
import org.apache.axis2.AxisFault;
|
||||
import org.apache.axis2.Constants;
|
||||
import org.apache.axis2.client.Options;
|
||||
import org.apache.axis2.client.ServiceClient;
|
||||
import org.apache.axis2.transport.http.HTTPConstants;
|
||||
import org.apache.axis2.transport.http.HttpTransportProperties;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpConnectionManager;
|
||||
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
|
||||
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
|
||||
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
|
||||
import org.apache.commons.httpclient.protocol.Protocol;
|
||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.pool.BasePoolableObjectFactory;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.authentication.oauth.exception.OAuthTokenValidationException;
|
||||
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.util.PropertyUtils;
|
||||
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* This follows object pool pattern to manage the stub for oauth validation service.
|
||||
*/
|
||||
public class OAuthTokenValidatorStubFactory extends BasePoolableObjectFactory {
|
||||
private static final Log log = LogFactory.getLog(OAuthTokenValidatorStubFactory.class);
|
||||
private HttpClient httpClient;
|
||||
Map<String, String> tokenValidationProperties;
|
||||
|
||||
public OAuthTokenValidatorStubFactory(Map<String, String> globalProperties) {
|
||||
this.tokenValidationProperties = globalProperties;
|
||||
this.httpClient = createHttpClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates a OAuth2TokenValidationServiceStub object to the pool.
|
||||
*
|
||||
* @return an OAuthValidationStub object
|
||||
* @throws Exception thrown when creating the object.
|
||||
*/
|
||||
@Override
|
||||
public Object makeObject() throws Exception {
|
||||
return this.generateStub();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to clean up the OAuth validation stub and releases to the object pool.
|
||||
*
|
||||
* @param o object that needs to be released.
|
||||
* @throws Exception throws when failed to release to the pool
|
||||
*/
|
||||
@Override
|
||||
public void passivateObject(Object o) throws Exception {
|
||||
if (o instanceof OAuth2TokenValidationServiceStub) {
|
||||
OAuth2TokenValidationServiceStub stub = (OAuth2TokenValidationServiceStub) o;
|
||||
stub._getServiceClient().cleanupTransport();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to create a stub which will be triggered through object pool factory, which will create an
|
||||
* instance of it.
|
||||
*
|
||||
* @return OAuth2TokenValidationServiceStub stub that is used to call an external service.
|
||||
* @throws OAuthTokenValidationException will be thrown when initialization failed.
|
||||
*/
|
||||
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
|
||||
OAuth2TokenValidationServiceStub stub;
|
||||
try {
|
||||
URL hostURL = new URL(PropertyUtils.replaceProperty(tokenValidationProperties.get(
|
||||
(RemoteSessionConstants.TOKEN_VALIDATION_ENDPOINT_URL)))
|
||||
+ RemoteSessionConstants.TOKEN_VALIDATION_CONTEX);
|
||||
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
|
||||
ServiceClient client = stub._getServiceClient();
|
||||
client.getServiceContext().getConfigurationContext().setProperty(
|
||||
HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
|
||||
|
||||
HttpTransportProperties.Authenticator auth =
|
||||
new HttpTransportProperties.Authenticator();
|
||||
auth.setPreemptiveAuthentication(true);
|
||||
String username = tokenValidationProperties.get(RemoteSessionConstants.USERNAME);
|
||||
String password = tokenValidationProperties.get(RemoteSessionConstants.PASSWORD);
|
||||
auth.setPassword(username);
|
||||
auth.setUsername(password);
|
||||
Options options = client.getOptions();
|
||||
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
|
||||
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
|
||||
client.setOptions(options);
|
||||
if (hostURL.getProtocol().equals("https")) {
|
||||
// set up ssl factory since axis2 https notification is used.
|
||||
EasySSLProtocolSocketFactory sslProtocolSocketFactory = createProtocolSocketFactory();
|
||||
Protocol authhttps = new Protocol(hostURL.getProtocol()
|
||||
, (ProtocolSocketFactory) sslProtocolSocketFactory, hostURL.getPort());
|
||||
Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
|
||||
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
|
||||
}
|
||||
|
||||
} catch (AxisFault axisFault) {
|
||||
throw new OAuthTokenValidationException(
|
||||
"Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new OAuthTokenValidationException(
|
||||
"Error occurred while parsing token endpoint URL", e);
|
||||
} catch (RemoteSessionManagementException e) {
|
||||
throw new OAuthTokenValidationException("Invalid token endpoint url", e);
|
||||
}
|
||||
|
||||
return stub;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is required to create a trusted connection with the external entity.
|
||||
* Have to manually configure it since we use CommonHTTPTransport(axis2 notification) in axis2.
|
||||
*
|
||||
* @return an EasySSLProtocolSocketFactory for SSL communication.
|
||||
*/
|
||||
private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException {
|
||||
try {
|
||||
return new EasySSLProtocolSocketFactory();
|
||||
} catch (IOException e) {
|
||||
String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory.";
|
||||
throw new OAuthTokenValidationException(errorMsg, e);
|
||||
} catch (GeneralSecurityException e) {
|
||||
String errorMsg = "Failed to set the key material in easy ssl factory.";
|
||||
throw new OAuthTokenValidationException(errorMsg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This created httpclient pool that can be used to connect to external entity. This connection can be configured
|
||||
* via broker.xml by setting up the required http connection parameters.
|
||||
*
|
||||
* @return an instance of HttpClient that is configured with MultiThreadedHttpConnectionManager
|
||||
*/
|
||||
private HttpClient createHttpClient() {
|
||||
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
|
||||
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.get(
|
||||
RemoteSessionConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
|
||||
params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.get(
|
||||
RemoteSessionConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
|
||||
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
|
||||
connectionManager.setParams(params);
|
||||
return new HttpClient(connectionManager);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.authentication.oauth.exception;
|
||||
|
||||
/**
|
||||
* This Exception will be thrown, when there any interference with token validation flow.
|
||||
*/
|
||||
public class OAuthTokenValidationException extends Exception {
|
||||
|
||||
public OAuthTokenValidationException(String msg, Exception nestedEx) {
|
||||
super(msg, nestedEx);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.constants;
|
||||
|
||||
/**
|
||||
* This holds the constants related to remote session
|
||||
*/
|
||||
public class RemoteSessionConstants {
|
||||
|
||||
public static final String SCOPE_IDENTIFIER = "scopes";
|
||||
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 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";
|
||||
public static final String DEFAULT_MAXIMUM_HTTP_CONNECTION_PER_HOST = "2";
|
||||
public static final String DEFAULT_MAXIMUM_TOTAL_HTTP_CONNECTIONS = "100";
|
||||
|
||||
// Initial remote connection operation related Constants
|
||||
public static final String REMOTE_CONNECT = "REMOTE_CONNECT";
|
||||
public static final String REMOTE_CONNECT_CODE = "code";
|
||||
|
||||
private RemoteSessionConstants() {
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuthTokenValidator specific constants
|
||||
*/
|
||||
public final class OAuthTokenValidator {
|
||||
public static final String COOKIE_KEY_VALUE_SEPERATOR = "=";
|
||||
public static final String COOKIE_KEYPAIR_SEPERATOR = ";";
|
||||
public static final String COOKIE = "cookie";
|
||||
public static final String TOKEN_TYPE = "bearer";
|
||||
public static final String TOKEN_IDENTIFIER = "websocketToken";
|
||||
public static final String QUERY_STRING_SEPERATOR = "&";
|
||||
public static final String QUERY_KEY_VALUE_SEPERATOR = "=";
|
||||
public static final String QUERY_STRING = "queryString";
|
||||
|
||||
private OAuthTokenValidator() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.RemoteSessionManagementException;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.internal.RemoteSessionManagementDataHolder;
|
||||
|
||||
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 context.
|
||||
*/
|
||||
public 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();
|
||||
private int maxMessagesPerSecond;
|
||||
private int messageAllowance;
|
||||
private double messageRatePerSecond;
|
||||
private RemoteSessionConstants.CONNECTION_TYPE connectionType;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private void sendMessage(Object message) throws RemoteSessionManagementException {
|
||||
if (message != null) {
|
||||
boolean isMessageCountExceed = false;
|
||||
if (mySession != null && mySession.isOpen()) {
|
||||
synchronized (writeLockObject) {
|
||||
try {
|
||||
isMessageCountExceed = applyRateLimit();
|
||||
if (!isMessageCountExceed) {
|
||||
if (message instanceof String) {
|
||||
mySession.getBasicRemote().sendText(message.toString());
|
||||
} else {
|
||||
mySession.getBasicRemote().sendBinary(ByteBuffer.wrap((byte[]) message));
|
||||
}
|
||||
this.lastMessageTimeStamp = System.currentTimeMillis();
|
||||
} else {
|
||||
log.warn("Message count per second is exceeded for device id :" + deviceId);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Send data to session failed due to ", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new RemoteSessionManagementException("Peer Session already closed ");
|
||||
}
|
||||
} else {
|
||||
throw new RemoteSessionManagementException("Message is empty");
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessageToPeer(Object message) throws RemoteSessionManagementException {
|
||||
peerSession.sendMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use for limit the messages for given time
|
||||
*
|
||||
* @return message rate applied
|
||||
*/
|
||||
private boolean applyRateLimit() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
messageAllowance += (currentTime - lastMessageTimeStamp) * messageRatePerSecond;
|
||||
if (messageAllowance > maxMessagesPerSecond) {
|
||||
messageAllowance = maxMessagesPerSecond;
|
||||
}
|
||||
if (messageAllowance >= 1) {
|
||||
lastMessageTimeStamp = currentTime;
|
||||
messageAllowance -= 1;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Session getMySession() {
|
||||
return mySession;
|
||||
}
|
||||
|
||||
public RemoteSession getPeerSession() {
|
||||
return peerSession;
|
||||
}
|
||||
|
||||
public void setPeerSession(RemoteSession peerSession) {
|
||||
this.peerSession = peerSession;
|
||||
}
|
||||
|
||||
public String getTenantDomain() {
|
||||
return tenantDomain;
|
||||
}
|
||||
|
||||
public String getOperationId() {
|
||||
return operationId;
|
||||
}
|
||||
|
||||
public void setOperationId(String operationId) {
|
||||
this.operationId = operationId;
|
||||
}
|
||||
|
||||
public String getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public RemoteSessionConstants.CONNECTION_TYPE getConnectionType() {
|
||||
return connectionType;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
|
||||
/**
|
||||
* This Exception will be thrown, when there any management issues with Remote Session.
|
||||
*/
|
||||
public class RemoteSessionManagementException extends Exception {
|
||||
|
||||
CloseReason closeReason;
|
||||
|
||||
public RemoteSessionManagementException(String msg) {
|
||||
super(msg);
|
||||
this.closeReason = new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, msg);
|
||||
}
|
||||
|
||||
public CloseReason getCloseReason() {
|
||||
return closeReason;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.internal;
|
||||
|
||||
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
|
||||
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 java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Class {@link RemoteSessionManagementDataHolder} will hold the configurations and in memory storage strictures to
|
||||
* manage remote sessions.
|
||||
*/
|
||||
public class RemoteSessionManagementDataHolder {
|
||||
|
||||
private static RemoteSessionManagementDataHolder thisInstance = new RemoteSessionManagementDataHolder();
|
||||
private DeviceManagementProviderService deviceManagementProviderService;
|
||||
private DeviceAccessAuthorizationService deviceAccessAuthorizationService;
|
||||
private boolean isEnabled;
|
||||
private String serverUrl;
|
||||
private long maxIdleTimeout;
|
||||
private int maxMessagesPerSecond;
|
||||
private OAuthAuthenticator oAuthAuthenticator;
|
||||
private Map<String, RemoteSession> activeDeviceClientSessionMap = new ConcurrentHashMap<String, RemoteSession>();
|
||||
private Map<String, RemoteSession> sessionMap = new ConcurrentHashMap<String, RemoteSession>();
|
||||
|
||||
public static RemoteSessionManagementDataHolder getInstance() {
|
||||
return thisInstance;
|
||||
}
|
||||
|
||||
public DeviceManagementProviderService getDeviceManagementProviderService() {
|
||||
return deviceManagementProviderService;
|
||||
}
|
||||
|
||||
public void setDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
|
||||
this.deviceManagementProviderService = deviceManagementProviderService;
|
||||
}
|
||||
|
||||
public DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() {
|
||||
return deviceAccessAuthorizationService;
|
||||
}
|
||||
|
||||
public void setDeviceAccessAuthorizationService(DeviceAccessAuthorizationService deviceAccessAuthorizationService) {
|
||||
this.deviceAccessAuthorizationService = deviceAccessAuthorizationService;
|
||||
}
|
||||
|
||||
public OAuthAuthenticator getOauthAuthenticator() {
|
||||
return oAuthAuthenticator;
|
||||
}
|
||||
|
||||
public void setOauthAuthenticator(OAuthAuthenticator oAuthAuthenticator) {
|
||||
this.oAuthAuthenticator = oAuthAuthenticator;
|
||||
}
|
||||
|
||||
public Map<String, RemoteSession> getSessionMap() {
|
||||
return sessionMap;
|
||||
}
|
||||
|
||||
public Map<String, RemoteSession> getActiveDeviceClientSessionMap() {
|
||||
return activeDeviceClientSessionMap;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
isEnabled = enabled;
|
||||
}
|
||||
|
||||
public String getServerUrl() {
|
||||
return serverUrl;
|
||||
}
|
||||
|
||||
public void setServerUrl(String serverUrl) {
|
||||
this.serverUrl = serverUrl;
|
||||
}
|
||||
|
||||
public int getMaxMessagesPerSecond() {
|
||||
return maxMessagesPerSecond;
|
||||
}
|
||||
|
||||
public void setMaxMessagesPerSecond(int maxMessagesPerSecond) {
|
||||
this.maxMessagesPerSecond = maxMessagesPerSecond;
|
||||
}
|
||||
|
||||
public long getMaxIdleTimeout() {
|
||||
return maxIdleTimeout;
|
||||
}
|
||||
|
||||
public void setMaxIdleTimeout(long maxIdleTimeout) {
|
||||
this.maxIdleTimeout = maxIdleTimeout;
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.internal;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.wso2.carbon.core.ServerStartupObserver;
|
||||
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
|
||||
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.RemoteSessionManagementService;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.RemoteSessionManagementServiceImpl;
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.listener.RemoteSessionManagerStartupListener;
|
||||
|
||||
/**
|
||||
* @scr.component name="RemoteSessionManagementServiceComponent" immediate="true"
|
||||
* @scr.reference name="carbon.device.mgt.provider"
|
||||
* interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService"
|
||||
* cardinality="1..1"
|
||||
* policy="dynamic"
|
||||
* bind="setDeviceManagementProviderService"
|
||||
* unbind="unsetDeviceManagementProviderService"
|
||||
* @scr.reference name="device.manager.service"
|
||||
* interface="org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService"
|
||||
* cardinality="0..n"
|
||||
* policy="dynamic"
|
||||
* bind="setDeviceAccessAuthorizationService"
|
||||
* unbind="unsetDeviceAccessAuthorizationService"
|
||||
*/
|
||||
|
||||
public class RemoteSessionManagementServiceComponent {
|
||||
|
||||
private static final Log log = LogFactory.getLog(RemoteSessionManagementServiceComponent.class);
|
||||
|
||||
protected void activate(ComponentContext componentContext) {
|
||||
try {
|
||||
|
||||
BundleContext bundleContext = componentContext.getBundleContext();
|
||||
bundleContext.registerService(ServerStartupObserver.class.getName(), new
|
||||
RemoteSessionManagerStartupListener(), null);
|
||||
bundleContext.registerService(RemoteSessionManagementService.class.getName(), new
|
||||
RemoteSessionManagementServiceImpl(), null);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Remote Session device access service implementation bundle has been successfully " +
|
||||
"initialized");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
log.error("Error occurred while initializing Remote Session device access service " +
|
||||
"implementation bundle", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void deactivate(ComponentContext componentContext) {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
protected void setDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
|
||||
RemoteSessionManagementDataHolder.getInstance()
|
||||
.setDeviceManagementProviderService(deviceManagementProviderService);
|
||||
}
|
||||
|
||||
protected void unsetDeviceManagementProviderService(DeviceManagementProviderService
|
||||
deviceManagementProviderService) {
|
||||
RemoteSessionManagementDataHolder.getInstance().setDeviceManagementProviderService(null);
|
||||
}
|
||||
|
||||
protected void setDeviceAccessAuthorizationService(DeviceAccessAuthorizationService
|
||||
deviceAccessAuthorizationService) {
|
||||
RemoteSessionManagementDataHolder.getInstance()
|
||||
.setDeviceAccessAuthorizationService(deviceAccessAuthorizationService);
|
||||
}
|
||||
|
||||
protected void unsetDeviceAccessAuthorizationService(DeviceAccessAuthorizationService
|
||||
deviceAccessAuthorizationService) {
|
||||
RemoteSessionManagementDataHolder.getInstance().setDeviceManagementProviderService(null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.listener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
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;
|
||||
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
private static final Log log = LogFactory.getLog(RemoteSessionManagerStartupListener.class);
|
||||
|
||||
@Override
|
||||
public void completingServerStartup() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completedServerStartup() {
|
||||
PrivilegedCarbonContext.startTenantFlow();
|
||||
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(rsConfig.isEnabled());
|
||||
RemoteSessionManagementDataHolder.getInstance().setServerUrl(rsConfig.getRemoteSessionServerUrl());
|
||||
Map<String, String> configProperties = new HashMap<>();
|
||||
|
||||
// Set max idle timeout in milliseconds
|
||||
RemoteSessionManagementDataHolder.getInstance().setMaxIdleTimeout((long) rsConfig.getSessionIdleTimeOut() *
|
||||
60000);
|
||||
|
||||
// Set max messages per second.
|
||||
if (rsConfig.getMaxMessagesPerSession() > 0) {
|
||||
RemoteSessionManagementDataHolder.getInstance().setMaxMessagesPerSecond(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);
|
||||
|
||||
} finally {
|
||||
PrivilegedCarbonContext.endTenantFlow();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Class for reading web socket url parameters
|
||||
*/
|
||||
public class PropertyUtils {
|
||||
|
||||
/**
|
||||
* Replace URL with placeholders with properties
|
||||
* @param urlWithPlaceholders URL
|
||||
* @return replaced url
|
||||
* @throws RemoteSessionManagementException
|
||||
*/
|
||||
public static String replaceProperty(String urlWithPlaceholders) throws RemoteSessionManagementException {
|
||||
String regex = "\\$\\{(.*?)\\}";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matchPattern = pattern.matcher(urlWithPlaceholders);
|
||||
while (matchPattern.find()) {
|
||||
String sysPropertyName = matchPattern.group(1);
|
||||
String sysPropertyValue = System.getProperty(sysPropertyName);
|
||||
if (sysPropertyValue != null && !sysPropertyName.isEmpty()) {
|
||||
urlWithPlaceholders = urlWithPlaceholders.replaceAll("\\$\\{(" + sysPropertyName + ")\\}", sysPropertyValue);
|
||||
} else {
|
||||
throw new RemoteSessionManagementException("System property - " + sysPropertyName
|
||||
+ " is not defined, hence cannot resolve : " + urlWithPlaceholders);
|
||||
}
|
||||
}
|
||||
return urlWithPlaceholders;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<artifactId>extensions</artifactId>
|
||||
<version>4.0.88-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>remote-session-extension</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>WSO2 Carbon - Remote Sessions Extension</name>
|
||||
<url>http://wso2.org</url>
|
||||
|
||||
<modules>
|
||||
<module>org.wso2.carbon.device.mgt.extensions.remote.session</module>
|
||||
<module>org.wso2.carbon.device.mgt.extensions.remote.session.endpoint</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-scr-plugin</artifactId>
|
||||
<version>1.7.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-scr-scrdescriptor</id>
|
||||
<goals>
|
||||
<goal>scr</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.terminal {
|
||||
background-color: #1f1d1d;
|
||||
border: 1px solid #000;
|
||||
color: #39ef39;
|
||||
padding: 8px;
|
||||
font-family: courier new;
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
var rs_websocket;
|
||||
var rs_WebSocketURL;
|
||||
var shellMessageField = document.getElementById('shell-command');
|
||||
var shellResponseField = document.getElementById('shell-response');
|
||||
var canRemotelyControl = true;
|
||||
WebSocket.prototype.set_opened = function() {
|
||||
this._opened = true;
|
||||
};
|
||||
|
||||
WebSocket.prototype.set_closed = function() {
|
||||
this._opened = false;
|
||||
};
|
||||
WebSocket.prototype.get_opened = function() {
|
||||
return this._opened || false;
|
||||
};
|
||||
|
||||
var remoteSessionWebSocketOnOpen = function() {
|
||||
rs_websocket.set_opened();
|
||||
};
|
||||
|
||||
var remoteSessionWebSocketOnMessage = function(message) {
|
||||
|
||||
$('#lbl-remote-session-status').text('Server Connected...');
|
||||
$('#remote-session-operations').removeClass('hidden');
|
||||
$('#loading-remote-session').addClass('hidden');
|
||||
$('#btn-close-remote-session').removeClass('hidden');
|
||||
$('#shell-terminal').removeClass('hidden');
|
||||
if (typeof message.data !== 'string') {
|
||||
$('#loading-screen').addClass('hidden');
|
||||
var url = URL.createObjectURL(event.data);
|
||||
var img = new Image;
|
||||
|
||||
img.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext('2d');
|
||||
ctx.canvas.height = this.height;
|
||||
ctx.canvas.width = this.width;
|
||||
ctx.drawImage(this, 0, 0);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
img.src = url;
|
||||
} else {
|
||||
|
||||
var json = $.parseJSON(message.data);
|
||||
if (json.code == "REMOTE_SHELL") {
|
||||
if (json.status != "NEW") {
|
||||
$('#loading-terminal').addClass('hidden');
|
||||
}
|
||||
if (json.operationResponse != null) {
|
||||
var shellResponse = $("#shell-response");
|
||||
shellResponse.val(shellResponse.val() + json.operationResponse);
|
||||
}
|
||||
|
||||
} else if (json.code == "REMOTE_LOGCAT") {
|
||||
|
||||
if (json.status != "NEW") {
|
||||
$('#btn-refresh-logCat').removeClass('hidden');
|
||||
$('#loading-logcat').addClass('hidden');
|
||||
}
|
||||
if (json.operationResponse != null) {
|
||||
var logcatResponse = $("#logcat-response");
|
||||
|
||||
logcatResponse.val(logcatResponse.val() + json.operationResponse);
|
||||
}
|
||||
} else if (json.code == "REMOTE_CONNECT") {
|
||||
$('#loading-terminal').addClass('hidden');
|
||||
if (json.operationResponse != null) {
|
||||
var shellResponse = $("#shell-response");
|
||||
shellResponse.val(json.operationResponse);
|
||||
}
|
||||
} else if (json.code == "REMOTE_INPUT") {
|
||||
canRemotelyControl = false;
|
||||
} else {
|
||||
console.log("Message type not supported." + JSON.stringify(json));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var remoteSessionWebSocketOnClose = function(e) {
|
||||
location.reload();
|
||||
};
|
||||
|
||||
var remoteSessionWebSocketOnError = function(err) {
|
||||
location.reload();
|
||||
};
|
||||
|
||||
$("#btn-connect-device").click(function() {
|
||||
|
||||
$('#loading-remote-session').removeClass('hidden');
|
||||
$('#btn-connect-device').addClass('hidden');
|
||||
$('#lbl-remote-session-status').text('Connecting to Server...');
|
||||
initializeRemoteSession();
|
||||
});
|
||||
|
||||
|
||||
$("#btn-close-remote-session").click(function() {
|
||||
// Close the WebSocket.
|
||||
rs_websocket.close();
|
||||
rs_websocket.set_closed();
|
||||
var canvas = document.getElementById("canvas");
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
$('#btn-connect-device').removeClass('hidden');
|
||||
$('#remote-session-operations').addClass('hidden');
|
||||
$('#btn-close-remote-session').addClass('hidden');
|
||||
$('#loading-screen').addClass('hidden');
|
||||
$('#btn-stop-screen').addClass('hidden');
|
||||
$('#btn-start-screen').removeClass('hidden');
|
||||
//location.reload();
|
||||
});
|
||||
|
||||
$("#btn-refresh-logCat").click(function() {
|
||||
|
||||
$('#loading-logcat').removeClass('hidden');
|
||||
$('#btn-refresh-logCat').addClass('hidden');
|
||||
var message = new Object();
|
||||
message.code = "REMOTE_LOGCAT";
|
||||
|
||||
// Send the message through the WebSocket.
|
||||
rs_websocket.send(JSON.stringify(message));
|
||||
|
||||
// Clear out the message field.
|
||||
$("#logcat-response").val("");
|
||||
|
||||
});
|
||||
|
||||
|
||||
function initializeRemoteSessionWebSocket() {
|
||||
|
||||
rs_websocket = new WebSocket(rs_WebSocketURL);
|
||||
rs_websocket.onopen = remoteSessionWebSocketOnOpen;
|
||||
rs_websocket.onmessage = remoteSessionWebSocketOnMessage;
|
||||
rs_websocket.onclose = remoteSessionWebSocketOnClose;
|
||||
rs_websocket.onerror = remoteSessionWebSocketOnError;
|
||||
|
||||
}
|
||||
|
||||
function initializeRemoteSession() {
|
||||
|
||||
rs_WebSocketURL = $("#remote-session").data("remote-session-uri");
|
||||
if (rs_WebSocketURL != null) {
|
||||
initializeRemoteSessionWebSocket();
|
||||
window.onbeforeunload = function() {
|
||||
rs_websocket.close();
|
||||
}
|
||||
$('#lbl-remote-session-status').text('Waiting on device to connect...');
|
||||
|
||||
} else {
|
||||
noty({
|
||||
text: 'Remote Session endpoint connection Failed!',
|
||||
type: 'error'
|
||||
});
|
||||
$('#btn-connect-device').removeClass('hidden');
|
||||
$('#loading-remote-session').addClass('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$("#shell-command").keyup(function(event) {
|
||||
if (event.keyCode == 13) {
|
||||
var message = new Object();
|
||||
message.code = "REMOTE_SHELL";
|
||||
message.payload = $("#shell-command").val();
|
||||
|
||||
|
||||
// Send the message through the WebSocket.
|
||||
rs_websocket.send(JSON.stringify(message));
|
||||
|
||||
// Clear out the message field.
|
||||
$("#shell-command").val("");
|
||||
$("#shell-response").val("");
|
||||
$('#loading-terminal').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$("#btn-start-screen").click(function() {
|
||||
|
||||
canRemotelyControl = true;
|
||||
$('#loading-screen').removeClass('hidden');
|
||||
$('#btn-start-screen').addClass('hidden');
|
||||
$('#remote-control-pannel').removeClass('hidden');
|
||||
$('#btn-stop-screen').removeClass('hidden');
|
||||
var message = new Object();
|
||||
var input = new Object();
|
||||
input.action = "start";
|
||||
input.height = 768;
|
||||
input.width = 1024;
|
||||
message.code = "REMOTE_SCREEN";
|
||||
message.payload = JSON.stringify(input);
|
||||
// Send the message through the WebSocket.
|
||||
rs_websocket.send(JSON.stringify(message));
|
||||
});
|
||||
|
||||
|
||||
$("#btn-stop-screen").click(function() {
|
||||
|
||||
canRemotelyControl = false;
|
||||
var canvas = document.getElementById("canvas");
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
$('#loading-screen').addClass('hidden');
|
||||
$('#remote-control-pannel').addClass('hidden');
|
||||
$('#btn-stop-screen').addClass('hidden');
|
||||
$('#btn-start-screen').removeClass('hidden');
|
||||
var message = new Object();
|
||||
var input = new Object();
|
||||
input.action = "stop";
|
||||
message.code = "REMOTE_SCREEN";
|
||||
message.payload = JSON.stringify(input);
|
||||
// Send the message through the WebSocket.
|
||||
rs_websocket.send(JSON.stringify(message));
|
||||
});
|
||||
|
||||
|
||||
$(function() {
|
||||
var lastDuration = 0;
|
||||
var minDuration = 50;
|
||||
var durationDiff = 0;
|
||||
var status = "ready";
|
||||
var bounds, x, y;
|
||||
//Enable swiping...
|
||||
$("#canvas").swipe({
|
||||
swipeStatus: function(event, phase, direction, distance, duration, fingers, fingerData, currentDirection) {
|
||||
|
||||
if (canRemotelyControl) {
|
||||
bounds = event.target.getBoundingClientRect();
|
||||
x = event.clientX - bounds.left;
|
||||
y = event.clientY - bounds.top;
|
||||
durationDiff = duration - lastDuration;
|
||||
if (x < 0 || y < 0 || status == "blocked") {
|
||||
return;
|
||||
}
|
||||
var inputMessage = new Object();
|
||||
var input = new Object();
|
||||
input.x = x / bounds.width;
|
||||
input.y = y / bounds.height;
|
||||
input.duration = durationDiff;
|
||||
inputMessage.code = "REMOTE_INPUT";
|
||||
|
||||
if (status == "ready" && phase == "start") {
|
||||
input.action = "down";
|
||||
inputMessage.payload = JSON.stringify(input);
|
||||
rs_websocket.send(JSON.stringify(inputMessage));
|
||||
status = "unblocked";
|
||||
} else if (status == "unblocked") {
|
||||
if (phase == "move") {
|
||||
if (durationDiff < minDuration) {
|
||||
return;
|
||||
} else {
|
||||
input.action = "move";
|
||||
inputMessage.payload = JSON.stringify(input);
|
||||
rs_websocket.send(JSON.stringify(inputMessage));
|
||||
lastDuration = duration;
|
||||
}
|
||||
} else {
|
||||
input.action = "up";
|
||||
lastDuration = 0;
|
||||
status = "blocked";
|
||||
if (durationDiff < minDuration) {
|
||||
setTimeout(function() {
|
||||
inputMessage.payload = JSON.stringify(input);
|
||||
rs_websocket.send(JSON.stringify(inputMessage));
|
||||
status = "ready";
|
||||
}, minDuration);
|
||||
} else {
|
||||
inputMessage.payload = JSON.stringify(input);
|
||||
rs_websocket.send(JSON.stringify(inputMessage));
|
||||
status = "ready";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
threshold: 200,
|
||||
maxTimeThreshold: 5000,
|
||||
fingers: 'all'
|
||||
});
|
||||
});;
|
@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<artifactId>extensions-feature</artifactId>
|
||||
<version>4.0.88-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>org.wso2.carbon.device.mgt.remote.session.feature</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>4.0.88-SNAPSHOT</version>
|
||||
<name>WSO2 Carbon - Remote Session Manager</name>
|
||||
<url>http://wso2.org</url>
|
||||
<description>This feature contains the core bundles required iot Remote Sessions</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-jaxrs</artifactId>
|
||||
<version>${io.github.openfeign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-gson</artifactId>
|
||||
<version>${io.github.openfeign.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<artifactId>org.wso2.carbon.device.mgt.extensions.remote.session.endpoint</artifactId>
|
||||
<version>${carbon.devicemgt.plugins.version}</version>
|
||||
<type>war</type>
|
||||
<overWrite>true</overWrite>
|
||||
<outputDirectory>
|
||||
${project.build.directory}/maven-shared-archive-resources/webapps/
|
||||
</outputDirectory>
|
||||
<destFileName>remote#session.war</destFileName>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-resources</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>src/main/resources</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>resources</directory>
|
||||
<includes>
|
||||
<include>build.properties</include>
|
||||
<include>p2.inf</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.wso2.maven</groupId>
|
||||
<artifactId>carbon-p2-plugin</artifactId>
|
||||
<version>${carbon.p2.plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>p2-feature-generation</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>p2-feature-gen</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<id>org.wso2.carbon.device.mgt.remote.session</id>
|
||||
<propertiesFile>../../../features/etc/feature.properties</propertiesFile>
|
||||
<adviceFile>
|
||||
<properties>
|
||||
<propertyDef>org.wso2.carbon.p2.category.type:server</propertyDef>
|
||||
<propertyDef>org.eclipse.equinox.p2.type.group:true</propertyDef>
|
||||
</properties>
|
||||
</adviceFile>
|
||||
<bundles>
|
||||
<bundleDef>
|
||||
org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.extensions.remote.session:${carbon.devicemgt.plugins.version}
|
||||
</bundleDef>
|
||||
|
||||
<bundleDef>
|
||||
org.wso2.carbon.identity.inbound.auth.oauth2:org.wso2.carbon.identity.oauth.stub:${identity.inbound.auth.oauth.version}
|
||||
</bundleDef>
|
||||
<bundleDef>
|
||||
io.github.openfeign:feign-core:${io.github.openfeign.version}
|
||||
</bundleDef>
|
||||
<bundleDef>
|
||||
io.github.openfeign:feign-slf4j:${io.github.openfeign.version}
|
||||
</bundleDef>
|
||||
<bundleDef>
|
||||
io.github.openfeign:feign-gson:${io.github.openfeign.version}
|
||||
</bundleDef>
|
||||
</bundles>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@ -0,0 +1,19 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
custom = true
|
@ -0,0 +1,3 @@
|
||||
instructions.configure = \
|
||||
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\
|
||||
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.remote.session_${feature.version}/webapps/,target:${installFolder}/../../deployment/server/webapps/,overwrite:true);\
|
Loading…
Reference in new issue