Skip to content

Instantly share code, notes, and snippets.

@mangadul
Last active March 15, 2017 06:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mangadul/72b2ec0d465a59d648bee102e084f6d7 to your computer and use it in GitHub Desktop.
Save mangadul/72b2ec0d465a59d648bee102e084f6d7 to your computer and use it in GitHub Desktop.
package com.alphamedia.tatapmuka.KurentoJsonrpcTatapMuka;
/*
* Modified from : https://github.com/nubomedia-vtt/jsonrpc-ws-android/blob/master/jsonrpc-ws-android/src/main/java/fi/vtt/nubomedia/jsonrpcwsandroid/JsonRpcWebSocketClient.java
* Using Websocket from https://github.com/TakahikoKawasaki/nv-websocket-client
* Modified by https://github.com/mangadul
*/
/*
* (C) Copyright 2016 VTT (http://www.vtt.fi)
*
* 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.
*
*/
import android.util.Log;
import com.alphamedia.tatapmuka.util.Constants;
import com.alphamedia.tatapmuka.util.websocket.WebSocket;
import com.alphamedia.tatapmuka.util.websocket.WebSocketAdapter;
import com.alphamedia.tatapmuka.util.websocket.WebSocketException;
import com.alphamedia.tatapmuka.util.websocket.WebSocketExtension;
import com.alphamedia.tatapmuka.util.websocket.WebSocketFactory;
import com.alphamedia.tatapmuka.util.websocket.WebSocketFrame;
import com.alphamedia.tatapmuka.util.websocket.WebSocketListener;
import com.alphamedia.tatapmuka.util.websocket.WebSocketState;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Message;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Notification;
import com.thetransactioncompany.jsonrpc2.JSONRPC2ParseException;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.Map;
import javax.net.SocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import fi.vtt.nubomedia.utilitiesandroid.LooperExecutor;
public class JsonRpcWebSocketClient {
private static final String TAG = "JsonRpcWebSocketClient";
private static final int CLOSE_TIMEOUT = 1000;
private static SSLContext sslctx;
private WebSocketConnectionState connectionState;
private WebSocketConnectionEvents events;
private ExtendedWebSocketClient client;
private LooperExecutor executor;
private WebSocketFactory factory;
private final Object closeEventLock = new Object();
private boolean closeEvent;
private SocketFactory socketfactory;
private InputStream sslks;
protected WebSocket wss;
public enum WebSocketConnectionState {
CONNECTED, CLOSED, ERROR, CLOSING, CONNECTING, CREATED, OPEN
}
public interface ExtendedWebSocketEvents {
public void onOpen(WebSocketState handshakedata);
public void onMessage(final String message);
public void onClose(int code, String reason, boolean remote);
public void onError(Exception e);
public void send(String s);
}
private class ExtendedWebSocketClient extends WebSocketFactory implements ExtendedWebSocketEvents {
protected URI serverUri;
protected WebSocketConnectionEvents events;
public ExtendedWebSocketClient(URI serverUri, WebSocketConnectionEvents events) {
//super();
this.serverUri = serverUri;
this.events = events;
}
@Override
public void onOpen(final WebSocketState handshakedata) {
executor.execute(new Runnable() {
@Override
public void run() {
setConnectionState(WebSocketConnectionState.CONNECTED);
events.onOpen(handshakedata);
}
});
}
@Override
public void onClose(final int code, final String reason, final boolean remote) {
executor.execute(new Runnable() {
@Override
public void run() {
//if (getConnectionState().equals(WebSocketConnectionState.CLOSED)) {
setConnectionState(WebSocketConnectionState.CLOSED);
events.onClose(code, reason, remote);
//}
}
});
}
@Override
public void onError(final Exception e) {
executor.execute(new Runnable() {
@Override
public void run() {
setConnectionState(WebSocketConnectionState.ERROR);
events.onError(e);
}
});
}
@Override
public void onMessage(final String message) {
onMessageListener(message);
}
@Override
public void send(String s) {
wss.sendText(s);
}
}
public interface WebSocketConnectionEvents {
void onOpen(WebSocketState handshakedata);
void onRequest(JsonRpcRequest request);
void onResponse(JsonRpcResponse response);
void onNotification(JsonRpcNotification notification);
void onClose(int code, String reason, boolean remote);
void onError(Exception e);
}
public JsonRpcWebSocketClient(URI serverUri, WebSocketConnectionEvents events, LooperExecutor executor, SSLContext ssLcontext) {
this.events = events;
this.executor = executor;
this.sslctx = ssLcontext;
this.client = new ExtendedWebSocketClient(serverUri, events);
}
public void onMessageListener(final String message){
Log.d(TAG, "onMessageListener() onTextMessage() response: "+message);
if(message != null) setConnectionState(WebSocketConnectionState.CONNECTED);
final WebSocketConnectionState wstats = getConnectionState();
executor.execute(new Runnable() {
@Override
public void run() {
if (wstats.equals(WebSocketConnectionState.CONNECTED)) {
try {
JSONRPC2Message msg = JSONRPC2Message.parse(message);
if (msg instanceof JSONRPC2Request) {
JsonRpcRequest request = new JsonRpcRequest();
request.setId(((JSONRPC2Request) msg).getID());
request.setMethod(((JSONRPC2Request) msg).getMethod());
request.setNamedParams(((JSONRPC2Request) msg).getNamedParams());
request.setPositionalParams(((JSONRPC2Request) msg).getPositionalParams());
events.onRequest(request);
} else if (msg instanceof JSONRPC2Notification) {
JsonRpcNotification notification = new JsonRpcNotification();
notification.setMethod(((JSONRPC2Notification) msg).getMethod());
notification.setNamedParams(((JSONRPC2Notification) msg).getNamedParams());
notification.setPositionalParams(((JSONRPC2Notification) msg).getPositionalParams());
events.onNotification(notification);
} else if (msg instanceof JSONRPC2Response) {
JsonRpcResponse notification = new JsonRpcResponse(message);
events.onResponse(notification);
}
} catch (JSONRPC2ParseException e) {
// TODO: Handle exception
}
}
}
});
}
public void connect() throws WebSocketException {
checkIfCalledOnValidThread();
closeEvent = false;
wss = getWss().connectAsynchronously()
.setPingInterval(24 * 1000)
.addListener(new WebSocketListener(){
@Override
public void onStateChanged(WebSocket websocket, WebSocketState newState) throws Exception {
}
@Override
public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
setConnectionState(WebSocketConnectionState.CONNECTED);
events.onOpen(WebSocketState.OPEN);
}
@Override
public void onConnectError(WebSocket websocket, WebSocketException cause) throws Exception {
setConnectionState(WebSocketConnectionState.ERROR);
events.onError(cause);
}
@Override
public void onDisconnected(WebSocket websocket, WebSocketFrame serverCloseFrame, WebSocketFrame clientCloseFrame, boolean closedByServer) throws Exception {
setConnectionState(WebSocketConnectionState.CLOSED);
events.onClose(1000, "no reason", closedByServer);
}
@Override
public void onFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onContinuationFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onBinaryFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onCloseFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onPingFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onPongFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onTextMessage(WebSocket websocket, final String message) {
setConnectionState(WebSocketConnectionState.CONNECTED);
onMessageListener(message);
}
@Override
public void onBinaryMessage(WebSocket websocket, byte[] binary) throws Exception {
}
@Override
public void onSendingFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onFrameUnsent(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
setConnectionState(WebSocketConnectionState.ERROR);
events.onError(cause);
}
@Override
public void onFrameError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame) throws Exception {
}
@Override
public void onMessageError(WebSocket websocket, WebSocketException cause, List<WebSocketFrame> frames) throws Exception {
}
@Override
public void onMessageDecompressionError(WebSocket websocket, WebSocketException cause, byte[] compressed) throws Exception {
}
@Override
public void onTextMessageError(WebSocket websocket, WebSocketException cause, byte[] data) throws Exception {
}
@Override
public void onSendError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame) throws Exception {
}
@Override
public void onUnexpectedError(WebSocket websocket, WebSocketException cause) throws Exception {
}
@Override
public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception {
}
@Override
public void onSendingHandshake(WebSocket websocket, String requestLine, List<String[]> headers) throws Exception {
}
});
if(wss.isOpen()) setConnectionState(WebSocketConnectionState.CONNECTED);
}
public void reconnect() throws WebSocketException {
Log.d(TAG, "reconnect() started.");
checkIfCalledOnValidThread();
closeEvent = false;
WebSocket ws = getWss();
try {
ws.recreate().connectAsynchronously()
.addListener(new WebSocketListener() {
@Override
public void onStateChanged(WebSocket websocket, WebSocketState newState) throws Exception {
}
@Override
public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
setConnectionState(WebSocketConnectionState.CONNECTED);
events.onOpen(WebSocketState.OPEN);
}
@Override
public void onConnectError(WebSocket websocket, WebSocketException cause) throws Exception {
setConnectionState(WebSocketConnectionState.ERROR);
events.onError(cause);
}
@Override
public void onDisconnected(WebSocket websocket, WebSocketFrame serverCloseFrame, WebSocketFrame clientCloseFrame, boolean closedByServer) throws Exception {
setConnectionState(WebSocketConnectionState.CLOSED);
events.onClose(1000, "no reason", closedByServer);
}
@Override
public void onFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onContinuationFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onBinaryFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onCloseFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onPingFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onPongFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onTextMessage(WebSocket websocket, String message) {
setConnectionState(WebSocketConnectionState.CONNECTED);
Log.d(TAG,"method reconnect() onTextMessage(): " + message);
onMessageListener(message);
}
@Override
public void onBinaryMessage(WebSocket websocket, byte[] binary) throws Exception {
}
@Override
public void onSendingFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onFrameUnsent(WebSocket websocket, WebSocketFrame frame) throws Exception {
}
@Override
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
setConnectionState(WebSocketConnectionState.ERROR);
events.onError(cause);
}
@Override
public void onFrameError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame) throws Exception {
}
@Override
public void onMessageError(WebSocket websocket, WebSocketException cause, List<WebSocketFrame> frames) throws Exception {
}
@Override
public void onMessageDecompressionError(WebSocket websocket, WebSocketException cause, byte[] compressed) throws Exception {
}
@Override
public void onTextMessageError(WebSocket websocket, WebSocketException cause, byte[] data) throws Exception {
}
@Override
public void onSendError(WebSocket websocket, WebSocketException cause, WebSocketFrame frame) throws Exception {
}
@Override
public void onUnexpectedError(WebSocket websocket, WebSocketException cause) throws Exception {
}
@Override
public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception {
}
@Override
public void onSendingHandshake(WebSocket websocket, String requestLine, List<String[]> headers) throws Exception {
}
});
} catch (IOException e) {
e.printStackTrace();
}
if(wss.isOpen()) setConnectionState(WebSocketConnectionState.CONNECTED);
}
public void disconnect(boolean waitForComplete) {
checkIfCalledOnValidThread();
if (wss.isOpen()) {
wss.sendClose();
connectionState = WebSocketConnectionState.CLOSED;
if (waitForComplete) {
synchronized (closeEventLock) {
while (!closeEvent) {
try {
closeEventLock.wait(CLOSE_TIMEOUT);
break;
} catch (InterruptedException e) {
Log.e(TAG, "WebSocket wait error: " + e.toString());
}
}
}
}
}
}
public void sendRequest(JsonRpcRequest request) throws WebSocketException {
Log.d(TAG, "JsonRpcWebSocketClient -> sendRequest(): "+request.toString());
checkIfCalledOnValidThread();
wss.sendText(request.toString());
}
public void sendNotification(JsonRpcNotification notification) throws WebSocketException {
checkIfCalledOnValidThread();
wss.sendText(notification.toString());
//client.send(notification.toString());
}
public void setConnectionState(WebSocketConnectionState webSocketConnectionState){
this.connectionState = webSocketConnectionState;
}
public WebSocketConnectionState getConnectionState(){
if(connectionState == null) {
return connectionState = WebSocketConnectionState.CLOSED;
}
if(wss.isOpen()) connectionState = WebSocketConnectionState.CONNECTED;
return connectionState;
}
private void checkIfCalledOnValidThread() {
if (!executor.checkOnLooperThread()) {
throw new IllegalStateException("WebSocket method is not called on valid thread");
}
}
public SSLSocketFactory getSSLScoketFactory(){
return sslctx.getSocketFactory();
}
public SSLContext getSSLContext(){
return sslctx;
}
public void setSSLContext(SSLContext ks){
this.sslctx = ks;
}
public WebSocket getWss(){
try {
Log.d(TAG, "getWss: started.");
SSLContext ctx = getSSLContext();
SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();
WebSocket ws = new WebSocketFactory()
.setSSLContext(getSSLContext())
.setSSLSocketFactory(sslSocketFactory)
.setConnectionTimeout(Constants.WSS_TIMEOUT)
.createSocket(Constants.WSS_ROOM_URI)
.setPingInterval(1000 * 24)
.addExtension(WebSocketExtension.PERMESSAGE_DEFLATE);
return ws;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void testSocket() throws Exception
{
new WebSocketFactory()
.createSocket("wss://echo.websocket.org")
.addListener(new WebSocketAdapter() {
@Override
public void onTextMessage(WebSocket ws, String message) {
// Received a response. Print the received message.
System.out.println(message);
// Close the WebSocket connection.
ws.disconnect();
}
})
.connect()
.sendText("Hello.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment