// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.io.remotecontrol;
import static org.openstreetmap.josm.tools.I18n.marktr;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import org.openstreetmap.josm.Main;
/**
* Simple HTTP server that spawns a {@link RequestProcessor} for every
* connection.
*
* Taken from YWMS plugin by frsantos.
*/
public class RemoteControlHttpServer extends Thread {
/** The server socket */
private final ServerSocket server;
/** The server instance for IPv4 */
private static volatile RemoteControlHttpServer instance4;
/** The server instance for IPv6 */
private static volatile RemoteControlHttpServer instance6;
/**
* Starts or restarts the HTTP server
*/
public static void restartRemoteControlHttpServer() {
stopRemoteControlHttpServer();
int port = Main.pref.getInteger("remote.control.port", 8111);
try {
instance4 = new RemoteControlHttpServer(port, false);
instance4.start();
} catch (IOException ex) {
Main.debug(ex);
Main.warn(marktr("Cannot start IPv4 remotecontrol server on port {0}: {1}"),
Integer.toString(port), ex.getLocalizedMessage());
}
try {
instance6 = new RemoteControlHttpServer(port, true);
instance6.start();
} catch (IOException ex) {
/* only show error when we also have no IPv4 */
if (instance4 == null) {
Main.debug(ex);
Main.warn(marktr("Cannot start IPv6 remotecontrol server on port {0}: {1}"),
Integer.toString(port), ex.getLocalizedMessage());
}
}
}
/**
* Stops the HTTP server
* @since 5861
*/
public static void stopRemoteControlHttpServer() {
if (instance4 != null) {
try {
instance4.stopServer();
} catch (IOException ioe) {
Main.error(ioe);
}
instance4 = null;
}
if (instance6 != null) {
try {
instance6.stopServer();
} catch (IOException ioe) {
Main.error(ioe);
}
instance6 = null;
}
}
/**
* Constructor
* @param port The port this server will listen on
* @param ipv6 Whether IPv6 or IPv4 server should be started
* @throws IOException when connection errors
* @since 8339
*/
public RemoteControlHttpServer(int port, boolean ipv6) throws IOException {
super("RemoteControl HTTP Server");
this.setDaemon(true);
this.server = new ServerSocket(port, 1, ipv6 ?
RemoteControl.getInet6Address() : RemoteControl.getInet4Address());
}
/**
* The main loop, spawns a {@link RequestProcessor} for each connection
*/
@Override
public void run() {
Main.info(marktr("RemoteControl::Accepting remote connections on {0}:{1}"),
server.getInetAddress(), Integer.toString(server.getLocalPort()));
while (true) {
try {
@SuppressWarnings("resource")
Socket request = server.accept();
RequestProcessor.processRequest(request);
} catch (SocketException e) {
if (!server.isClosed()) {
Main.error(e);
} else {
// stop the thread automatically if server is stopped
return;
}
} catch (IOException ioe) {
Main.error(ioe);
}
}
}
/**
* Stops the HTTP server
*
* @throws IOException if any I/O error occurs
*/
public void stopServer() throws IOException {
Main.info(marktr("RemoteControl::Server {0}:{1} stopped."),
server.getInetAddress(), Integer.toString(server.getLocalPort()));
server.close();
}
}