/*
* Copyright (C) 2013-2014 Sony Computer Science Laboratories, Inc. All Rights Reserved.
* Copyright (C) 2014 Sony Corporation. All Rights Reserved.
*/
package com.sonycsl.Kadecot.server;
import android.os.Build;
import android.util.Log;
import com.sonycsl.Kadecot.wamp.KadecotProtocolSetupCallback;
import com.sonycsl.Kadecot.wamp.KadecotWampClient;
import com.sonycsl.Kadecot.wamp.KadecotWampPeerLocator;
import com.sonycsl.Kadecot.wamp.KadecotWampRouter;
import com.sonycsl.Kadecot.wamp.KadecotWampSetupCallback;
import com.sonycsl.Kadecot.wamp.KadecotWebSocketClient;
import com.sonycsl.wamp.WampError;
import com.sonycsl.wamp.WampRouter;
import com.sonycsl.wamp.message.WampMessage;
import com.sonycsl.wamp.message.WampMessageFactory;
import org.java_websocket.WebSocket;
import org.java_websocket.WebSocketImpl;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_10;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.drafts.Draft_75;
import org.java_websocket.drafts.Draft_76;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class KadecotWebSocketServer {
private static final String TAG = KadecotWebSocketServer.class.getSimpleName();
private static final String WAMP_PROTOCOL = "wamp.2.json";
private static final int portno = 41314;
protected static KadecotWebSocketServer sInstance = null;
private WebSocketServerImpl mWebSocketServer = null;
private boolean mStarted = false;
private KadecotWampRouter mRouter;
private CountDownLatch mSystemSetup;
private CountDownLatch mWampSetup;
public synchronized static KadecotWebSocketServer getInstance() {
if (sInstance == null) {
sInstance = new KadecotWebSocketServer();
}
return sInstance;
}
private KadecotWebSocketServer() {
if (Build.PRODUCT.startsWith("sdk")) {
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
}
mRouter = KadecotWampPeerLocator.getRouter();
mSystemSetup = new CountDownLatch(KadecotWampPeerLocator.getSystemClients().length);
for (KadecotWampClient client : KadecotWampPeerLocator.getSystemClients()) {
client.connect(mRouter);
client.setCallback(new KadecotWampSetupCallback(
client.getTopicsToSubscribe(), client.getRegisterableProcedures()
.keySet(),
new KadecotWampSetupCallback.OnCompletionListener() {
@Override
public void onCompletion() {
mSystemSetup.countDown();
}
}));
}
mWampSetup = new CountDownLatch(KadecotWampPeerLocator.getProtocolClients().length);
for (KadecotWampClient client : KadecotWampPeerLocator.getProtocolClients()) {
client.connect(mRouter);
client.setCallback(new KadecotProtocolSetupCallback(client.getSubscribableTopics(),
client.getRegisterableProcedures(),
new KadecotProtocolSetupCallback.OnCompletionListener() {
@Override
public void onCompletion() {
}
}));
client.setCallback(new KadecotWampSetupCallback(client.getTopicsToSubscribe(), client
.getRegisterableProcedures().keySet(),
new KadecotWampSetupCallback.OnCompletionListener() {
@Override
public void onCompletion() {
mWampSetup.countDown();
}
}));
}
WebSocketImpl.DEBUG = false;// true;
}
public WampRouter getWampRouter() {
return mRouter;
}
public synchronized void start() {
if (isStarted()) {
return;
}
stop();
List<Draft> draftList = new ArrayList<Draft>();
draftList.add(new Draft_17_Protocol(WAMP_PROTOCOL));
draftList.add(new Draft_17());
draftList.add(new Draft_10_Protocol(WAMP_PROTOCOL));
draftList.add(new Draft_10());
draftList.add(new Draft_76_Protocol(WAMP_PROTOCOL));
draftList.add(new Draft_76());
draftList.add(new Draft_75_Protocol(WAMP_PROTOCOL));
draftList.add(new Draft_75());
mWebSocketServer = new WebSocketServerImpl(new InetSocketAddress(portno), draftList);
mWebSocketServer.start();
for (KadecotWampClient client : KadecotWampPeerLocator.getSystemClients()) {
client.transmit(WampMessageFactory.createHello(KadecotWampRouter.REALM,
new JSONObject()));
}
try {
mSystemSetup.await(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
Log.e(TAG, "unable to setup KadecotWampClient");
return;
}
for (KadecotWampClient client : KadecotWampPeerLocator.getProtocolClients()) {
client.transmit(WampMessageFactory.createHello(KadecotWampRouter.REALM,
new JSONObject()));
}
try {
mWampSetup.await(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
Log.e(TAG, "unable to setup Wamp");
return;
}
mStarted = true;
}
public synchronized boolean isStarted() {
return mStarted;
}
public synchronized void stop() {
if (!isStarted()) {
return;
}
try {
if (mWebSocketServer != null) {
mWebSocketServer.stop();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (KadecotWampClient client : KadecotWampPeerLocator.getProtocolClients()) {
client.transmit(WampMessageFactory.createGoodbye(new JSONObject(),
WampError.CLOSE_REALM));
}
for (KadecotWampClient client : KadecotWampPeerLocator.getSystemClients()) {
client.transmit(WampMessageFactory.createGoodbye(new JSONObject(),
WampError.CLOSE_REALM));
}
mWebSocketServer = null;
mStarted = false;
}
public class WebSocketServerImpl extends WebSocketServer {
private Map<WebSocket, KadecotWebSocketClient> mClients = new ConcurrentHashMap<WebSocket, KadecotWebSocketClient>();
public WebSocketServerImpl(InetSocketAddress address, List<Draft> draftList) {
super(address, draftList);
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
KadecotWebSocketClient client = new KadecotWebSocketClient(conn);
client.connect(mRouter);
mClients.put(conn, client);
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
mClients.remove(conn);
}
@Override
public void onMessage(WebSocket conn, String message) {
if (mClients.containsKey(conn)) {
try {
WampMessage msg = WampMessageFactory.create(new JSONArray(message));
mClients.get(conn).transmit(msg);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
@Override
public void onError(WebSocket conn, Exception ex) {
}
@Override
public synchronized void stop(int timeout) throws IOException, InterruptedException {
super.stop(timeout);
mClients.clear();
KadecotWebSocketServer.this.mWebSocketServer = null;
if (KadecotWebSocketServer.this.isStarted()) {
KadecotWebSocketServer.this.start();
}
}
}
}