/*
GNU GENERAL PUBLIC LICENSE
Copyright (C) 2006 The Lobo Project
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
verion 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Contact info: lobochief@users.sourceforge.net
*/
/*
* Created on Jun 18, 2005
*/
package org.lobobrowser.main;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
import org.eclipse.jdt.annotation.NonNull;
import org.lobobrowser.ua.NavigatorFrame;
/**
* The local-bound server that allows the browser JVM to be reused.
*/
public class ReuseServer implements Runnable {
/**
*
*/
public ReuseServer() {
final Thread t = new Thread(this, "ReuseServer");
t.setDaemon(true);
t.start();
}
private static final int MIN_PORT = 55000;
private static final int TOP_PORT = 65000;
private static final Random RAND = new Random(System.currentTimeMillis());
private static int getRandomPort() {
return (Math.abs(RAND.nextInt()) % (TOP_PORT - MIN_PORT)) + MIN_PORT;
}
private ServerSocket serverSocket;
public int start(final InetAddress bindAddr) {
// Should be called with bindAddr=127.0.0.1 only.
synchronized (this) {
if (this.serverSocket != null) {
throw new IllegalStateException("Already started");
}
for (int tries = 0; tries < 100; tries++) {
final int rport = getRandomPort();
try {
final ServerSocket ss = new ServerSocket(rport, 100, bindAddr);
this.serverSocket = ss;
this.notify();
return rport;
} catch (final IOException ioe) {
ioe.printStackTrace(System.err);
}
}
}
throw new IllegalStateException("Unable to bind reuse server after many tries.");
}
public void stop() {
synchronized (this) {
if (this.serverSocket != null) {
try {
this.serverSocket.close();
} catch (final IOException ioe) {
// ignore
}
this.serverSocket = null;
}
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
for (;;) {
try {
ServerSocket ss;
synchronized (this) {
while (this.serverSocket == null) {
this.wait();
}
ss = this.serverSocket;
}
try (
final Socket s = ss.accept()) {
s.setSoTimeout(10000);
s.setTcpNoDelay(true);
try (
final InputStream in = s.getInputStream()) {
final Reader reader = new InputStreamReader(in);
final BufferedReader br = new BufferedReader(reader);
String line;
while ((line = br.readLine()) != null) {
final int blankIdx = line.indexOf(' ');
final String command = blankIdx == -1 ? line : line.substring(0, blankIdx).trim();
if ("LAUNCH".equals(command)) {
if (blankIdx == -1) {
PlatformInit.getInstance().launch();
} else {
final String path = line.substring(blankIdx + 1).trim();
PlatformInit.getInstance().launch(path);
}
} else if ("LAUNCH_BLANK".equals(command)) {
PlatformInit.getInstance().launch();
} else if ("GRINDER".equals(command)) {
final DataOutputStream dos = new DataOutputStream(s.getOutputStream());
if (blankIdx != -1) {
@SuppressWarnings("null")
final @NonNull String key = line.substring(blankIdx + 1).trim();
if (PlatformInit.getInstance().verifyAuth(ss.getLocalPort(), key)) {
final NavigatorFrame frame = PlatformInit.getInstance().launch("about:blank");
final GrinderServer gs = new GrinderServer(frame);
final int gsPort = gs.getPort();
dos.writeInt(gsPort);
dos.flush();
} else {
dos.writeInt(-1);
dos.flush();
}
} else {
dos.writeInt(-1);
dos.flush();
}
// Wait for ACK
br.readLine();
}
}
}
}
} catch (final Exception t) {
t.printStackTrace(System.err);
}
}
}
}