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 ioe.printStackTrace(); 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 ioe.printStackTrace(); 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) 067 throws IOException 068 { 069 super("RemoteControl HTTP Server"); 070 this.setDaemon(true); 071 // Start the server socket with only 1 connection. 072 // Also make sure we only listen 073 // on the local interface so nobody from the outside can connect! 074 // NOTE: On a dual stack machine with old Windows OS this may not listen on both interfaces! 075 this.server = new ServerSocket(port, 1, 076 InetAddress.getByName(Main.pref.get("remote.control.host", "localhost"))); 077 } 078 079 /** 080 * The main loop, spawns a {@link RequestProcessor} for each connection 081 */ 082 @Override 083 public void run() 084 { 085 Main.info(marktr("RemoteControl::Accepting connections on port {0}"), 086 Integer.toString(server.getLocalPort())); 087 while (true) 088 { 089 try 090 { 091 Socket request = server.accept(); 092 RequestProcessor.processRequest(request); 093 } 094 catch( SocketException se) 095 { 096 if( !server.isClosed() ) 097 se.printStackTrace(); 098 } 099 catch (IOException ioe) 100 { 101 ioe.printStackTrace(); 102 } 103 } 104 } 105 106 /** 107 * Stops the HTTP server 108 * 109 * @throws IOException 110 */ 111 public void stopServer() throws IOException 112 { 113 server.close(); 114 Main.info(marktr("RemoteControl::Server stopped.")); 115 } 116}