/*
* ProxyKbdReceiver.java
*
* Copyright (c) 2010 VDP <vdp DOT kindle AT gmail.com>.
*
* This file is part of MidpSSH.
*
* MidpSSH 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 version 3 of the License, or
* (at your option) any later version.
*
* MidpSSH 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 MidpSSH. If not, see <http ://www.gnu.org/licenses/>.
*/
package kindle;
import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import org.apache.log4j.Logger;
/**
* Listens on a UDP socket for keyboard events
* and forwards them to the terminal window.
*/
public class RemoteKbdReceiver extends Thread {
private boolean stopping;
//private DatagramSocket socket;
//private DatagramPacket packet;
private ServerSocket sockServ;
private Socket sock;
byte[] readBuf = new byte[1024];
private Logger log;
private KeyListener keyListener;
private Component receiver;
private Thread watchdog;
private RKbdStatusListener rkbdListener;
public RemoteKbdReceiver(int port, KeyListener listener, Component receiver) {
stopping = false;
log = Logger.getLogger(RemoteKbdReceiver.class.getName());
this.keyListener = listener;
this.receiver = receiver;
try {
sockServ = new ServerSocket(port);
} catch (Exception ex) {
log.error(ex.toString());
}
watchdog = new Thread(new Runnable() {
public void run() {
long sleepTime = 5 * 1000;
while (!stopping) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException ie) {
log.debug("Watchdog thread interrupted");
}
try {
if (sock != null)
sock.getOutputStream().write(1);
} catch (Exception e) {
if (sock != null) {
try {
sock.close();
sock = null;
} catch (IOException ex) {
log.warn(ex.toString());
}
}
log.debug("Remote keyboard probably disconnected ...");
}
}
}
});
watchdog.start();
}
public void kill() {
try {
stopping = true;
if (sockServ != null)
sockServ.close();
if (sock != null && !sock.isClosed()) {
sock.close();
}
watchdog.interrupt();
} catch (IOException ex) {
log.error(ex.getMessage());
}
}
public void run() {
try {
while (!stopping) {
if (sock == null) {
log.info("Remote keyboard disconnected");
if (rkbdListener != null) {
rkbdListener.statusChanged(false);
}
sock = sockServ.accept();
log.info("New remote keyboard attached");
if (rkbdListener != null) {
rkbdListener.statusChanged(true);
}
}
int i = 0;
try {
int b = sock.getInputStream().read();
while (b != 0) {
readBuf[i++] = (byte) b;
b = sock.getInputStream().read();
}
}
catch (SocketException se) {
log.info("RKeyboard read() interrupted: " + se.toString());
sock = null;
}
catch (NullPointerException npe) {
log.debug(npe.toString());
}
String strEvent = new String(readBuf, 0, i);
System.out.println("Received: " + strEvent);
ProxyKeyEvent pe = ProxyKeyEvent.makeEvent(strEvent, receiver, 0);
int id = pe.getID();
if (id == KeyEvent.KEY_PRESSED) {
keyListener.keyPressed(pe);
}
else if (id == KeyEvent.KEY_RELEASED) {
keyListener.keyReleased(pe);
}
else {
keyListener.keyTyped(pe);
}
}
} catch (IOException ex) {
if (!stopping) {
log.error(ex.toString());
}
}
}
public void setRKbdStatusListener(RKbdStatusListener rkbdListener) {
this.rkbdListener = rkbdListener;
}
/**
* The objects interested whether a remote keyboard is attached
* should implement this interface and register it with RemoteKbdReceiver
*/
public interface RKbdStatusListener {
public void statusChanged(boolean isAttached);
}
}