/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package logic;
import enums.ServiceTags;
import framework.IATMSModel;
import framework.IClientThread;
import framework.IPlaneUpdateObject;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.UserInfo;
import framework.IUserInfo;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import messages.PlaneDataObject;
import messages.PlaneUpdateObject;
import messages.ServiceObject;
/**
*
* @author swift
*/
public class ClientThread implements IClientThread, Runnable{
private IATMSModel model;
// Enthaelt die information welches der InputStream ist
private ObjectInputStream in;
// Enthaelt die Information ueber den clientSocket
private Socket clientSocket;
// Entaelt eine Referenz auf die Hauptserverklasse
private Object input;
// Kontainer fuer empfangene ServiceObjects
private ServiceObject so;
// Enhaelt die Benutzerinfos wie Name und ObjectOutputStream
private IUserInfo ui;
// Enthaelt die Zeit in Minuten, bis zu der sich der Client spaetestens melden muss
private static final int SENDKEEPALIVEMINUTES = 5;
// Enthaelt die maximale Verzoegerung bis sich der Client meldet in ms
private static final int DELAY = 60000;
// Enthaelt den TimerTask
private MyTimerTask timerTask;
// Der Timer der Laeuft
private Timer timer;
public ClientThread(Socket clientSocket, IATMSModel model){
//System.out.println("ClientThread starting...");
this.model=model;
this.clientSocket = clientSocket;
try {
in = new ObjectInputStream(clientSocket.getInputStream());
// das Benutzerinfo Objeckt wird erstellt ohne den Namen, der Name wird spaeter hinzugefuegt
ui = new UserInfo(null, null, new ObjectOutputStream(clientSocket.getOutputStream()), this);
} catch (IOException ex) {
Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
}
timer = new Timer();
timerTask = new MyTimerTask();
timer.schedule(timerTask, SENDKEEPALIVEMINUTES * 60000L, SENDKEEPALIVEMINUTES * 60000L);
}
public void run() {
try {
// der Thread laeft solange auf dem InputStream was zulesen ist.
while ((input = in.readObject()) != null) {
// Wenn ein Paket vom Client ankommt wir der Timer neu gesetzt.
timerTask.setActive();
// Wenn das Object ein ServiceObject ist wird es gecastet
if (input instanceof ServiceObject) {
so = (ServiceObject) input;
if (so.isTag(ServiceTags.KeepAlive)) {
System.out.println("sending keepalive");
ui.getOOS().writeObject(new ServiceObject("Server",ServiceTags.KeepAlive));
//ATMserver.keepAlive(so, ui);
// es wird kontrolliert ob sich der Client angemeldet hat, wenn nicht wird die Verbindung geschlossen
} else if (so.isTag(ServiceTags.ClientLoggedIn)) {
if(model.isNameUnique(so.getSenderName())){
ui.setNickName(so.getSenderName());
model.addUserInfo(ui);
System.out.println(so.getSenderName()+" logged in.");
//Sending functionlist
ServiceObject sout=new ServiceObject("Server",ServiceTags.FunctionList);
sout.setFunctions(model.getFuncs());
System.out.println("Sending functionlist to: "+ui.getNickName());
ui.getOOS().writeObject(sout);
model.getServer().sendUserList(ui);
model.sendUpdateList(ui);
} else {
System.out.println(so.getSenderName()+" already exists, closing connection.");
ui.getOOS().writeObject(new ServiceObject("Server",ServiceTags.NameAlreadyExists));
throw new IOException();
}
}else if (so.isTag(ServiceTags.chatMessage)) {
ServiceObject sout = new ServiceObject(ui.getNickName(), ServiceTags.chatMessage);
sout.setValue(so.getValue());
model.getServer().broadcast(sout, ui);
}
else if (so.isTag(ServiceTags.ClientLoggedOut)) {
throw new IOException();
} else if(so.isTag(ServiceTags.FunctionChoosen)){
System.out.println("User "+ui.getNickName()+" choose function "+so.getValue());
if(ui.getFunction()!=null){
System.out.println("old function was: "+ui.getFunction());
model.addFunction(ui.getFunction());
}
ui.setFunction(so.getValue());
model.removeFunction(so.getValue());
model.updateUserInfo(ui);
}
} else if (input instanceof PlaneUpdateObject){
model.addPlaneUpdate((IPlaneUpdateObject)input, ui);
} else if (input instanceof PlaneDataObject){
PlaneDataObject pdo = (PlaneDataObject)input;
model.getServer().broadcast(input);
}
}
} catch (IOException ex) {
System.err.println(ui.getNickName()+": logged out");
model.addFunction(ui.getFunction());
model.removeUserInfo(ui);
if(ui.getFunction()!=null)model.resetPlanes(ui.getFunction());
//Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
private class MyTimerTask extends TimerTask {
private long start;
public MyTimerTask() {
start = System.currentTimeMillis();
}
public void run() {
if (System.currentTimeMillis() - start > (SENDKEEPALIVEMINUTES * 60000L) + DELAY) {
//System.out.println("End of Session because of Timeout" + ui.getName());
//close();
}
}
public void setActive() {
start = System.currentTimeMillis();
}
}
}