Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jul 10th, 2012  |  syntax: None  |  size: 9.72 KB  |  hits: 18  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /**
  2.  * Appcelerator Titanium Mobile
  3.  * Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
  4.  * Licensed under the terms of the Apache Public License
  5.  * Please see the LICENSE included with this distribution for details.
  6.  */
  7.  
  8. package ti.modules.titanium.network.socket;
  9.  
  10. import java.io.IOException;
  11. import java.net.ServerSocket;
  12. import java.net.Socket;
  13. import java.net.UnknownHostException;
  14.  
  15. import org.appcelerator.kroll.KrollDict;
  16. import org.appcelerator.kroll.KrollProxy;
  17. import org.appcelerator.kroll.annotations.Kroll;
  18. import org.appcelerator.titanium.TiContext;
  19. import org.appcelerator.titanium.io.TiStream;
  20. import org.appcelerator.titanium.kroll.KrollCallback;
  21. import org.appcelerator.titanium.proxy.BufferProxy;
  22. import org.appcelerator.titanium.util.Log;
  23. import org.appcelerator.titanium.util.TiConfig;
  24. import org.appcelerator.titanium.util.TiConvert;
  25. import org.appcelerator.titanium.util.TiStreamHelper;
  26.  
  27.  
  28. @Kroll.proxy(creatableInModule=SocketModule.class)
  29. public class TCPProxy extends KrollProxy implements TiStream
  30. {
  31.         @Kroll.constant public static final int SOCKET_INITIALIZED = 1;
  32.         @Kroll.constant public static final int SOCKET_CONNECTED = 2;
  33.         @Kroll.constant public static final int SOCKET_LISTENING = 3;
  34.         @Kroll.constant public static final int SOCKET_CLOSED = 4;
  35.         @Kroll.constant public static final int SOCKET_ERROR = 5;
  36.  
  37.         @Kroll.constant public int state = 0;
  38.  
  39.  
  40.         private static final String LCAT = "TCPProxy";
  41.         private static final boolean DBG = TiConfig.LOGD;
  42.  
  43.         private boolean initialized = false;
  44.         private Socket clientSocket;
  45.         private ServerSocket serverSocket;
  46.         private boolean accepting;
  47.         private KrollDict acceptOptions;
  48.  
  49.  
  50.         public TCPProxy(TiContext context)
  51.         {
  52.                 super(context);
  53.                 state = SOCKET_INITIALIZED; // TODO is this the right place to init?
  54.         }
  55.  
  56.         @Kroll.method
  57.         public void connect() throws Exception
  58.         {
  59.                 Object host = getProperty("host");
  60.                 Object port = getProperty("port");
  61.                 if((host != null) && (port != null)) {
  62.                         initialized = true;
  63.                         new ConnectedSocketThread().start();
  64.  
  65.                 } else {
  66.                         throw new Exception("unable to call connect, socket must have a valid host and port");
  67.                 }
  68.         }
  69.  
  70.         @Kroll.method
  71.         public void listen(int queueSize) throws Exception
  72.         {
  73.                 Object port = getProperty("port");
  74.                 if(port != null) {
  75.                         initialized = true;
  76.  
  77.                         try {
  78.                                 serverSocket = new ServerSocket(TiConvert.toInt(port), queueSize);
  79.                                 new ListeningSocketThread(queueSize).start();
  80.                                 state = SOCKET_LISTENING;
  81.  
  82.                         } catch (IOException e) {
  83.                                 e.printStackTrace();
  84.                                 throw new Exception("Unable to listen, IO error");
  85.                         }
  86.  
  87.                 } else {
  88.                         throw new Exception("unable to call listen, socket must have a valid port");
  89.                 }
  90.         }
  91.  
  92.         @Kroll.method
  93.         public void accept(KrollDict acceptOptions)
  94.         {
  95.                 if(!initialized) {
  96.                         Log.e(LCAT, "Socket is not initialized, unable to call accept");
  97.                         return;
  98.                 }
  99.  
  100.                 this.acceptOptions = acceptOptions;
  101.                 accepting = true;
  102.         }
  103.  
  104.         @Kroll.method
  105.         public void close()
  106.         {
  107.                 if(!initialized) {
  108.                         Log.e(LCAT, "Socket is not initialized, unable to call close");
  109.                         return;
  110.                 }
  111.  
  112.                 try {
  113.                         clientSocket.close();
  114.                         updateState(SOCKET_CLOSED, "closed", buildClosedCallbackArgs());
  115.  
  116.                 } catch (IOException e) {
  117.                         e.printStackTrace();
  118.                         updateState(SOCKET_ERROR, "error", buildErrorCallbackArgs("Unable to close socket, IO error", 0));
  119.                 }
  120.         }
  121.  
  122.         @Kroll.setProperty @Kroll.method
  123.         public void setHost(String host)
  124.         {
  125.                 setSocketProperty("host", host);
  126.         }
  127.  
  128.         @Kroll.setProperty @Kroll.method
  129.         public void setPort(int port)
  130.         {
  131.                 setSocketProperty("port", port);
  132.         }
  133.  
  134.         @Kroll.setProperty @Kroll.method
  135.         public void setTimeout(int timeout)
  136.         {
  137.                 setSocketProperty("timeout", timeout);
  138.         }
  139.  
  140.         @Kroll.setProperty @Kroll.method
  141.         public void setOptions()
  142.         {
  143.                 // not implemented yet - reserved for future use
  144.                 Log.i(LCAT, "setting options on socket is not supported yet");
  145.         }
  146.  
  147.         @Kroll.setProperty @Kroll.method
  148.         public void setConnected(KrollCallback connected)
  149.         {
  150.                 setSocketProperty("connected", connected);
  151.         }
  152.  
  153.         @Kroll.setProperty @Kroll.method
  154.         public void setError(KrollCallback error)
  155.         {
  156.                 setSocketProperty("error", error);
  157.         }
  158.  
  159.         @Kroll.setProperty @Kroll.method
  160.         public void setClosed(KrollCallback closed)
  161.         {
  162.                 setSocketProperty("closed", closed);
  163.         }
  164.  
  165.         @Kroll.setProperty @Kroll.method
  166.         public void setAccepted(KrollCallback accepted)
  167.         {
  168.                 setSocketProperty("accepted", accepted);
  169.         }
  170.  
  171.         private void setSocketProperty(String propertyName, Object propertyValue)
  172.         {
  173.                 if(!initialized) {
  174.                         setProperty(propertyName, propertyValue);
  175.  
  176.                 } else {
  177.                         Log.e(LCAT, "Socket is already initialized, unable to set property <" + propertyName + ">");
  178.                 }
  179.         }
  180.  
  181.         private class ConnectedSocketThread extends Thread
  182.         {
  183.                 public ConnectedSocketThread()
  184.                 {
  185.                         super("ConnectedSocketThread");
  186.                 }
  187.  
  188.                 public void run()
  189.                 {
  190.                         String host = TiConvert.toString(getProperty("host"));
  191.  
  192.                         try {
  193.                                 clientSocket = new Socket(host, TiConvert.toInt(getProperty("port")));
  194.                                 updateState(SOCKET_CONNECTED, "connected", buildConnectedCallbackArgs());
  195.  
  196.                         } catch (UnknownHostException e) {
  197.                                 e.printStackTrace();
  198.                                 updateState(SOCKET_ERROR, "error", buildErrorCallbackArgs("Unable to connect, unknown host <" + host + ">", 0));
  199.  
  200.                         } catch (IOException e) {
  201.                                 e.printStackTrace();
  202.                                 updateState(SOCKET_ERROR, "error", buildErrorCallbackArgs("Unable to connect to , IO error", 0));
  203.                         }
  204.                 }
  205.         }
  206.  
  207.         private class ListeningSocketThread extends Thread
  208.         {
  209.                 public ListeningSocketThread(int queueSize)
  210.                 {
  211.                         super("ListeningSocketThread");
  212.                 }
  213.  
  214.                 public void run()
  215.                 {
  216.                         while(true) {
  217.                                 if(accepting) {
  218.                                         try {
  219.                                                 Socket acceptedSocket = serverSocket.accept();
  220.  
  221.                                                 TCPProxy acceptedTcpProxy = new TCPProxy(context);
  222.                                                 acceptedTcpProxy.clientSocket = acceptedSocket;
  223.  
  224.                                                 Object optionValue;
  225.                                                 if((optionValue = acceptOptions.get("timeout")) != null) {
  226.                                                         acceptedTcpProxy.setProperty("timeout", TiConvert.toInt(optionValue));
  227.                                                 }
  228.                                                 if((optionValue = acceptOptions.get("error")) != null) {
  229.                                                         if(optionValue instanceof KrollCallback) {
  230.                                                                 acceptedTcpProxy.setProperty("error", (KrollCallback) optionValue);
  231.                                                         }
  232.                                                 }
  233.                                                 if((optionValue = acceptOptions.get("closed")) != null) {
  234.                                                         if(optionValue instanceof KrollCallback) {
  235.                                                                 acceptedTcpProxy.setProperty("closed", (KrollCallback) optionValue);
  236.                                                         }
  237.                                                 }
  238.  
  239.                                                 updateState(SOCKET_CONNECTED, "accepted", buildAcceptedCallbackArgs(acceptedTcpProxy));
  240.                                                 accepting = false;
  241.  
  242.                                         } catch (IOException e) {
  243.                                                 e.printStackTrace();
  244.                                                 updateState(SOCKET_ERROR, "error", buildErrorCallbackArgs("Unable to accept new connection, IO error", 0));
  245.                                         }
  246.  
  247.                                 } else {
  248.                                         try {
  249.                                                 sleep(500);
  250.  
  251.                                         } catch (InterruptedException e) {
  252.                                                 e.printStackTrace();
  253.                                                 Log.e(LCAT, "listening thread interrupted");
  254.                                         }
  255.                                 }
  256.                         }
  257.                 }
  258.         }
  259.  
  260.         private Object[] buildConnectedCallbackArgs()
  261.         {
  262.                 KrollDict callbackArgs = new KrollDict();
  263.                 callbackArgs.put("socket", this);
  264.  
  265.                 return (new Object[] {callbackArgs});
  266.         }
  267.  
  268.         private Object[] buildErrorCallbackArgs(String error, int errorCode)
  269.         {
  270.                 KrollDict callbackArgs = new KrollDict();
  271.                 callbackArgs.put("socket", this);
  272.                 callbackArgs.put("error", error);
  273.                 callbackArgs.put("errorCode", errorCode);
  274.  
  275.                 return (new Object[] {callbackArgs});
  276.         }
  277.  
  278.         private Object[] buildClosedCallbackArgs()
  279.         {
  280.                 KrollDict callbackArgs = new KrollDict();
  281.                 callbackArgs.put("socket", this);
  282.  
  283.                 return (new Object[] {callbackArgs});
  284.         }
  285.  
  286.         private Object[] buildAcceptedCallbackArgs(TCPProxy acceptedTcpProxy)
  287.         {
  288.                 KrollDict callbackArgs = new KrollDict();
  289.                 callbackArgs.put("socket", this);
  290.                 callbackArgs.put("inbound", acceptedTcpProxy);
  291.  
  292.                 return (new Object[] {callbackArgs});
  293.         }
  294.  
  295.         public void updateState(int state, String callbackName, Object[] callbackArgs)
  296.         {
  297.                 this.state = state;
  298.  
  299.                 Object callback = getProperty(callbackName);
  300.                 if(callback instanceof KrollCallback) {
  301.                         ((KrollCallback) callback).callAsync(callbackArgs);
  302.                 }
  303.         }
  304.  
  305.         @Kroll.method
  306.         public boolean isConnected()
  307.         {
  308.                 if(state == SOCKET_CONNECTED)
  309.                 {
  310.                         return true;
  311.                 }
  312.                 return false;
  313.         }
  314.  
  315.  
  316.         // TiStream interface methods
  317.         @Kroll.method
  318.         public int read(BufferProxy bufferProxy) throws IOException
  319.         {
  320.                 try{
  321.                         return TiStreamHelper.read(clientSocket.getInputStream(), bufferProxy);
  322.  
  323.                 } catch (IOException e) {
  324.                         e.printStackTrace();
  325.                         clientSocket.close();
  326.                         throw new IOException("Unable to read from socket, IO error");
  327.                 }
  328.         }
  329.  
  330.         @Kroll.method
  331.         public int read(BufferProxy bufferProxy, int offset, int length) throws IOException
  332.         {
  333.                 try {
  334.                         return TiStreamHelper.read(clientSocket.getInputStream(), bufferProxy, offset, length);
  335.  
  336.                 } catch (IOException e) {
  337.                         e.printStackTrace();
  338.                         clientSocket.close();
  339.                         throw new IOException("Unable to read from socket, IO error");
  340.                 }
  341.         }
  342.  
  343.         @Kroll.method
  344.         public int write(BufferProxy bufferProxy) throws IOException
  345.         {
  346.                 try {
  347.                         return TiStreamHelper.write(clientSocket.getOutputStream(), bufferProxy);
  348.  
  349.                 } catch (IOException e) {
  350.                         e.printStackTrace();
  351.                         clientSocket.close();
  352.                         throw new IOException("Unable to write to socket, IO error");
  353.                 }
  354.         }
  355.  
  356.         @Kroll.method
  357.         public int write(BufferProxy bufferProxy, int offset, int length) throws IOException
  358.         {
  359.                 try {
  360.                         return TiStreamHelper.write(clientSocket.getOutputStream(), bufferProxy, offset, length);
  361.  
  362.                 } catch (IOException e) {
  363.                         e.printStackTrace();
  364.                         clientSocket.close();
  365.                         throw new IOException("Unable to write to socket, IO error");
  366.                 }
  367.         }
  368.  
  369.         @Kroll.method
  370.         public boolean isWriteable()
  371.         {
  372.                 return isConnected();
  373.         }
  374.  
  375.         @Kroll.method
  376.         public boolean isReadable()
  377.         {
  378.                 return isConnected();
  379.         }
  380. }