emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/geiser-kawa 02cd922 046/119: Add workaround to free port w


From: Philip Kaludercic
Subject: [nongnu] elpa/geiser-kawa 02cd922 046/119: Add workaround to free port when a Kawa server is already using it through ssocket.close()
Date: Sun, 1 Aug 2021 18:30:36 -0400 (EDT)

branch: elpa/geiser-kawa
commit 02cd922876f4b20bb9ae5b09a2b84022a7c58781
Author: spellcard199 <spellcard199@protonmail.com>
Commit: spellcard199 <spellcard199@protonmail.com>

    Add workaround to free port when a Kawa server is already using it through 
ssocket.close()
---
 .../kawageiser/StartKawaWithGeiserSupport.java     | 90 ++++++++++++++++++----
 1 file changed, 77 insertions(+), 13 deletions(-)

diff --git a/src/main/java/kawageiser/StartKawaWithGeiserSupport.java 
b/src/main/java/kawageiser/StartKawaWithGeiserSupport.java
index cc558e8..433b0b1 100644
--- a/src/main/java/kawageiser/StartKawaWithGeiserSupport.java
+++ b/src/main/java/kawageiser/StartKawaWithGeiserSupport.java
@@ -5,19 +5,41 @@
 
 package kawageiser;
 
+import gnu.expr.Language;
+import kawa.TelnetRepl;
+import kawa.standard.Scheme;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+
 public class StartKawaWithGeiserSupport {
 
-    public static void main(String[] args) {
+    public static void main(String[] args) throws IOException {
+        Scheme scheme = new Scheme();
         if (args.length == 0) {
             int defaultPort = 37146;
             System.out.println(
                     String.format(
                             "No port specified. Starting kawa server on 
default port (%d)...",
                             defaultPort));
-            startKawaServerWithGeiserSupport(defaultPort);
+            // NOTE: You can use ssocket.close() to forcefully free port:
+            //       that's why we are passing around a ServerSocket instead 
of an int port
+            // NOTE:
+            // 1. You can't reuse address if you use the constructor new 
ServerSocket(int port);
+            // 2. That's why we used the following 3 lines here
+            ServerSocket ssocket = 
makeServerSocketWithReusableAddress(defaultPort);
+            Thread kawaServerThread = 
makeThreadForKawaServerWithGeiserSupport(ssocket, scheme);
+            kawaServerThread.start();
+
         } else if (args.length == 1 && args[0].matches("[0-9]+")) {
+            // NOTE: You can use ssocket.close() to forcefully free port:
+            //       that's why we are passing around a ServerSocket instead 
of an int port
             int port = Integer.parseInt(args[0]);
-            startKawaServerWithGeiserSupport(port);
+            ServerSocket ssocket = makeServerSocketWithReusableAddress(port);
+            Thread kawaServerThread = 
makeThreadForKawaServerWithGeiserSupport(ssocket, scheme);
+            kawaServerThread.start();
+
         } else if (args.length == 1 && args[0].equals("--no-server")) {
             System.out.println("Starting kawa repl in current terminal...");
             startKawaReplWithGeiserSupport();
@@ -30,24 +52,66 @@ public class StartKawaWithGeiserSupport {
         }
     }
 
-    public static void startKawaReplWithGeiserSupport() {
+    public static Scheme startKawaReplWithGeiserSupport() {
         String[] interpArgs = new String[]{
                 "-e", "(require <kawageiser.Geiser>)",
                 "--",
         };
-        runSchemeAsApplication(interpArgs);
+        return runSchemeAsApplication(interpArgs);
     }
 
-    public static void startKawaServerWithGeiserSupport(int port) {
-        String[] interpArgs = new String[]{
-                "-e", "(require <kawageiser.Geiser>)",
-                "--server", String.valueOf(port)};
-        runSchemeAsApplication(interpArgs);
-    }
-
-    public static void runSchemeAsApplication(String[] args) {
+    public static Scheme runSchemeAsApplication(String[] args) {
         kawa.standard.Scheme scheme = kawa.standard.Scheme.getInstance();
         scheme.runAsApplication(args);
+        return scheme;
+
+    }
+
+    public static Thread
+    makeThreadForKawaServerWithGeiserSupport(ServerSocket ssocket, Scheme 
scheme) {
+        return new Thread(() -> {
+            try {
+                startKawaServerWithGeiserSupport(ssocket, scheme);
+            } catch (Throwable throwable) {
+                throwable.printStackTrace();
+            }
+        });
+    }
+
+    public static ServerSocket
+    makeServerSocketWithReusableAddress(int port) throws IOException {
+        ServerSocket ssocket = new ServerSocket();
+        ssocket.setReuseAddress(true);
+        ssocket.bind(new InetSocketAddress(port));
+        return ssocket;
+    }
+
+    private static void
+    startKawaServerWithGeiserSupport(ServerSocket ssocket,
+                                     Scheme scheme) throws Throwable {
+        scheme.eval("(require <kawageiser.Geiser>)");
+        startKawaServer(ssocket, scheme);
+    }
+
+    private static void
+    startKawaServer(ServerSocket ssocket, Scheme scheme) throws IOException {
+        // Adapted from Kawa's code in kawa/repl.java
+        System.err.println("Listening on port " + ssocket.getLocalPort());
+        for (; ; ) {
+            System.err.print("waiting ... ");
+            System.err.flush();
+            java.net.Socket client = ssocket.accept();
+            System.err.println("got connection from "
+                    + client.getInetAddress()
+                    + " port:" + client.getPort());
+            Language saveLang = Language.getDefaultLanguage();
+            try {
+                Language.setCurrentLanguage(scheme);
+                TelnetRepl.serve(scheme, client);
+            } finally {
+                Language.setCurrentLanguage(saveLang);
+            }
+        }
     }
 
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]