diff --git a/socket.js b/socket.js index 43a33d5..a0d5b90 100644 --- a/socket.js +++ b/socket.js @@ -10,9 +10,54 @@ function Socket() { this.socketKey = guid(); } -Socket.create = function(callback) { +//Socket.create = function(/*callback*/) { +// +// var socket = new Socket(); +// +// function socketEventHandler(event) { +// +// var payload = event.payload; +// +// if (payload.socketKey !== socket.socketKey) { +// return; +// } +// +// switch(payload.type) { +// case "Close": +// console.debug("SocketsForCordova: Close event, socket key: " + payload.socketKey); +// window.document.removeEventListener(SOCKET_EVENT, socketEventHandler); +// socket.onClose(); +// break; +// case "DataReceived": +// console.debug("SocketsForCordova: DataReceived event, socket key: " + payload.socketKey); +// socket.onData(new Int8Array(payload.data)); +// break; +// case "Error": +// console.debug("SocketsForCordova: Error event, socket key: " + payload.socketKey); +// socket.onError(payload.errorMessage); +// break; +// default: +// console.error("SocketsForCordova: Unknown event type " + payload.type + ", socket key: " + payload.socketKey); +// break; +// } +// } +// +// window.document.addEventListener(SOCKET_EVENT, socketEventHandler); +// +// exec( +// function() { +// console.debug("SocketsForCordova: Socket object successfully constructed."); +// callback(socket); +// }, +// function(error) { +// console.error("SocketsForCordova: Unexpected error during constructing Socket object. Error: " + error); +// }, +// CORDOVA_SERVICE_NAME, +// "create", +// [ socket.socketKey ]); +//}; - var socket = new Socket(); +Socket.prototype.open = function (host, port, success, error) { function socketEventHandler(event) { @@ -42,35 +87,20 @@ Socket.create = function(callback) { } } - window.document.addEventListener(SOCKET_EVENT, socketEventHandler); - exec( function() { - console.debug("SocketsForCordova: Socket object successfully constructed."); - callback(socket); - }, - function(error) { - console.error("SocketsForCordova: Unexpected error during constructing Socket object. Error: " + error); - }, - CORDOVA_SERVICE_NAME, - "create", - [ socket.socketKey ]); -}; - -Socket.prototype.connect = function (host, port, success, error) { - exec( - function() { - console.debug("SocketsForCordova: Socket successfully connected."); + console.debug("SocketsForCordova: Socket successfully opened."); + window.document.addEventListener(SOCKET_EVENT, socketEventHandler); if (success) success(); }, function(errorMessage) { - console.error("SocketsForCordova: Error during socket connecting. Error: " + errorMessage); + console.error("SocketsForCordova: Error during opening socket. Error: " + errorMessage); if (error) error(errorMessage); }, CORDOVA_SERVICE_NAME, - "connect", + "open", [ this.socketKey, host, port ]); }; diff --git a/src/android/src/cz/blocshop/socketsforcordova/SocketAdapter.java b/src/android/src/cz/blocshop/socketsforcordova/SocketAdapter.java index 8eb6c70..4e29b6b 100644 --- a/src/android/src/cz/blocshop/socketsforcordova/SocketAdapter.java +++ b/src/android/src/cz/blocshop/socketsforcordova/SocketAdapter.java @@ -5,11 +5,12 @@ import java.net.SocketException; public interface SocketAdapter { - public void connect(String host, int port) throws Throwable; + public void open(String host, int port) throws Throwable; public void write(byte[] data) throws IOException; + public void shutdownWrite() throws IOException; public void close() throws IOException; public void setOptions(SocketAdapterOptions options) throws SocketException; public void setDataConsumer(Consumer dataConsumer); public void setCloseEventHandler(Consumer closeEventHandler); - public void setErrorHandler(Consumer errorHandler); + public void setErrorHandler(Consumer errorHandler); } \ No newline at end of file diff --git a/src/android/src/cz/blocshop/socketsforcordova/SocketAdapterImpl.java b/src/android/src/cz/blocshop/socketsforcordova/SocketAdapterImpl.java index 008dae8..681a0de 100644 --- a/src/android/src/cz/blocshop/socketsforcordova/SocketAdapterImpl.java +++ b/src/android/src/cz/blocshop/socketsforcordova/SocketAdapterImpl.java @@ -1,7 +1,6 @@ package cz.blocshop.socketsforcordova; import java.io.IOException; -import java.io.InvalidObjectException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; @@ -19,7 +18,7 @@ public class SocketAdapterImpl implements SocketAdapter { private Consumer dataConsumer; private Consumer closeEventHandler; - private Consumer exceptionHandler; + private Consumer exceptionHandler; private ExecutorService executor; @@ -29,8 +28,8 @@ public class SocketAdapterImpl implements SocketAdapter { } @Override - public void connect(String host, int port) throws Throwable { - this.connectSocket(host, port); + public void open(String host, int port) throws Throwable { + this.openWithBackgroundThread(host, port); this.submitReadTask(); } @@ -39,11 +38,14 @@ public class SocketAdapterImpl implements SocketAdapter { this.socket.getOutputStream().write(data); } + @Override + public void shutdownWrite() throws IOException { + this.socket.shutdownOutput(); + } + @Override public void close() throws IOException { - if (!this.socket.isClosed()) { - this.socket.shutdownOutput(); - } + this.socket.close(); } @Override @@ -82,24 +84,25 @@ public class SocketAdapterImpl implements SocketAdapter { } @Override - public void setErrorHandler(Consumer exceptionHandler) { + public void setErrorHandler(Consumer exceptionHandler) { this.exceptionHandler = exceptionHandler; } - private void connectSocket(final String host, final int port) throws Throwable { - Future future = this.executor.submit(new Runnable() { + private void openWithBackgroundThread(final String host, final int port) throws Throwable { + Future future = this.executor.submit(new Runnable() { @Override public void run() { try { socket.connect(new InetSocketAddress(host, port)); } catch (IOException e) { - Logging.Error(SocketAdapterImpl.class.getName(), "Error during connecting of socket", e); + Logging.Error(SocketAdapterImpl.class.getName(), "Error during connecting of socket", e.getCause()); + throw new RuntimeException(e); } } }); try { - Object result = future.get(); + future.get(); } catch (ExecutionException e) { throw e.getCause(); @@ -122,7 +125,7 @@ public class SocketAdapterImpl implements SocketAdapter { } catch (Throwable e) { Logging.Error(SocketAdapterImpl.class.getName(), "Error during reading of socket input stream", e); hasError = true; - invokeExceptionHandler(e); + invokeExceptionHandler(e.getMessage()); } finally { try { socket.close(); @@ -159,9 +162,9 @@ public class SocketAdapterImpl implements SocketAdapter { } } - private void invokeExceptionHandler(Throwable exception) { + private void invokeExceptionHandler(String errorMessage) { if (this.exceptionHandler != null) { - this.exceptionHandler.accept(exception); + this.exceptionHandler.accept(errorMessage); } } } diff --git a/src/android/src/cz/blocshop/socketsforcordova/SocketPlugin.java b/src/android/src/cz/blocshop/socketsforcordova/SocketPlugin.java index 862892e..369db58 100644 --- a/src/android/src/cz/blocshop/socketsforcordova/SocketPlugin.java +++ b/src/android/src/cz/blocshop/socketsforcordova/SocketPlugin.java @@ -1,13 +1,11 @@ package cz.blocshop.socketsforcordova; -import android.annotation.SuppressLint; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; + import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaArgs; import org.apache.cordova.CordovaPlugin; @@ -15,6 +13,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import android.annotation.SuppressLint; public class SocketPlugin extends CordovaPlugin { @@ -23,12 +22,12 @@ public class SocketPlugin extends CordovaPlugin { @Override public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException { - if(action.equals("create")) { - this.create(args, callbackContext); - } else if (action.equals("connect")) { - this.connect(args, callbackContext); + if (action.equals("open")) { + this.open(args, callbackContext); } else if (action.equals("write")) { this.write(args, callbackContext); + } else if (action.equals("shutdownWrite")) { + this.shutdownWrite(args, callbackContext); } else if (action.equals("close")) { this.close(args, callbackContext); } else if (action.equals("setOptions")) { @@ -40,29 +39,19 @@ public class SocketPlugin extends CordovaPlugin { return true; } - private void create(CordovaArgs args, CallbackContext callbackContext) throws JSONException { - - final String socketKey = args.getString(0); + private void open(CordovaArgs args, CallbackContext callbackContext) throws JSONException { + String socketKey = args.getString(0); + String host = args.getString(1); + int port = args.getInt(2); SocketAdapter socketAdapter = new SocketAdapterImpl(); socketAdapter.setCloseEventHandler(new CloseEventHandler(socketKey)); socketAdapter.setDataConsumer(new DataConsumer(socketKey)); socketAdapter.setErrorHandler(new ErrorHandler(socketKey)); - - this.socketAdapters.put(socketKey, socketAdapter); - - callbackContext.success(socketKey); - } - - private void connect(CordovaArgs args, CallbackContext callbackContext) throws JSONException { - String socketKey = args.getString(0); - String host = args.getString(1); - int port = args.getInt(2); - - SocketAdapter socket = this.getSocketAdapter(socketKey); try { - socket.connect(host, port); + socketAdapter.open(host, port); + this.socketAdapters.put(socketKey, socketAdapter); callbackContext.success(); } catch (Throwable t) { callbackContext.error(t.toString()); @@ -87,6 +76,19 @@ public class SocketPlugin extends CordovaPlugin { callbackContext.error(e.toString()); } } + + private void shutdownWrite(CordovaArgs args, CallbackContext callbackContext) throws JSONException { + String socketKey = args.getString(0); + + SocketAdapter socket = this.getSocketAdapter(socketKey); + + try { + socket.shutdownWrite(); + callbackContext.success(); + } catch (IOException e) { + callbackContext.error(e.toString()); + } + } private void close(CordovaArgs args, CallbackContext callbackContext) throws JSONException { String socketKey = args.getString(0); @@ -135,8 +137,7 @@ public class SocketPlugin extends CordovaPlugin { private SocketAdapter getSocketAdapter(String socketKey) { if (!this.socketAdapters.containsKey(socketKey)) { - throw new IllegalArgumentException( - String.format("Cannot find socketKey: %s. Connection is probably closed.", socketKey)); + throw new IllegalStateException("Socket isn't connected."); } return this.socketAdapters.get(socketKey); } @@ -197,17 +198,17 @@ public class SocketPlugin extends CordovaPlugin { } } - private class ErrorHandler implements Consumer { + private class ErrorHandler implements Consumer { private String socketKey; public ErrorHandler(String socketKey) { this.socketKey = socketKey; } @Override - public void accept(Throwable exception) { + public void accept(String errorMessage) { try { JSONObject event = new JSONObject(); event.put("type", "Error"); - event.put("errorMessage", exception.toString()); + event.put("errorMessage", errorMessage); event.put("socketKey", socketKey); dispatchEvent(event);