package mobi.monaca.framework.plugin;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Set;
import mobi.monaca.framework.util.NetworkUtils;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.apache.cordova.PluginResult.Status;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class WebSocketPlugin extends CordovaPlugin{
WebSocketServer server;
int port;
CallbackContext callbackContext;
HashMap<String, WebSocket> sockets = new HashMap<String, WebSocket>();
@Override
public boolean execute(String action, JSONArray args,
CallbackContext callbackContext) throws JSONException {
if(action.equalsIgnoreCase("start")){
if(server == null){
JSONObject params = args.getJSONObject(0);
this.port = params.getInt("port");
createServer(port);
server.start();
}
JSONObject result;
try {
result = createAddressJSON();
result.put("event", "server:started");
PluginResult pluginResult = new PluginResult(Status.OK, result);
pluginResult.setKeepCallback(true);
callbackContext.sendPluginResult(pluginResult);
this.callbackContext = callbackContext;
} catch (SocketException e) {
callbackContext.error(e.getMessage());
e.printStackTrace();
}
return true;
}
if(action.equalsIgnoreCase("getStatus")){
if(server == null){
JSONObject statusJSON = new JSONObject();
statusJSON.put("status", "stopped");
callbackContext.success(statusJSON);
}else{
JSONObject statusJSON;
try {
statusJSON = createAddressJSON();
statusJSON.put("status", "started");
JSONArray clients = new JSONArray(sockets.keySet());
statusJSON.put("clients", clients);
callbackContext.success(statusJSON);
} catch (SocketException e) {
callbackContext.error(e.getMessage());
e.printStackTrace();
}
}
return true;
}
if(action.equalsIgnoreCase("getAddress")){
if(server == null){
callbackContext.error("You need to start server first");
}else{
JSONObject result;
try {
result = createAddressJSON();
callbackContext.success(result);
} catch (SocketException e) {
callbackContext.error(e.getMessage());
e.printStackTrace();
}
}
return true;
}
if(action.equalsIgnoreCase("getClients")){
if(server == null){
callbackContext.error("You need to start server first");
}else{
JSONArray message = new JSONArray(sockets.keySet());
callbackContext.success(message);
}
return true;
}
if(action.equalsIgnoreCase("send")){
if(server == null){
callbackContext.error("You need to start server before sending a message");
}else{
JSONObject params = args.getJSONObject(0);
String clientId = params.getString("clientId");
String message = params.getString("message");
if(sockets.containsKey(clientId)){
WebSocket webSocket = sockets.get(clientId);
webSocket.send(message);
callbackContext.success();
}else{
callbackContext.error("client " + clientId + " is not yet connected");
}
}
return true;
}
if(action.equalsIgnoreCase("sendToAllClients")){
if(server == null){
callbackContext.error("You need to start server before sending a message");
}else{
JSONObject params = args.getJSONObject(0);
String message = params.getString("message");
Set<String> clients = sockets.keySet();
WebSocket webSocket;
for (String client : clients) {
webSocket = sockets.get(client);
webSocket.send(message);
}
JSONObject resultJSON = new JSONObject();
resultJSON.put("send", "success");
resultJSON.put("clientsSent", sockets.size());
callbackContext.success(resultJSON);
}
return true;
}
if(action.equalsIgnoreCase("stop")){
if(server != null){
try {
stopServer();
callbackContext.success();
} catch (Exception e) {
e.printStackTrace();
callbackContext.error(e.getMessage());
}
}else{
callbackContext.error("server not yet started");
}
return true;
}
return super.execute(action, args, callbackContext);
}
private void stopServer() throws IOException, InterruptedException {
server.stop();
sockets.clear();
server = null;
}
private JSONObject createAddressJSON() throws JSONException, SocketException {
JSONObject result = new JSONObject();
result.put("networks", NetworkUtils.getIPAddresses());
result.put("port", port);
return result;
}
@Override
public void onDestroy() {
if(server != null){
try {
stopServer();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
super.onDestroy();
}
private void createServer(int port){
server = new WebSocketServer(new InetSocketAddress(port)){
@Override
public void onClose(WebSocket webSocket, int arg1, String msg,
boolean arg3) {
String clientId = getClientId(webSocket);
sockets.remove(clientId);
try {
JSONObject message = createJSONMessage("disconnected", clientId);
message.put("message", msg);
PluginResult pluginResult = new PluginResult(Status.OK, message);
pluginResult.setKeepCallback(true);
WebSocketPlugin.this.callbackContext.sendPluginResult(pluginResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onError(WebSocket webSocket, Exception msg) {
String clientId = getClientId(webSocket);
try {
JSONObject message = createJSONMessage("error", clientId);
message.put("message", msg.toString());
PluginResult pluginResult = new PluginResult(Status.OK, message);
pluginResult.setKeepCallback(true);
WebSocketPlugin.this.callbackContext.sendPluginResult(pluginResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onMessage(WebSocket webSocket, String msg) {
String clientId = getClientId(webSocket);
try {
JSONObject message = createJSONMessage("message", clientId);
message.put("message", msg);
PluginResult pluginResult = new PluginResult(Status.OK, message);
pluginResult.setKeepCallback(true);
WebSocketPlugin.this.callbackContext.sendPluginResult(pluginResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
String clientId = getClientId(webSocket);
sockets.put(clientId, webSocket);
try {
JSONObject message = createJSONMessage("connected", clientId);
PluginResult pluginResult = new PluginResult(Status.OK, message);
pluginResult.setKeepCallback(true);
WebSocketPlugin.this.callbackContext.sendPluginResult(pluginResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
private String getClientId(WebSocket webSocket) {
if(webSocket != null){
String clientId = webSocket.getRemoteSocketAddress().toString();
return clientId;
}
return null;
}
};
}
private JSONObject createJSONMessage(String event, String clientId)
throws JSONException {
JSONObject message = new JSONObject();
message.put("event", event);
message.put("client", clientId);
return message;
}
}