Fix issue with closing session which are abort by client

merge-requests/1/head
warunalakshitha 7 years ago
parent 1d23c3f709
commit 0ddb899b24

@ -100,104 +100,13 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme
// if session initiated using operation id means request came from device
if (operationId != null) {
RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance()
.getActiveDeviceClientSessionMap().get((authenticationInfo.getTenantDomain() + "/" +
deviceType + "/" + deviceId));
if (activeSession != null) {
RemoteSession clientRemote = RemoteSessionManagementDataHolder.getInstance()
.getSessionMap().get(activeSession.getMySession().getId());
if (clientRemote != null) {
if (clientRemote.getOperationId().equals(operationId)) {
RemoteSession deviceRemote = new RemoteSession(session, authenticationInfo
.getTenantDomain(), deviceType, deviceId);
deviceRemote.setOperationId(operationId);
deviceRemote.setPeerSession(clientRemote);
clientRemote.setPeerSession(deviceRemote);
RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session
.getId(), deviceRemote);
// Send Remote connect response
JSONObject message = new JSONObject();
message.put(RemoteSessionConstants.REMOTE_CONNECT_CODE, RemoteSessionConstants
.REMOTE_CONNECT);
deviceRemote.sendMessageToPeer(message.toString());
log.info("Device session opened for session id: " + session.getId() +
" device Type : " + deviceType + " , " + "deviceId : " + deviceId);
} else {
throw new RemoteSessionManagementException("Device and Operation information " +
"does not matched with client information for operation id: " +
operationId + " device Type : " + deviceType + " , " + "deviceId : " +
deviceId);
}
} else {
throw new RemoteSessionManagementException("Device session is inactive for " +
"operation id: " + operationId + " device Type : " + deviceType + " , " +
"deviceId : " + deviceId);
}
} else {
throw new RemoteSessionManagementException("Device session is inactive for operation " +
"id: " + operationId + " device Type : " + deviceType + " , " + "deviceId : " +
deviceId);
}
// create new device session
initializeDeviceSession(session, authenticationInfo.getTenantDomain(), deviceType, deviceId,
operationId);
} else {
RemoteSession clientRemote = new RemoteSession(session, authenticationInfo
.getTenantDomain(), deviceType, deviceId);
// Create new remote control operation to start the session
RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance()
.getActiveDeviceClientSessionMap().putIfAbsent((authenticationInfo
.getTenantDomain() + "/" + deviceType + "/" + deviceId),
clientRemote);
if (activeSession != null && activeSession.getMySession().isOpen() && activeSession
.getPeerSession() == null) {
throw new RemoteSessionManagementException("Another client session waiting on device " +
"to connect.");
} else {
// if there is pending session exists but already closed, then we need to remove it.
if (activeSession != null) {
endSession(activeSession.getMySession(), "Remote session closed due to new session" +
" request");
// Use put if absent for adding session to waiting list since we need to overcome
// multithreaded session requests.
activeSession = RemoteSessionManagementDataHolder.getInstance()
.getActiveDeviceClientSessionMap().putIfAbsent((authenticationInfo
.getTenantDomain() + "/" + deviceType + "/" +
deviceId), clientRemote);
}
// If another client tried to start session same time then active session will be
// exist. So we are adding session request only no parallel sessions added to map
if (activeSession == null) {
// Create operation if session initiated by client
Operation operation = new ConfigOperation();
operation.setCode(RemoteSessionConstants.REMOTE_CONNECT);
operation.setEnabled(true);
operation.setControl(Operation.Control.NO_REPEAT);
JSONObject payload = new JSONObject();
payload.put("serverUrl", RemoteSessionManagementDataHolder.getInstance()
.getServerUrl());
operation.setPayLoad(payload.toString());
String date = new SimpleDateFormat(RemoteSessionConstants.DATE_FORMAT_NOW).format
(new Date());
operation.setCreatedTimeStamp(date);
List<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.");
}
}
// create new client session
initializeClientSession(session, authenticationInfo.getTenantDomain(), deviceType,
deviceId);
}
log.info("Current remote sessions count: " + RemoteSessionManagementDataHolder.getInstance()
.getSessionMap().size());
@ -278,15 +187,28 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme
*/
@Override
public void endSession(Session session, String closeReason) {
log.info("Closing session: "+session.getId()+" due to:"+ closeReason);
log.info("Closing session: " + session.getId() + " due to:" + closeReason);
RemoteSession remoteSession = RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(session
.getId());
if (remoteSession != null) {
String operationId = remoteSession.getOperationId();
//String operationId = remoteSession.getOperationId();
String deviceKey = remoteSession.getTenantDomain() + "/" + remoteSession.getDeviceType() + "/" +
remoteSession.getDeviceId();
RemoteSession lastSession = RemoteSessionManagementDataHolder.getInstance()
.getActiveDeviceClientSessionMap().get(deviceKey);
if (lastSession != null && lastSession.getMySession().getId().equals(session.getId())) {
RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap().remove
(deviceKey);
}
if (remoteSession.getPeerSession() != null) {
Session peerSession = remoteSession.getPeerSession().getMySession();
if (peerSession != null) {
RemoteSessionManagementDataHolder.getInstance().getSessionMap().remove(peerSession.getId());
if (lastSession != null && lastSession.getMySession().getId().equals(peerSession.getId())) {
RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap().remove
(deviceKey);
}
if (peerSession.isOpen()) {
try {
peerSession.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, closeReason));
@ -298,28 +220,125 @@ public class RemoteSessionManagementServiceImpl implements RemoteSessionManageme
}
}
}
if (remoteSession.getMySession() != null) {
Session mySession = remoteSession.getMySession();
if (mySession.isOpen()) {
try {
mySession.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, closeReason));
} catch (IOException ex) {
if (log.isDebugEnabled()) {
log.error("Failed to disconnect the client.", ex);
}
}
}
/**
* Starting new client session
*
* @param session Web socket Session
* @param tenantDomain Tenant domain
* @param deviceType Device Type
* @param deviceId Device Id
* @throws RemoteSessionManagementException throws when session has errors with accessing device resources
* @throws OperationManagementException throws when error occured during new operation
* @throws InvalidDeviceException throws when incorrect device identifier
*/
private void initializeClientSession(Session session, String tenantDomain, String deviceType, String deviceId) throws RemoteSessionManagementException,
OperationManagementException, InvalidDeviceException {
RemoteSession clientRemote = new RemoteSession(session, tenantDomain, deviceType, deviceId, RemoteSessionConstants
.CONNECTION_TYPE.CLIENT);
String deviceKey = tenantDomain + "/" + deviceType + "/" + deviceId;
// Create new remote control operation to start the session
RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap
().putIfAbsent(deviceKey, clientRemote);
if (activeSession != null && activeSession.getMySession().isOpen() && activeSession
.getPeerSession() == null) {
throw new RemoteSessionManagementException("Another client session waiting on device to connect.");
} else {
// if there is pending session exists but already closed, then we need to remove it.
if (activeSession != null) {
RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap().remove
(deviceKey);
try {
activeSession.getMySession().close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "Remote " +
"session closed due to new session request"));
} catch (IOException ex) {
if (log.isDebugEnabled()) {
log.error("Failed to disconnect the client.", ex);
}
}
// Use put if absent for adding session to waiting list since we need to overcome
// multithreaded session requests.
activeSession = RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap()
.putIfAbsent(deviceKey, clientRemote);
}
// If another client tried to start session same time then active session will be
// exist. So we are adding session request only no parallel sessions added to map
if (activeSession == null) {
// Create operation if session initiated by client
Operation operation = new ConfigOperation();
operation.setCode(RemoteSessionConstants.REMOTE_CONNECT);
operation.setEnabled(true);
operation.setControl(Operation.Control.NO_REPEAT);
JSONObject payload = new JSONObject();
payload.put("serverUrl", RemoteSessionManagementDataHolder.getInstance().getServerUrl());
operation.setPayLoad(payload.toString());
String date = new SimpleDateFormat(RemoteSessionConstants.DATE_FORMAT_NOW).format(new Date());
operation.setCreatedTimeStamp(date);
List<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.");
}
if (operationId != null) {
String deviceIdentifier = remoteSession.getTenantDomain() + "/" + remoteSession
.getDeviceType() + "/" + remoteSession.getDeviceId();
RemoteSession lastSession = RemoteSessionManagementDataHolder.getInstance()
.getActiveDeviceClientSessionMap().get(deviceIdentifier);
if (lastSession != null && lastSession.getMySession().getId().equals(session.getId())) {
RemoteSessionManagementDataHolder.getInstance().getActiveDeviceClientSessionMap().remove
(deviceIdentifier);
}
}
/**
* Starting new device session
*
* @param session Web socket Session
* @param tenantDomain Tenant domain
* @param deviceType Device Type
* @param deviceId Device Id
* @param operationId Operation id
* @throws RemoteSessionManagementException throws when session has errors with accessing device resources
*/
private void initializeDeviceSession(Session session, String tenantDomain, String deviceType, String deviceId,
String operationId) throws RemoteSessionManagementException {
String deviceKey = tenantDomain + "/" + deviceType + "/" + deviceId;
RemoteSession activeSession = RemoteSessionManagementDataHolder.getInstance()
.getActiveDeviceClientSessionMap().get(deviceKey);
if (activeSession != null) {
RemoteSession clientRemote = RemoteSessionManagementDataHolder.getInstance().getSessionMap().get
(activeSession.getMySession().getId());
if (clientRemote != null) {
if (clientRemote.getOperationId().equals(operationId)) {
RemoteSession deviceRemote = new RemoteSession(session, tenantDomain, deviceType, deviceId,
RemoteSessionConstants.CONNECTION_TYPE.DEVICE);
deviceRemote.setOperationId(operationId);
deviceRemote.setPeerSession(clientRemote);
clientRemote.setPeerSession(deviceRemote);
RemoteSessionManagementDataHolder.getInstance().getSessionMap().put(session.getId(), deviceRemote);
// Send Remote connect response
JSONObject message = new JSONObject();
message.put(RemoteSessionConstants.REMOTE_CONNECT_CODE, RemoteSessionConstants.REMOTE_CONNECT);
deviceRemote.sendMessageToPeer(message.toString());
log.info("Device session opened for session id: " + session.getId() + " device Type : " +
deviceType + " , " + "deviceId : " + deviceId);
} else {
throw new RemoteSessionManagementException("Device and Operation information " +
"does not matched with client information for operation id: " + operationId + " device " +
"Type : " + deviceType + " , " + "deviceId : " + deviceId);
}
} else {
throw new RemoteSessionManagementException("Device session is inactive for " + "operation id: " +
operationId + " device Type : " + deviceType + " , " + "deviceId : " + deviceId);
}
} else {
throw new RemoteSessionManagementException("Device session is inactive for operation " + "id: " +
operationId + " device Type : " + deviceType + " , " + "deviceId : " + deviceId);
}
}

