blob: 2e7b05952a2b1b33a69c24d182af85b2791ff7ea [file] [log] [blame]
/*
* Copyright (c) 2020 Kentyou.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kentyou - initial API and implementation
*/
package org.eclipse.sensinact.gateway.nthbnd.rest.internal.ws;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.sensinact.gateway.core.security.AuthenticationToken;
import org.eclipse.sensinact.gateway.core.security.Credentials;
import org.eclipse.sensinact.gateway.core.security.InvalidCredentialException;
import org.eclipse.sensinact.gateway.nthbnd.endpoint.LoginResponse;
import org.eclipse.sensinact.gateway.nthbnd.endpoint.NorthboundEndpoint;
import org.eclipse.sensinact.gateway.nthbnd.endpoint.NorthboundMediator;
import org.json.JSONObject;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WebSocketConnectionFactory implements WebSocketCreator {
private NorthboundMediator mediator;
private List<WebSocketConnection> sessions;
private Map<String, String> anonymous;
/**
* @param mediator
*/
public WebSocketConnectionFactory(NorthboundMediator mediator) {
this.mediator = mediator;
this.sessions = new ArrayList<WebSocketConnection>();
this.anonymous = new HashMap<String, String>();
}
/**
* @param wsEndpoint
*/
public void deleteSocketEndpoint(WebSocketConnection wsEndpoint) {
synchronized (this.sessions) {
if (this.sessions.remove(wsEndpoint)) {
wsEndpoint.close();
}
}
}
/**
*
*/
public void close() {
synchronized (this.sessions) {
while (!this.sessions.isEmpty()) {
this.sessions.remove(0).close();
}
}
}
/**
* @inheritDoc
* @see org.eclipse.jetty.websocket.servlet.WebSocketCreator#
* createWebSocket(org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest,
* org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse)
*/
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) {
HttpServletRequest request = req.getHttpServletRequest();
String tokenHeader = request.getHeader("X-Auth-Token");
String authorizationHeader = request.getHeader("Authorization");
NorthboundEndpoint endpoint = null;
AuthenticationToken token = null;
Credentials credentials = null;
String client = null;
if (tokenHeader != null) {
token = new AuthenticationToken(tokenHeader);
} else if (authorizationHeader != null) {
credentials = new Credentials(authorizationHeader);
}
if (token == null && credentials == null) {
String clientAddress = request.getRemoteAddr();
int clientPort = request.getRemotePort();
client = new StringBuilder().append(clientAddress).append(":").append(clientPort).toString();
String sid = this.anonymous.get(client);
if (sid != null) {
token = new AuthenticationToken(sid);
} else {
try {
endpoint = mediator.getNorthboundEndpoints().getEndpoint();
this.anonymous.put(client, endpoint.getSessionToken());
} catch (InvalidCredentialException e) {
mediator.debug(e.getMessage());
}
}
}
if (credentials != null) {
try {
LoginResponse response = mediator.getAccessingEndpoint().createNorthboundEndpoint(credentials);
token = new AuthenticationToken(response.getToken());
} catch (InvalidCredentialException | NullPointerException e) {
mediator.debug(e.getMessage());
}
}
if (token != null) {
try {
endpoint = mediator.getNorthboundEndpoints().getEndpoint(token);
} catch (InvalidCredentialException e) {
mediator.debug(e.getMessage());
}
}
if (endpoint == null) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("statusCode", 403);
jsonObject.put("message", "Authentication failed");
try {
resp.sendError(403, new String(jsonObject.toString().getBytes("UTF-8")));
} catch (IOException e) {
mediator.error(e);
}
return null;
}
WebSocketConnection wsConnection = new WebSocketConnection(this, endpoint, this.mediator);
synchronized (this.sessions) {
this.sessions.add(wsConnection);
}
return wsConnection;
}
}