001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io.remotecontrol; 003 004import static org.openstreetmap.josm.tools.I18n.marktr; 005 006import java.io.IOException; 007import java.net.BindException; 008import java.net.InetAddress; 009import java.net.ServerSocket; 010import java.net.Socket; 011import java.net.SocketException; 012 013import org.openstreetmap.josm.Main; 014 015/** 016 * Simple HTTP server that spawns a {@link RequestProcessor} for every 017 * connection. 018 * 019 * Taken from YWMS plugin by frsantos. 020 */ 021public class RemoteControlHttpServer extends Thread { 022 023 /** The server socket */ 024 private ServerSocket server; 025 026 private static RemoteControlHttpServer instance; 027 028 /** 029 * Starts or restarts the HTTP server 030 */ 031 public static void restartRemoteControlHttpServer() { 032 int port = Main.pref.getInteger("remote.control.port", 8111); 033 try { 034 stopRemoteControlHttpServer(); 035 036 instance = new RemoteControlHttpServer(port); 037 instance.start(); 038 } catch (BindException ex) { 039 Main.warn(marktr("Cannot start remotecontrol server on port {0}: {1}"), 040 Integer.toString(port), ex.getLocalizedMessage()); 041 } catch (IOException ioe) { 042 Main.error(ioe); 043 } 044 } 045 046 /** 047 * Stops the HTTP server 048 * @since 5861 049 */ 050 public static void stopRemoteControlHttpServer() { 051 if (instance != null) { 052 try { 053 instance.stopServer(); 054 instance = null; 055 } catch (IOException ioe) { 056 Main.error(ioe); 057 } 058 } 059 } 060 061 /** 062 * Constructor 063 * @param port The port this server will listen on 064 * @throws IOException when connection errors 065 */ 066 public RemoteControlHttpServer(int port) throws IOException { 067 super("RemoteControl HTTP Server"); 068 this.setDaemon(true); 069 // Start the server socket with only 1 connection. 070 // Also make sure we only listen 071 // on the local interface so nobody from the outside can connect! 072 // NOTE: On a dual stack machine with old Windows OS this may not listen on both interfaces! 073 this.server = new ServerSocket(port, 1, 074 InetAddress.getByName(Main.pref.get("remote.control.host", "localhost"))); 075 } 076 077 /** 078 * The main loop, spawns a {@link RequestProcessor} for each connection 079 */ 080 @Override 081 public void run() { 082 Main.info(marktr("RemoteControl::Accepting connections on port {0}"), 083 Integer.toString(server.getLocalPort())); 084 while (true) { 085 try { 086 @SuppressWarnings("resource") 087 Socket request = server.accept(); 088 RequestProcessor.processRequest(request); 089 } catch (SocketException se) { 090 if (!server.isClosed()) 091 Main.error(se); 092 } catch (IOException ioe) { 093 Main.error(ioe); 094 } 095 } 096 } 097 098 /** 099 * Stops the HTTP server 100 * 101 * @throws IOException 102 */ 103 public void stopServer() throws IOException { 104 server.close(); 105 Main.info(marktr("RemoteControl::Server stopped.")); 106 } 107}