package client.Network;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import client.MyClientID;
import client.CustomEvents.NewClientsListEvent;
import CustomEvents.CustomEventSource;
import CustomEvents.ICustomEventListener;
import CustomEvents.OpenMsgClientEvent;
import CustomEvents.SeverConnectionEvent;
import chatown.Client;
import chatown.ClientIdentityMsg;
import chatown.OpenMsg;
public class ServerConnection implements Runnable {
private Socket _socket;
private ObjectOutputStream _out;
private ObjectInputStream _in;
private String _clientID = null;
private String _clientNickname = null;
private CustomEventSource _eventNewClientsList = new CustomEventSource();
private CustomEventSource _eventReceiveOpenMessage = new CustomEventSource();
private CustomEventSource _eventServerConnection = new CustomEventSource();
private int _port;
private String _IPAddress;
private boolean _isDataSet = false;
public void registerServerConnectionEvent(ICustomEventListener listener) {
_eventServerConnection.addEventListener(listener);
}
public void registerSettingsFilledEvent(ICustomEventListener listener) {
_eventNewClientsList.addEventListener(listener);
}
public void registerReceiveOpenMsgEvent(ICustomEventListener listener) {
_eventReceiveOpenMessage.addEventListener(listener);
}
public ServerConnection() {
}
public void connect(String IPAddress, int port, String nickname) {
_clientNickname = nickname;
_IPAddress = IPAddress;
_port = port;
_isDataSet = true;
}
private void backoffServerConnect()
{
while (!_isDataSet) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) { e.printStackTrace(); }
}
if(_socket != null)
{
try {
_socket.close();
} catch (IOException e) {
e.printStackTrace();
}
_socket = null;
}
boolean success = false;
int wait = 100; // Exponential back-off
while (!success) {
try {
Thread.sleep(wait);
} catch (InterruptedException e) { e.printStackTrace(); }
wait *= 2;
if (wait > 20000) { wait = 100; }
try {
_socket = new Socket(_IPAddress, _port);
success = true;
//JOptionPane.showMessageDialog(null, "Server is back to business");
} catch (IOException e) {}
}
}
public void disconnect() {
if(_socket != null)
{
try {
_in.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
_in = null;
}
try {
_out.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
_out = null;
}
try {
_socket.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
_socket = null;
}
}
}
@Override
public void run() {
while (true) {
_eventServerConnection.fireEvent(new SeverConnectionEvent(this, false));
backoffServerConnect();
_eventServerConnection.fireEvent(new SeverConnectionEvent(this, true));
try { // send nickname to server and ID if already allocated from before
_out = new ObjectOutputStream(_socket.getOutputStream());
_out.flush();
_out.writeObject(new ClientIdentityMsg(_clientNickname, _clientID));
} catch (IOException e) {
//JOptionPane.showMessageDialog(null, "Error in connection to server");
e.printStackTrace();
try {
_out.close();
_socket.close();
} catch (IOException ee) {
} finally {
_out = null;
_socket = null;
}
}
try { // receive client ID from server
_in = new ObjectInputStream(_socket.getInputStream());
_clientID = (String)_in.readObject(); // receive ID from server
} catch (Exception e) {
e.printStackTrace();
try {
_in.close();
_out.close();
_socket.close();
} catch (IOException ee) {
} finally {
_in = null;
_out = null;
_socket = null;
}
}
MyClientID.set_ID(_clientID);
Object serverObj;
while (_socket != null) {
serverObj = null;
try {
serverObj = _in.readObject();
} catch (IOException e) {
//JOptionPane.showMessageDialog(null, "Error in connection to server");
e.printStackTrace();
try {
_in.close();
_out.close();
_socket.close();
} catch (IOException ee) {
} finally {
_in = null;
_out = null;
_socket = null;
}
} catch (ClassNotFoundException e) {
continue;
}
// receive clients list from server
if (serverObj instanceof Object[]) {
Object[] clientsObject = (Object[]) serverObj;
Client[] clientsArray = new Client[clientsObject.length];
int i = 0;
int myIndex = 0;
for(Object o : clientsObject) {
clientsArray[i] = (Client) o;
if (((Client) o).get_ID().equals(_clientID)) { myIndex = i; } // save my location in array
i++;
}
// make myself appear at the top of the array
Client clt = clientsArray[0];
clientsArray[0] = clientsArray[myIndex];
clientsArray[myIndex] = clt;
// fire clients list event
_eventNewClientsList.fireEvent(new NewClientsListEvent(this, clientsArray, _clientID));
}
else if (serverObj instanceof OpenMsg) {
// fire open message event
_eventNewClientsList.fireEvent(new OpenMsgClientEvent(this, (OpenMsg)serverObj));
}
}
}
}
void sendMessage(String msg)
{
if (_out != null) {
try{
_out.writeObject(msg);
_out.flush();
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
}
}