package envoy.client;
import java.io.Closeable;
import java.io.IOException;
import java.net.Socket;
import java.util.Map;
import java.util.logging.Logger;
import envoy.client.util.EnvoyLog;
import envoy.data.LoginCredentials;
import envoy.data.Message;
import envoy.data.User;
import envoy.exception.EnvoyException;
import envoy.util.SerializationUtils;
/**
* Project: envoy-client
* File: Client.java
* Created: 28 Sep 2019
*
* @author Kai S. K. Engelbart
* @author Maximilian Käfer
* @author Leon Hofmeister
* @since Envoy v0.1-alpha
*/
public class Client implements Closeable {
private Socket socket;
private Receiver receiver;
private boolean online;
private volatile User sender;
private User recipient;
private Config config = Config.getInstance();
private static final Logger logger = EnvoyLog.getLogger(Client.class.getSimpleName());
/**
* Enters the online mode by acquiring a user ID from the server.
*
* @param credentials the login credentials of the user
* @throws Exception if the online mode could not be entered or the request
* failed for some other reason
* @since Envoy v0.2-alpha
*/
public void onlineInit(LoginCredentials credentials) throws Exception {
// Establish TCP connection
logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
socket = new Socket(config.getServer(), config.getPort());
logger.info("Successfully connected to server.");
// Create message receiver
receiver = new Receiver(socket.getInputStream());
// Register user creation processor
receiver.registerProcessor(User.class, sender -> { logger.info("Acquired user object " + sender); this.sender = sender; });
// Write login credentials
logger.finest("Sending login credentials...");
SerializationUtils.writeBytesWithLength(credentials, socket.getOutputStream());
// Start receiver
new Thread(receiver).start();
// Wait for a maximum of five seconds to acquire the sender object
long start = System.currentTimeMillis();
while (sender == null) {
if (System.currentTimeMillis() - start > 5000) throw new EnvoyException("Did not log in after 5 seconds");
Thread.sleep(500);
}
online = true;
}
/**
* Sends a message to the server.
*
* @param message the message to send
* @throws IOException if the message does not reach the server
* @since Envoy v0.3-alpha
*/
public void sendMessage(Message message) throws IOException {
if (!online) throw new IllegalStateException("Client is not online");
SerializationUtils.writeBytesWithLength(message, socket.getOutputStream());
}
/**
* @return a {@code Map} of all users on the server with their
* user names as keys
* @since Envoy v0.2-alpha
*/
public Map getUsers() {
// TODO
return null;
}
@Override
public void close() throws IOException { if (online) socket.close(); }
/**
* @return the sender object that represents this client.
* @since Envoy v0.1-alpha
*/
public User getSender() { return sender; }
/**
* Sets the client user which is used to send messages.
*
* @param sender the client user to set
* @since Envoy v0.2-alpha
*/
public void setSender(User sender) { this.sender = sender; }
/**
* @return the current recipient of the current chat.
* @since Envoy v0.1-alpha
*/
public User getRecipient() { return recipient; }
/**
* Sets the recipient.
*
* @param recipient the recipient to set
* @since Envoy v0.1-alpha
*/
public void setRecipient(User recipient) { this.recipient = recipient; }
/**
* @return true, if a recipient is selected
* @since Envoy v0.1-alpha
*/
public boolean hasRecipient() { return recipient != null; }
/**
* @return the {@link Receiver} used by this {@link Client}
*/
public Receiver getReceiver() { return receiver; }
/**
* @return {@code true} if a connection to the server could be established
* @since Envoy v0.2-alpha
*/
public boolean isOnline() { return online; }
}