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