@ -31,6 +31,10 @@ public class RemoteSessionConstants {
public static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";
public static final int MAX_BUFFER_SIZE = 640 * 1024;
public enum CONNECTION_TYPE {
CLIENT, DEVICE
}
public static final String QUERY_STRING = "queryString";
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection";
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";

@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.extensions.remote.session.dto;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.extensions.remote.session.constants.RemoteSessionConstants;
import org.wso2.carbon.device.mgt.extensions.remote.session.exception.RemoteSessionManagementException;
import org.wso2.carbon.device.mgt.extensions.remote.session.internal.RemoteSessionManagementDataHolder;
@ -41,12 +42,15 @@ public class RemoteSession {
private int maxMessagesPerSecond;
private int messageAllowance;
private double messageRatePerSecond;
private RemoteSessionConstants.CONNECTION_TYPE connectionType;
public RemoteSession(Session session, String tenantDomain, String deviceType, String deviceId) {
public RemoteSession(Session session, String tenantDomain, String deviceType, String deviceId,
RemoteSessionConstants.CONNECTION_TYPE connectionType) {
this.mySession = session;
this.deviceType = deviceType;
this.deviceId = deviceId;
this.tenantDomain = tenantDomain;
this.connectionType = connectionType;
maxMessagesPerSecond = RemoteSessionManagementDataHolder.getInstance().getMaxMessagesPerSecond();
messageAllowance = maxMessagesPerSecond;
messageRatePerSecond = (double) maxMessagesPerSecond / 1000;
@ -136,4 +140,8 @@ public class RemoteSession {
public String getDeviceId() {
return deviceId;
}
public RemoteSessionConstants.CONNECTION_TYPE getConnectionType() {
return connectionType;
}
}

Loading…
Cancel
Save