package net.sourceforge.pain.network.guitool; import net.sourceforge.pain.util.*; import java.io.*; import java.net.*; import java.util.*; public final class GuiToolConnection implements Runnable { private GuiToolConnectionServer server; private final ObjectOutputStream os; private final ObjectInputStream is; private boolean forcedClose; private boolean lostLink; public Object guiAdminId = null; public final LinkedList inputEvents = new LinkedList(); private final LinkedList outputEvents = new LinkedList(); Socket socket; long sessionStartTime; private final Object sendMonitor = new Object(); private Flusher flusher; public GuiToolConnection(GuiToolConnectionServer server, Socket socket) throws IOException { this.server = server; this.socket = socket; os = new ObjectOutputStream(socket.getOutputStream()); is = new ObjectInputStream(socket.getInputStream()); sessionStartTime = System.currentTimeMillis(); } public void run() { forcedClose = false; flusher = new Flusher(); flusher.start(); try { do { try { GTNetPacket inPacket = (GTNetPacket) is.readObject(); Log.debug("GTC: new event:" + inPacket.eventClassName); inputEvents.add(inPacket); } catch (InterruptedIOException e) { break; } catch (IOException e) { if (!forcedClose) { Log.error(e.getMessage(), e); lostLink = true; } break; } catch (Exception e) { Log.error(e.getMessage(), e); } } while (!forcedClose && !lostLink); } catch (Exception e) { Log.error(e); } finally { flusher.die(); server.onClose(this); try { socket.close(); } catch (Exception ignored) { } } } public void forceClose() { Log.debug("GTC:force close!"); forcedClose = true; } public void send(GTNetPacket packet) { synchronized (sendMonitor) { outputEvents.add(packet); sendMonitor.notify(); } } private final class Flusher extends Thread { private boolean isAlive = true; public Flusher() { setDaemon(true); } public void run() { while (isAlive) { if (outputEvents.isEmpty()) { synchronized (sendMonitor) { try { sendMonitor.wait(50); } catch (InterruptedException e) { Log.error(e); } } continue; } // ok we really have somethong to send while (!outputEvents.isEmpty()) { GTNetPacket packet; synchronized (sendMonitor) { packet = (GTNetPacket) outputEvents.removeFirst(); } try { os.writeObject(packet); } catch (IOException e) { Log.error(e); // do nothing, main thread will catch IO by itself } } Log.debug("GTC: flushing"); try { os.flush(); } catch (IOException e) { Log.error(e); // do nothing, main thread will catch IO by itself } } } public void die() { isAlive = false; synchronized (sendMonitor) { sendMonitor.notify(); } } } }