blob: 582fb625f2c599d6724fac292dbf92cf03c69642 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF 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 com.cloud.consoleproxy.websocket;
import com.cloud.consoleproxy.util.Logger;
import org.eclipse.jetty.websocket.api.Session;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.extensions.DefaultExtension;
import org.java_websocket.handshake.ServerHandshake;
import org.java_websocket.protocols.Protocol;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509ExtendedTrustManager;
import java.io.IOException;
import java.net.Socket;
import java.net.URI;
import java.nio.ByteBuffer;
import java.security.cert.X509Certificate;
import java.util.Collections;
/**
* Acts as a websocket reverse proxy between the remoteSession and the connected endpoint
* - Connects to a websocket endpoint and sends the received data to the remoteSession endpoint
* - Receives data from the remoteSession through the receiveProxiedMsg() method and forwards it to the connected endpoint
*
* remoteSession WebSocketReverseProxy websocket endpoint
* data -----------------> receiveProxiedMsg() -----------> data
* data <----------------- onMessage() <------------------- data
*/
public class WebSocketReverseProxy extends WebSocketClient {
private static final Protocol protocol = new Protocol("binary");
private static final DefaultExtension defaultExtension = new DefaultExtension();
private static final Draft_6455 draft = new Draft_6455(Collections.singletonList(defaultExtension), Collections.singletonList(protocol));
protected Logger logger = Logger.getLogger(getClass());
private Session remoteSession;
private void acceptAllCerts() {
TrustManager[] trustAllCerts = new TrustManager[]{new X509ExtendedTrustManager() {
@Override
public void checkClientTrusted (X509Certificate [] chain, String authType, Socket socket) {
}
@Override
public void checkServerTrusted (X509Certificate [] chain, String authType, Socket socket) {
}
@Override
public void checkClientTrusted (X509Certificate [] chain, String authType, SSLEngine engine) {
}
@Override
public void checkServerTrusted (X509Certificate [] chain, String authType, SSLEngine engine) {
}
@Override
public java.security.cert.X509Certificate [] getAcceptedIssuers () {
return null;
}
@Override
public void checkClientTrusted (X509Certificate [] certs, String authType) {
}
@Override
public void checkServerTrusted (X509Certificate [] certs, String authType) {
}
}};
SSLContext sc;
try {
sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
SSLSocketFactory factory = sc.getSocketFactory();
this.setSocketFactory(factory);
} catch (Exception e) {
e.printStackTrace();
}
}
public WebSocketReverseProxy(URI wsUrl, Session session) {
super(wsUrl, draft);
this.remoteSession = session;
acceptAllCerts();
setConnectionLostTimeout(0);
}
@Override
public void onOpen(ServerHandshake serverHandshake) {
}
@Override
public void onMessage(String message) {
}
@Override
public void onClose(int code, String reason, boolean remote) {
logger.info("Closing connection to websocket: reason=" + reason + " code=" + code + " remote=" + remote);
}
@Override
public void onError(Exception ex) {
logger.error("Error on connection to websocket: " + ex.getLocalizedMessage());
ex.printStackTrace();
}
@Override
public void onMessage(ByteBuffer bytes) {
try {
this.remoteSession.getRemote().sendBytes(bytes);
} catch (IOException e) {
logger.error("Error proxing msg from websocket to client side: " + e.getLocalizedMessage());
e.printStackTrace();
}
}
public void proxyMsgFromRemoteSessionToEndpoint(ByteBuffer msg) {
this.getConnection().send(msg);
}
}