/*
* Copyright 2010 jOpenRay, ILM Informatique
*
* 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 version 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 program. If not, see <http://www.gnu.org/licenses/>
*/
package org.jopenray.server.thinclient;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import org.jopenray.adapter.RDPAdapter;
import org.jopenray.adapter.RFBAdapter;
import org.jopenray.adapter.SshAdapter;
import org.jopenray.authentication.AuthenticationMessage;
import org.jopenray.operation.FillOperation;
import org.jopenray.operation.Operation;
import org.jopenray.operation.SetMouseCursorOperation;
import org.jopenray.server.session.Session;
import org.jopenray.util.Hex;
public class ThinClient {
private final Map<String, String> properties = new HashMap<String, String>();
private final List<String> keys = new ArrayList<String>();
private InetAddress server;
private DisplayWriterThread tWriter;
private DisplayReaderThread tReader;
private DatagramSocket socket;
private final PropertyChangeSupport s = new PropertyChangeSupport(this);
private int byteSent;
OperationHistory h = new OperationHistory();
private boolean allowed;
private String name;
private Thread thread;
private int screenWidth;
private int screenHeight;
public ThinClient(String id) {
this("Unknown", id, 1280, 1024);
}
public ThinClient(String name, String id, int screenWidth, int screenHeight) {
this.name = name;
this.properties.put("sn", id);
this.keys.add("sn");
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
}
public void updateStateFrom(AuthenticationMessage m) {
m.exportProperties(this);
s.firePropertyChange("all", null, null);
}
public void addPropertyChangeListeneer(PropertyChangeListener l) {
s.addPropertyChangeListener(l);
}
public int getServerPort() {
String port = properties.get("pn");
if (port != null) {
final int udpPort = Integer.valueOf(port);
return udpPort;
}
return -1;
}
public DatagramSocket getSocket() {
return socket;
}
public void connectDisplay(Session session) throws SocketException {
initConnection();
System.out.println("Starting Session to: " + session.getAllInfo());
switch (session.getProtocol()) {
case Session.RDP:
startRDP(session);
break;
case Session.RFB:
startRFB(session);
break;
case Session.SSH:
startSSH(session);
break;
default:
startImage();
break;
}
// startRFB();
// tWriter.sendImage("console.png", 0, 1);
// DatagramPacket dataRecieved = new DatagramPacket(new
// byte[length],length);
// socket.receive(dataRecieved);
// System.out.println("Data recieved : " + new
// String(dataRecieved.getData()));
// System.out.println("From : " + dataRecieved.getAddress() + ":" +
// dataRecieved.getPort());
}
public void initConnection() throws SocketException {
socket = new DatagramSocket();
// h.clear();
String ip = properties.get("realIP");
try {
try {
server = InetAddress.getByAddress(Hex.decodeHex(ip));
} catch (Exception e) {
e.printStackTrace();
// FIXME: remove this and see if realIP is really needed
server = InetAddress.getByName("192.168.1.30");
}
System.out.println("connectDislay :ip:" + server.getHostAddress());
if (tReader != null) {
tReader.interrupt();
}
tReader = new DisplayReaderThread(this);
tReader.start();
if (tWriter == null) {
tWriter = new DisplayWriterThread(this);
tWriter.start();
} else {
tWriter.sendInit();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void startImage() {
if (thread != null && !thread.isInterrupted()) {
thread.interrupt();
}
thread = new Thread() {
public void run() {
ThinClient client = ThinClient.this;
BufferedImage image;
try {
image = ImageIO.read(new File("Images/happy.jpg"));
client.getWriter().sendImage(image, 0, 0);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void interrupt() {
super.interrupt();
}
};
thread.start();
}
private void startSSH(final Session session) {
if (thread != null && !thread.isInterrupted()) {
thread.interrupt();
}
thread = new Thread() {
SshAdapter t = new SshAdapter();
public void run() {
t = new SshAdapter();
tReader.addInputListener(t);
t.start(ThinClient.this, session);
}
@Override
public void interrupt() {
tReader.removeInputListener(t);
t.stop();
super.interrupt();
}
};
thread.start();
}
private void startRFB(final Session session) {
JOptionPane.showMessageDialog(null,
"RFB sessions are disabled in this release.");
return;
}
public void stop() {
}
private void startRDP(final Session session) {
if (thread != null && !thread.isInterrupted()) {
thread.interrupt();
}
thread = new Thread() {
RDPAdapter t = new RDPAdapter();
@Override
public void run() {
tReader.addInputListener(t);
if (!session.isHardwareCursorUsed()) {
DisplayMessage mCursor = new DisplayMessage(tWriter);
mCursor.addOperation(new SetMouseCursorOperation(
SetMouseCursorOperation.INVISIBLE_CURSOR));
tWriter.addMessage(mCursor);
}
t.start(ThinClient.this, session);
}
@Override
public void interrupt() {
tReader.removeInputListener(t);
t.stop();
super.interrupt();
}
};
thread.setName("RDP connection to " + session.getServer());
thread.start();
}
public InetAddress getServer() {
return server;
}
public String getName() {
if (name == null) {
name = this.properties.get("sn");
}
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getPropertyCount() {
return this.properties.size();
}
public String getPropertyName(int index) {
return this.keys.get(index);
}
public Object getPropertyValue(int index) {
return this.properties.get(getPropertyName(index));
}
public void put(String key, String value) {
if (!this.keys.contains(key)) {
this.keys.add(key);
}
this.properties.put(key, value);
}
public int getMTU() {
// TODO Auto-generated method stub
return 1500;
}
public void addByteSent(int nb) {
byteSent += nb;
System.out.println("Byte sent:" + byteSent);
}
public void sendBytes(byte[] buffer, int bufferLength) throws IOException {
DatagramPacket dataSent = new DatagramPacket(buffer, 0, bufferLength,
getServer(), getServerPort());
getSocket().send(dataSent);
}
public void addToHistory(Operation o) {
this.h.add(o);
}
/**
* Renvoi de from a to (compris) ex: 19,19 ou 19,50
*/
public void resend(int from, int to) {
h.resend(this.tWriter, from, to);
}
public DisplayWriterThread getWriter() {
return this.tWriter;
}
public DisplayReaderThread getReader() {
return this.tReader;
}
public void clearScreen() {
FillOperation f = new FillOperation(0, 0, getScreenWidth(),
getScreenHeight(), Color.PINK);
DisplayMessage m = new DisplayMessage(this.tWriter);
m.addOperation(f);
tWriter.addMessage(m);
}
public void setAllowed(boolean b) {
this.allowed = true;
}
public boolean isAllowed() {
return this.allowed;
}
public String getSerialNumber() {
return this.properties.get("sn");
}
public String getCardId() {
return this.properties.get("id");
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ThinClient) {
ThinClient c = (ThinClient) obj;
return this.getSerialNumber().equals(c.getSerialNumber());
}
return super.equals(obj);
}
public String getStats() {
return tWriter.getStats();
}
public int getMessageToSendCount() {
if (tWriter == null) {
return -1;
}
final int messageToSendCount = tWriter.getMessageToSendCount();
return messageToSendCount;
}
public String getPropertyByName(String name) {
return this.properties.get(name);
}
public void setScreenWidth(int screenWidth) {
this.screenWidth = screenWidth;
}
public int getScreenWidth() {
return screenWidth;
}
public void setScreenHeight(int screenHeight) {
this.screenHeight = screenHeight;
}
public int getScreenHeight() {
return screenHeight;
}
}