Last active
March 15, 2017 06:18
-
-
Save mangadul/72b2ec0d465a59d648bee102e084f6d7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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