2019-10-06 10:45:19 +02:00
|
|
|
package envoy.client;
|
|
|
|
|
2019-12-31 10:57:11 +01:00
|
|
|
import java.io.Closeable;
|
|
|
|
import java.io.IOException;
|
2019-12-29 11:54:05 +01:00
|
|
|
import java.net.Socket;
|
2019-12-31 15:38:52 +01:00
|
|
|
import java.util.HashMap;
|
2019-12-14 10:53:20 +01:00
|
|
|
import java.util.Map;
|
2019-12-21 18:29:59 +01:00
|
|
|
import java.util.logging.Logger;
|
2019-11-27 17:07:25 +01:00
|
|
|
|
2020-01-02 16:11:41 +01:00
|
|
|
import javax.naming.TimeLimitExceededException;
|
|
|
|
|
2019-12-21 18:29:59 +01:00
|
|
|
import envoy.client.util.EnvoyLog;
|
2020-01-02 16:11:41 +01:00
|
|
|
import envoy.data.*;
|
2019-12-29 11:54:05 +01:00
|
|
|
import envoy.util.SerializationUtils;
|
2019-10-06 10:45:19 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Project: <strong>envoy-client</strong><br>
|
2019-10-12 11:19:29 +02:00
|
|
|
* File: <strong>Client.java</strong><br>
|
2019-10-06 10:45:19 +02:00
|
|
|
* Created: <strong>28 Sep 2019</strong><br>
|
2019-12-21 18:29:59 +01:00
|
|
|
*
|
2019-10-12 08:19:00 +02:00
|
|
|
* @author Kai S. K. Engelbart
|
|
|
|
* @author Maximilian Käfer
|
2019-10-12 14:45:58 +02:00
|
|
|
* @author Leon Hofmeister
|
2019-10-31 22:11:50 +01:00
|
|
|
* @since Envoy v0.1-alpha
|
2019-10-06 10:45:19 +02:00
|
|
|
*/
|
2019-12-31 10:57:11 +01:00
|
|
|
public class Client implements Closeable {
|
|
|
|
|
|
|
|
private Socket socket;
|
|
|
|
private Receiver receiver;
|
|
|
|
private boolean online;
|
2019-10-06 10:45:19 +02:00
|
|
|
|
2019-12-30 17:18:03 +01:00
|
|
|
private volatile User sender;
|
|
|
|
private User recipient;
|
2019-12-31 10:57:11 +01:00
|
|
|
|
2020-01-02 16:11:41 +01:00
|
|
|
private volatile Contacts contacts;
|
|
|
|
|
2019-12-31 10:57:11 +01:00
|
|
|
private Config config = Config.getInstance();
|
2019-10-06 10:45:19 +02:00
|
|
|
|
2019-12-21 18:29:59 +01:00
|
|
|
private static final Logger logger = EnvoyLog.getLogger(Client.class.getSimpleName());
|
|
|
|
|
2019-12-14 11:30:00 +01:00
|
|
|
/**
|
2020-01-02 16:11:41 +01:00
|
|
|
* Enters the online mode by acquiring a user ID from the server. As a
|
|
|
|
* connection has to be established and a handshake has to be made, this method
|
|
|
|
* will block for up to 5 seconds. If the handshake does exceed this time limit,
|
|
|
|
* an exception is thrown.
|
2019-12-21 18:29:59 +01:00
|
|
|
*
|
2019-12-29 11:54:05 +01:00
|
|
|
* @param credentials the login credentials of the user
|
2019-12-30 17:18:03 +01:00
|
|
|
* @throws Exception if the online mode could not be entered or the request
|
|
|
|
* failed for some other reason
|
2019-12-14 11:30:00 +01:00
|
|
|
* @since Envoy v0.2-alpha
|
|
|
|
*/
|
2019-12-30 17:18:03 +01:00
|
|
|
public void onlineInit(LoginCredentials credentials) throws Exception {
|
2019-12-31 10:57:11 +01:00
|
|
|
// Establish TCP connection
|
2019-12-29 11:54:05 +01:00
|
|
|
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.");
|
|
|
|
|
2019-12-30 17:18:03 +01:00
|
|
|
// Create message receiver
|
2019-12-31 10:57:11 +01:00
|
|
|
receiver = new Receiver(socket.getInputStream());
|
2019-11-04 23:10:53 +01:00
|
|
|
|
2019-12-30 17:18:03 +01:00
|
|
|
// Register user creation processor
|
|
|
|
receiver.registerProcessor(User.class, sender -> { logger.info("Acquired user object " + sender); this.sender = sender; });
|
2020-01-02 16:11:41 +01:00
|
|
|
receiver.registerProcessor(Contacts.class, contacts -> { logger.info("Acquired contacts object " + contacts); this.contacts = contacts; });
|
2019-12-30 17:18:03 +01:00
|
|
|
|
2019-12-31 15:38:52 +01:00
|
|
|
// Start receiver
|
|
|
|
new Thread(receiver).start();
|
|
|
|
|
2019-12-31 10:57:11 +01:00
|
|
|
// Write login credentials
|
|
|
|
logger.finest("Sending login credentials...");
|
|
|
|
SerializationUtils.writeBytesWithLength(credentials, socket.getOutputStream());
|
|
|
|
|
2019-12-30 17:18:03 +01:00
|
|
|
// Wait for a maximum of five seconds to acquire the sender object
|
|
|
|
long start = System.currentTimeMillis();
|
2020-01-02 16:11:41 +01:00
|
|
|
while (sender == null || contacts == null) {
|
|
|
|
if (System.currentTimeMillis() - start > 5000) throw new TimeLimitExceededException("Did not log in after 5 seconds");
|
2019-12-30 17:18:03 +01:00
|
|
|
Thread.sleep(500);
|
2019-12-29 11:54:05 +01:00
|
|
|
}
|
|
|
|
|
2020-01-02 16:11:41 +01:00
|
|
|
logger.info("Handshake completed.");
|
2019-12-29 11:54:05 +01:00
|
|
|
online = true;
|
2020-01-02 16:11:41 +01:00
|
|
|
|
|
|
|
// Remove user creation processor
|
|
|
|
receiver.removeAllProcessors();
|
|
|
|
|
|
|
|
// Register processors for message and status handling
|
|
|
|
receiver.registerProcessor(Message.class, new ReceivedMessageProcessor());
|
2019-11-04 23:10:53 +01:00
|
|
|
}
|
2019-11-09 13:25:18 +01:00
|
|
|
|
2019-12-31 10:57:11 +01:00
|
|
|
/**
|
|
|
|
* 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 {
|
2019-12-31 15:38:52 +01:00
|
|
|
checkOnline();
|
2019-12-31 10:57:11 +01:00
|
|
|
SerializationUtils.writeBytesWithLength(message, socket.getOutputStream());
|
2020-01-02 16:11:41 +01:00
|
|
|
message.nextStatus();
|
2019-12-31 10:57:11 +01:00
|
|
|
}
|
|
|
|
|
2019-11-04 23:10:53 +01:00
|
|
|
/**
|
2019-12-14 11:30:00 +01:00
|
|
|
* @return a {@code Map<String, User>} of all users on the server with their
|
|
|
|
* user names as keys
|
2019-12-14 10:53:20 +01:00
|
|
|
* @since Envoy v0.2-alpha
|
2019-11-04 23:10:53 +01:00
|
|
|
*/
|
2019-12-14 10:53:20 +01:00
|
|
|
public Map<String, User> getUsers() {
|
2019-12-31 15:38:52 +01:00
|
|
|
checkOnline();
|
|
|
|
Map<String, User> users = new HashMap<>();
|
2020-01-02 16:11:41 +01:00
|
|
|
contacts.getContacts().forEach(u -> users.put(u.getName(), u));
|
2019-12-31 15:38:52 +01:00
|
|
|
return users;
|
2019-10-19 15:09:32 +02:00
|
|
|
}
|
|
|
|
|
2019-12-31 10:57:11 +01:00
|
|
|
@Override
|
|
|
|
public void close() throws IOException { if (online) socket.close(); }
|
|
|
|
|
2019-12-31 15:38:52 +01:00
|
|
|
private void checkOnline() { if (!online) throw new IllegalStateException("Client is not online"); }
|
|
|
|
|
2019-10-12 17:35:58 +02:00
|
|
|
/**
|
2019-11-04 23:10:53 +01:00
|
|
|
* @return the sender object that represents this client.
|
2019-10-26 18:31:49 +02:00
|
|
|
* @since Envoy v0.1-alpha
|
2019-10-12 17:35:58 +02:00
|
|
|
*/
|
2019-10-19 12:10:52 +02:00
|
|
|
public User getSender() { return sender; }
|
|
|
|
|
2019-12-14 11:30:00 +01:00
|
|
|
/**
|
|
|
|
* Sets the client user which is used to send messages.
|
2019-12-21 18:29:59 +01:00
|
|
|
*
|
2019-12-14 11:30:00 +01:00
|
|
|
* @param sender the client user to set
|
|
|
|
* @since Envoy v0.2-alpha
|
|
|
|
*/
|
2019-12-14 10:53:20 +01:00
|
|
|
public void setSender(User sender) { this.sender = sender; }
|
|
|
|
|
2019-11-04 23:10:53 +01:00
|
|
|
/**
|
|
|
|
* @return the current recipient of the current chat.
|
|
|
|
* @since Envoy v0.1-alpha
|
|
|
|
*/
|
2019-10-19 12:10:52 +02:00
|
|
|
public User getRecipient() { return recipient; }
|
|
|
|
|
2019-11-04 23:10:53 +01:00
|
|
|
/**
|
2019-12-07 10:44:25 +01:00
|
|
|
* Sets the recipient.
|
2019-12-21 18:29:59 +01:00
|
|
|
*
|
2019-12-14 11:30:00 +01:00
|
|
|
* @param recipient the recipient to set
|
2019-11-04 23:10:53 +01:00
|
|
|
* @since Envoy v0.1-alpha
|
|
|
|
*/
|
2019-10-19 12:10:52 +02:00
|
|
|
public void setRecipient(User recipient) { this.recipient = recipient; }
|
|
|
|
|
2019-12-07 10:44:25 +01:00
|
|
|
/**
|
2019-10-31 22:11:50 +01:00
|
|
|
* @return true, if a recipient is selected
|
2019-11-04 23:10:53 +01:00
|
|
|
* @since Envoy v0.1-alpha
|
|
|
|
*/
|
2019-10-19 12:10:52 +02:00
|
|
|
public boolean hasRecipient() { return recipient != null; }
|
2019-12-11 18:52:30 +01:00
|
|
|
|
2019-12-31 10:57:11 +01:00
|
|
|
/**
|
|
|
|
* @return the {@link Receiver} used by this {@link Client}
|
|
|
|
*/
|
|
|
|
public Receiver getReceiver() { return receiver; }
|
|
|
|
|
2019-12-11 18:52:30 +01:00
|
|
|
/**
|
|
|
|
* @return {@code true} if a connection to the server could be established
|
2019-12-14 11:30:00 +01:00
|
|
|
* @since Envoy v0.2-alpha
|
2019-12-11 18:52:30 +01:00
|
|
|
*/
|
|
|
|
public boolean isOnline() { return online; }
|
2019-12-21 21:23:19 +01:00
|
|
|
}
|