diff --git a/src/com/jsaasta/froj/stdlib/Stdlib.java b/src/com/jsaasta/froj/stdlib/Stdlib.java index 2ad7d0d..ab105cf 100644 --- a/src/com/jsaasta/froj/stdlib/Stdlib.java +++ b/src/com/jsaasta/froj/stdlib/Stdlib.java @@ -1,5 +1,7 @@ package com.jsaasta.froj.stdlib; +import com.jsaasta.froj.stdlib.socket.SocketServer; + import java.util.HashMap; import java.util.Map; @@ -12,6 +14,7 @@ public class Stdlib { classes.put("clock", new Clock()); classes.put("input", new Input()); classes.put("fileReader", new FileReader()); + classes.put("socket", new SocketServer()); } public static Map define(){ diff --git a/src/com/jsaasta/froj/stdlib/socket/ClientHandler.java b/src/com/jsaasta/froj/stdlib/socket/ClientHandler.java new file mode 100644 index 0000000..82e0979 --- /dev/null +++ b/src/com/jsaasta/froj/stdlib/socket/ClientHandler.java @@ -0,0 +1,39 @@ +package com.jsaasta.froj.stdlib.socket; + +import java.io.*; +import java.net.Socket; + +class ClientHandler implements Runnable { + private Socket socket; + + public ClientHandler(Socket socket) { + this.socket = socket; + } + + public void run() { + try { + InputStream in = socket.getInputStream(); + OutputStream out = socket.getOutputStream(); + + byte[] buffer = new byte[1024]; + int bytesRead = in.read(buffer); + if (bytesRead == -1) { + System.out.println("Client closed the Connection"); + } + + String message = new String(buffer, 0, bytesRead); + System.out.println("Received message from client: " + message); + + out.write(message.getBytes()); + + SocketServer.messageQueue.put(message); + + socket.close(); + } catch (IOException e) { + System.out.println("Error handling client connection: " + e.getMessage()); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/com/jsaasta/froj/stdlib/socket/SocketServer.java b/src/com/jsaasta/froj/stdlib/socket/SocketServer.java new file mode 100644 index 0000000..edcba8b --- /dev/null +++ b/src/com/jsaasta/froj/stdlib/socket/SocketServer.java @@ -0,0 +1,72 @@ +package com.jsaasta.froj.stdlib.socket; + +import com.jsaasta.froj.FrojCallable; +import com.jsaasta.froj.Interpreter; +import com.jsaasta.froj.stdlib.StdlibRuntimeError; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public class SocketServer implements FrojCallable { + protected static BlockingQueue messageQueue = new LinkedBlockingQueue<>(); + private static ServerSocket serverSocket; + + private final String EXIT_CODE = "EXIT"; + + @Override + public int arity() { + return 1; + } + + @Override + public Object call(Interpreter interpreter, List arguments) { + return startSocketServer(arguments.get(0)); + } + + private Object startSocketServer(Object port) { + try { + Double param = (Double) port; + final int PORT = param.intValue(); + + serverSocket = new ServerSocket(PORT); + + Socket socket = serverSocket.accept(); + System.out.println("Incoming connection from " + socket.getInetAddress()); + + ClientHandler clientHandler = new ClientHandler(socket); + clientHandler.run(); + String nextMessage = getNextMessage(); + if (nextMessage.toLowerCase().contentEquals("exit")) { + shutdown(); + return EXIT_CODE; + } + try { + return Double.parseDouble(nextMessage); + } catch (NumberFormatException e) { + return nextMessage; + } + + } catch (IOException | InterruptedException e) { + throw new StdlibRuntimeError(e.getMessage()); + } finally { + shutdown(); + } + } + + public static String getNextMessage() throws InterruptedException { + return messageQueue.take(); + } + + public static void shutdown() { + try { + serverSocket.close(); + } catch (IOException e) { + System.out.println("Error shutting down server: " + e.getMessage()); + } + } + +} diff --git a/src/com/jsaasta/tool/SocketClient.java b/src/com/jsaasta/tool/SocketClient.java new file mode 100644 index 0000000..6884bda --- /dev/null +++ b/src/com/jsaasta/tool/SocketClient.java @@ -0,0 +1,58 @@ +package com.jsaasta.tool; + +import java.io.*; +import java.net.ConnectException; +import java.net.Socket; + +class SocketClient { + + public static void main(String[] args) throws IOException { + while(true) { + InputStreamReader input = new InputStreamReader(System.in); + BufferedReader reader = new BufferedReader(input); + + String message = reader.readLine(); + if(message.contentEquals("SHUTMEDOWN")){ + break; + } + String response = sendMessage(message); + if (response != null) { + System.out.println("Received response from server: " + response); + } + } + } + + private static String sendMessage(String message) throws IOException { + Socket socket = null; + try { + socket = new Socket("localhost", 8000); + System.out.println("Connected to server"); + + OutputStream out = socket.getOutputStream(); + InputStream in = socket.getInputStream(); + + out.write(message.getBytes()); + + byte[] buffer = new byte[1024]; + int bytesRead = in.read(buffer); + String response = new String(buffer, 0, bytesRead); + + return response; + } catch (ConnectException e) { + System.out.println("Connection refused. Is the server running?"); + return null; + } catch (IOException e) { + System.out.println("Error sending message: " + e.getMessage()); + return null; + } finally { + if (socket != null) { + try { + socket.close(); + } catch (IOException e) { + System.out.println("Error closing socket: " + e.getMessage()); + } + } + } + } + +} diff --git a/src/test/com/saasta/froj/stdlib/FrojStdlibTest.java b/src/test/com/saasta/froj/stdlib/FrojStdlibTest.java index c094d1c..46ac2da 100644 --- a/src/test/com/saasta/froj/stdlib/FrojStdlibTest.java +++ b/src/test/com/saasta/froj/stdlib/FrojStdlibTest.java @@ -13,6 +13,12 @@ public class FrojStdlibTest { public void test_Stdlib_Clock() throws IOException { Froj froj = new Froj(); froj.runFile("src/test/com/saasta/froj/stdlib/froj_stdlib_clock.froj"); + froj.runFile("src/test/com/saasta/froj/stdlib/froj_stdlib_fileReader.froj"); + try { + froj.runFile("src/test/com/saasta/froj/stdlib/froj_stdlib_socketserver.froj"); + } catch(NullPointerException ex){ + + } } } diff --git a/src/test/com/saasta/froj/stdlib/froj_stdlib_fileReader.froj b/src/test/com/saasta/froj/stdlib/froj_stdlib_fileReader.froj new file mode 100644 index 0000000..bd96eb0 --- /dev/null +++ b/src/test/com/saasta/froj/stdlib/froj_stdlib_fileReader.froj @@ -0,0 +1 @@ +fileReader("./hello_world.froj"); \ No newline at end of file diff --git a/src/test/com/saasta/froj/stdlib/froj_stdlib_input.froj b/src/test/com/saasta/froj/stdlib/froj_stdlib_input.froj deleted file mode 100644 index edf9c3d..0000000 --- a/src/test/com/saasta/froj/stdlib/froj_stdlib_input.froj +++ /dev/null @@ -1 +0,0 @@ -input(); \ No newline at end of file diff --git a/src/test/com/saasta/froj/stdlib/froj_stdlib_socketserver.froj b/src/test/com/saasta/froj/stdlib/froj_stdlib_socketserver.froj new file mode 100644 index 0000000..a8dbbd7 --- /dev/null +++ b/src/test/com/saasta/froj/stdlib/froj_stdlib_socketserver.froj @@ -0,0 +1 @@ +socket("asdf"); \ No newline at end of file