PageRenderTime 56ms CodeModel.GetById 2ms app.highlight 49ms 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
  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}