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