PageRenderTime 50ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/de/fau/cs/mad/fasl/libs/Net.java

https://bitbucket.org/mad_fau/fasl
Java | 401 lines | 260 code | 45 blank | 96 comment | 34 complexity | bcaf201a54e7f422326fa1f4b42fe5e3 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-3.0
  1. /**
  2. * @file Net.java
  3. * @author Christian Dietrich <stettberger@dokucode.de>
  4. *
  5. * @brief Gives access to UDP and TCP communication
  6. *
  7. * Part of the FASL project and licensed under the GNU LGPL.
  8. * See README and COPYING.LESSER for details.
  9. */
  10. package de.fau.cs.mad.fasl.libs;
  11. import java.io.*;
  12. import java.net.*;
  13. // general settings
  14. import de.fau.cs.mad.fasl.LibraryClass;
  15. import de.fau.cs.mad.fasl.ast.AstType;
  16. import de.fau.cs.mad.fasl.interpreter.Scheduler;
  17. import de.fau.cs.mad.fasl.interpreter.Interpreter;
  18. import de.fau.cs.mad.fasl.libmanager.NeedsPermission;
  19. import de.fau.cs.mad.fasl.libmanager.IsLibraryMethod;
  20. import de.fau.cs.mad.fasl.libmanager.LibraryStruct;
  21. import de.fau.cs.mad.fasl.libmanager.IsLibraryStruct;
  22. import de.fau.cs.mad.fasl.libmanager.LibInfo;
  23. import android.Manifest.permission;
  24. /** The Net library provides access to UDP and TCP
  25. * communication. Client and server sockets are supported.
  26. *
  27. */
  28. public class Net extends LibraryClass
  29. {
  30. /** A udp socket handle
  31. */
  32. public static class UDPSocket extends LibraryStruct {
  33. private DatagramSocket clientSocket;
  34. public String lastSenderAddress;
  35. public Double lastSenderPort;
  36. }
  37. /**
  38. * Sends a UDP packet to a given ip address
  39. *
  40. * @param socket a udp socket
  41. * @param ipaddress a string identifying a remote machine
  42. * @param port UDP port
  43. * @param message the message that should be sent
  44. * @return whether the operation was a success
  45. */
  46. @IsLibraryMethod(params = "socket, ipaddress, port, message", description = "send udp packet")
  47. @NeedsPermission(permission.INTERNET)
  48. public static Boolean send(UDPSocket socket, String ipaddress, Double port, String message) {
  49. try {
  50. if (socket.clientSocket == null) {
  51. socket.clientSocket = new DatagramSocket();
  52. socket.clientSocket.setReuseAddress(true);
  53. }
  54. InetAddress IPAddress = InetAddress.getByName(ipaddress);
  55. byte[] sendData = message.getBytes();
  56. DatagramPacket sendPacket =
  57. new DatagramPacket(sendData, sendData.length, IPAddress, (int)(double)port);
  58. socket.clientSocket.send(sendPacket);
  59. } catch (UnknownHostException ex) {
  60. System.console("Unkown host: " + ipaddress);
  61. return false;
  62. } catch (IOException e) {
  63. System.console("UDP send failed:" + e);
  64. return false;
  65. }
  66. return true;
  67. }
  68. /**
  69. * Bind the UDP port to a certain port and ipaddress.
  70. *
  71. * @param socket a udp socket
  72. * @param ipaddress a string identifying a remote machine
  73. * @param port UDP port
  74. * @return whether the operation was a success
  75. */
  76. @IsLibraryMethod(params = "socket, ipaddress, port", description = "bind udp socket")
  77. @NeedsPermission(permission.INTERNET)
  78. public static Boolean bind(UDPSocket socket, String ipaddress, Double port) {
  79. try {
  80. InetAddress IPAddress = InetAddress.getByName(ipaddress);
  81. InetSocketAddress addr = new InetSocketAddress(IPAddress, (int)(double)port);
  82. socket.clientSocket = new DatagramSocket(addr);
  83. socket.clientSocket.setReuseAddress(true);
  84. } catch (UnknownHostException ex) {
  85. System.console("Unkown host: " + ipaddress);
  86. return false;
  87. } catch (IOException e) {
  88. System.console("UDP bin failed:" + e);
  89. return false;
  90. }
  91. return true;
  92. }
  93. /**
  94. * Receive UDP packet from previous bound socket. The sender of
  95. * the packet is stored within the socket. (lastSenderAddress,
  96. * lastSenderPort)
  97. *
  98. * @param socket a udp socket
  99. * @return The udp packet's content. null on error
  100. */
  101. @IsLibraryMethod(params = "socket", description = "receive udp packet")
  102. @NeedsPermission(permission.INTERNET)
  103. public static String receive(final UDPSocket socket) {
  104. if (socket == null || socket.clientSocket == null) {
  105. throw new IllegalArgumentException("socket must not be null");
  106. }
  107. final Scheduler scheduler = Scheduler.getInstance();
  108. final Interpreter current = scheduler.getCurrentTask();
  109. Thread t = new Thread() {
  110. @Override
  111. public void run() {
  112. try {
  113. byte[] receiveData = new byte[1600];
  114. DatagramPacket receivePacket =
  115. new DatagramPacket(receiveData, receiveData.length);
  116. socket.clientSocket.receive(receivePacket);
  117. String data = new String(receivePacket.getData());
  118. InetAddress IPAddress = receivePacket.getAddress();
  119. socket.lastSenderAddress = IPAddress.toString();
  120. socket.lastSenderPort = (double)receivePacket.getPort();
  121. if (!current.isTerminated()) {
  122. current.pushOntoStackFromLib(data, AstType.string);
  123. scheduler.awakeTask(current);
  124. }
  125. return;
  126. } catch (IOException e) {
  127. System.console("UDP bin failed:" + e);
  128. }
  129. if (!current.isTerminated()) {
  130. current.pushOntoStackFromLib(null, AstType.string);
  131. scheduler.awakeTask(current);
  132. }
  133. }
  134. };
  135. synchronized(scheduler) {
  136. t.start();
  137. // block current thread
  138. scheduler.pauseCurrentTask();
  139. return null; // never reached
  140. }
  141. }
  142. /**
  143. * Close a udp socket.
  144. *
  145. * @param socket a udp socket
  146. * @return The udp packet received. null on error
  147. */
  148. @IsLibraryMethod(params = "socket", description = "receive udp packet")
  149. public static void close(final UDPSocket socket) {
  150. if (socket == null) {
  151. return;
  152. }
  153. if (socket.clientSocket != null)
  154. socket.clientSocket.close();
  155. socket.clientSocket = null;
  156. }
  157. private static final AstType SocketType = LibInfo.libs.get("Net").structs.get("TCPClientSocket");
  158. /** A TCP server socket handle
  159. */
  160. @IsLibraryStruct(instantiable = false)
  161. public static class TCPServerSocket extends LibraryStruct {
  162. private final ServerSocket socket;
  163. // FIXME not that great
  164. public TCPServerSocket()
  165. {
  166. this(null);
  167. }
  168. public TCPServerSocket(ServerSocket socket) {
  169. this.socket = socket;
  170. }
  171. }
  172. /** A TCP client socket handle
  173. */
  174. @IsLibraryStruct(instantiable = false)
  175. public static class TCPClientSocket extends LibraryStruct {
  176. private final Socket socket;
  177. // FIXME not that great
  178. public TCPClientSocket()
  179. {
  180. this(null);
  181. }
  182. public TCPClientSocket(Socket socket) {
  183. this.socket = socket;
  184. }
  185. }
  186. /**
  187. * Creates a TCP server socket for a certain port
  188. *
  189. * @param port the port to usee
  190. * @return a server socket or null on failure
  191. */
  192. @IsLibraryMethod(params = "port", description = "creates a TCP server socket")
  193. @NeedsPermission(permission.INTERNET)
  194. public static final TCPServerSocket createServerSocket(Double port) {
  195. try {
  196. return new TCPServerSocket(new ServerSocket((int)(double)port));
  197. } catch (IOException e) {
  198. System.console("Net.createServerSocket: " + e.getMessage());
  199. }
  200. return null;
  201. }
  202. /**
  203. * Accepts a client connection on the server tcp socket.
  204. *
  205. * @param serverSocket the tcp server socket to accept a connection from
  206. * @return the client connection or null on failure
  207. */
  208. @IsLibraryMethod(params = "serverSocket", description = "accepts a TCP client connection")
  209. @NeedsPermission(permission.INTERNET)
  210. public static final TCPClientSocket accept(final TCPServerSocket serverSocket) {
  211. if (serverSocket == null || serverSocket.socket == null) {
  212. throw new IllegalArgumentException("socket must not be null");
  213. }
  214. final Scheduler scheduler = Scheduler.getInstance();
  215. final Interpreter current = scheduler.getCurrentTask();
  216. Thread t = new Thread() {
  217. public void run() {
  218. try {
  219. TCPClientSocket ret = new TCPClientSocket(serverSocket.socket.accept());
  220. if (!current.isTerminated()) {
  221. current.pushOntoStackFromLib(ret, SocketType);
  222. scheduler.awakeTask(current);
  223. }
  224. return;
  225. } catch (IOException e) {
  226. System.console("Net.accept: " + e.getMessage());
  227. }
  228. if (!current.isTerminated()) {
  229. current.pushOntoStackFromLib(null, SocketType);
  230. scheduler.awakeTask(current);
  231. }
  232. }
  233. };
  234. synchronized(scheduler) {
  235. t.start();
  236. scheduler.pauseCurrentTask();
  237. return null;
  238. }
  239. }
  240. /**
  241. * Creates a client socket connected to a specific host.
  242. *
  243. * @param ipAddress the ipAddress of the host
  244. * @param port the port of the host
  245. * @return the client socket or null on failure
  246. */
  247. @IsLibraryMethod(params = "ipAddress, port", description = "creates a TCP client socket for communicating with server")
  248. @NeedsPermission(permission.INTERNET)
  249. public static final TCPClientSocket createClientSocket(String ipAddress, Double port) {
  250. try {
  251. InetAddress ipaddr = InetAddress.getByName(ipAddress);
  252. return new TCPClientSocket(new Socket(ipaddr, (int)(double) port));
  253. } catch (UnknownHostException e) {
  254. System.console("Net.createClientSocket: unkown host");
  255. } catch (IOException e) {
  256. System.console("Net.createClientSocket: " + e.getMessage());
  257. }
  258. return null;
  259. }
  260. /**
  261. * Sends a message over the tcp socket
  262. *
  263. * @param socket the tcp socket to use
  264. * @param msg the message to send
  265. * @return true on successs, false on failure
  266. */
  267. @IsLibraryMethod(params = "socket, msg", description = "Sends a msg using the tcp socket")
  268. @NeedsPermission(permission.INTERNET)
  269. public static final Boolean send(TCPClientSocket socket, String msg) {
  270. if (socket == null || socket.socket == null) {
  271. throw new IllegalArgumentException("socket must not be null");
  272. }
  273. if (msg == null) {
  274. throw new IllegalArgumentException("msg must not be null");
  275. }
  276. try {
  277. PrintWriter out = new PrintWriter(socket.socket.getOutputStream());
  278. out.write(msg);
  279. out.flush();
  280. return true;
  281. } catch (IOException e) {
  282. System.console("Net.send: " + e.getMessage());
  283. }
  284. return false;
  285. }
  286. /**
  287. * Receives a message from a tcp socket
  288. *
  289. * @param socket the tcp socket to receive the message from
  290. * @return the message of null on failure
  291. */
  292. @IsLibraryMethod(params = "socket", description = "Receive a msg from the tcp socket")
  293. @NeedsPermission(permission.INTERNET)
  294. public static final String receive(final TCPClientSocket socket) {
  295. if (socket == null || socket.socket == null) {
  296. throw new IllegalArgumentException("socket must not be null");
  297. }
  298. final Scheduler scheduler = Scheduler.getInstance();
  299. final Interpreter current = scheduler.getCurrentTask();
  300. Thread t = new Thread() {
  301. public void run() {
  302. try {
  303. BufferedReader in = new BufferedReader(new InputStreamReader(
  304. socket.socket.getInputStream()));
  305. char buffer[] = new char[300];
  306. int count = in.read(buffer, 0, 300);
  307. String ret = new String(buffer, 0, count);
  308. if (!current.isTerminated()) {
  309. current.pushOntoStackFromLib(ret, AstType.string);
  310. scheduler.awakeTask(current);
  311. }
  312. return;
  313. } catch (IOException e) {
  314. System.console("Net.recv: " + e.getMessage());
  315. }
  316. if (!current.isTerminated()) {
  317. current.pushOntoStackFromLib(null, AstType.string);
  318. scheduler.awakeTask(current);
  319. }
  320. }
  321. };
  322. synchronized(scheduler) {
  323. t.start();
  324. scheduler.pauseCurrentTask();
  325. return null;
  326. }
  327. }
  328. /**
  329. * Closes a tcp server socket.
  330. *
  331. * @param socket the socket to close
  332. */
  333. @IsLibraryMethod(params = "socket", description = "Closes the server socket")
  334. public static final void close(TCPServerSocket socket) {
  335. if (socket == null)
  336. return;
  337. try {
  338. socket.socket.close();
  339. } catch (IOException e) {
  340. }
  341. }
  342. /**
  343. * Closes a tcp client socket.
  344. *
  345. * @param socket the socket to close
  346. */
  347. @IsLibraryMethod(params = "socket", description = "Closes the client socket")
  348. public static final void close(TCPClientSocket socket) {
  349. if (socket == null)
  350. return;
  351. try {
  352. socket.socket.close();
  353. } catch (IOException e) {
  354. }
  355. }
  356. }