160 lines
6.6 KiB
Java
160 lines
6.6 KiB
Java
package dslab.mailbox;
|
|
|
|
import dslab.Email;
|
|
import dslab.Message;
|
|
import dslab.exception.MalformedInputException;
|
|
import dslab.exception.UnknownRecipientException;
|
|
|
|
import java.io.*;
|
|
import java.net.Socket;
|
|
import java.net.SocketException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.LinkedList;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.logging.Logger;
|
|
|
|
public class DMTPConnection implements Runnable {
|
|
Logger logger = Logger.getLogger(DMTPConnection.class.getName());
|
|
private final Socket socket;
|
|
private PrintWriter out;
|
|
private BufferedReader in;
|
|
|
|
private Message msg = new Message();
|
|
|
|
private final String domain;
|
|
|
|
private final ConcurrentHashMap<Email, LinkedList<Message>> messageStorage;
|
|
private final ConcurrentHashMap<String, String> userStorage;
|
|
|
|
public DMTPConnection(Socket connection, ConcurrentHashMap<Email, LinkedList<Message>> messageStorage, ConcurrentHashMap<String, String> userStorage, String domain) {
|
|
this.socket = connection;
|
|
this.messageStorage = messageStorage;
|
|
this.userStorage = userStorage;
|
|
this.domain = domain;
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
logger.finer("Preparing for DMTP communication in " + this.toString());
|
|
try {
|
|
this.out = new PrintWriter(socket.getOutputStream(), true);
|
|
this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
|
out.println("ok DMTP");
|
|
|
|
String userInput;
|
|
|
|
try {
|
|
if (!("begin".equals(in.readLine()))) {
|
|
out.println("error protocol error");
|
|
shutdown();
|
|
}
|
|
} catch (SocketException e) {
|
|
// Thrown if socket has already been closed by shutdown() method
|
|
logger.finer("Received interrupt. Exiting " + this.toString());
|
|
shutdown();
|
|
}
|
|
out.println("ok");
|
|
|
|
while (!Thread.currentThread().isInterrupted() && (userInput = in.readLine()) != null) {
|
|
if ("quit".equals(userInput)) {
|
|
out.println("ok bye");
|
|
shutdown();
|
|
} else if ("send".equals(userInput)) {
|
|
try {
|
|
storeMessage();
|
|
out.println("ok");
|
|
} catch (UnknownRecipientException e) {
|
|
out.println(e.getMessage());
|
|
}
|
|
} else if ("to".equals(userInput.split("\\s+")[0])) {
|
|
msg.setTo(new ArrayList<>());
|
|
String[] emailAddresses = userInput.split("\\s+")[1].split(",");
|
|
logger.info("Split EMail addresses: " + Arrays.toString(emailAddresses));
|
|
int count = 0;
|
|
try {
|
|
for (String emailAddress : emailAddresses) {
|
|
logger.info("Current email address in msg.getTo(): " + emailAddress);
|
|
Email add = new Email(emailAddress);
|
|
if (this.domain.equals(add.getDomain())) {
|
|
logger.info("Address " + emailAddress + " belongs to this domain " + this.domain);
|
|
if (!this.userStorage.containsKey(add.getUsername())) {
|
|
logger.info("Our userStorage in domain " + this.domain + " does not contain user " + add.getUsername());
|
|
out.println("error unknown recipient " + add.toString());
|
|
} else {
|
|
logger.info("Address " + add.toString() + " belongs to this domain and user exists. Adding address to msg.To() field");
|
|
msg.addTo(add);
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
out.println("ok " + count);
|
|
} catch (MalformedInputException e) {
|
|
out.println(e.getMessage());
|
|
}
|
|
} else if ("from".equals(userInput.split("\\s+")[0])) {
|
|
try {
|
|
Email from = new Email(userInput.split("\\s+")[1]);
|
|
this.msg.setFrom(from);
|
|
out.println("ok");
|
|
} catch (MalformedInputException mie) {
|
|
out.println(mie.getMessage());
|
|
}
|
|
} else if ("subject".equals(userInput.split("\\s+")[0])) {
|
|
String subject = "";
|
|
if (userInput.split("\\s+").length > 1)
|
|
subject = userInput.split("\\s+", 2)[1];
|
|
msg.setSubject(subject);
|
|
out.println("ok");
|
|
} else if ("data".equals(userInput.split("\\s+")[0])) {
|
|
String data = userInput.split("\\s+", 2)[1];
|
|
msg.setData(data);
|
|
out.println("ok");
|
|
} else {
|
|
out.println("error protocol error");
|
|
shutdown();
|
|
}
|
|
}
|
|
} catch (InterruptedIOException ioe) {
|
|
logger.info("Received interrupt from parent. Shutting down...");
|
|
shutdown();
|
|
} catch (IOException e) {
|
|
logger.severe("Failed to get IO-Stream");
|
|
e.printStackTrace();
|
|
shutdown();
|
|
}
|
|
}
|
|
|
|
private synchronized void storeMessage() throws UnknownRecipientException {
|
|
logger.info("Storing message " + msg.toString());
|
|
this.msg.setId(MailboxServer.id++);
|
|
String errorUnknownRecipient = "";
|
|
for (Email recipient : this.msg.getTo()) {
|
|
if (this.messageStorage.containsKey(recipient)) {
|
|
this.messageStorage.get(recipient).add(this.msg);
|
|
} else {
|
|
if (errorUnknownRecipient.isBlank())
|
|
errorUnknownRecipient = "error unknown recipient " + recipient.getUsername();
|
|
}
|
|
}
|
|
|
|
if (!errorUnknownRecipient.isBlank())
|
|
throw new UnknownRecipientException(errorUnknownRecipient);
|
|
this.msg = new Message();
|
|
}
|
|
|
|
public void shutdown() {
|
|
logger.info("Shutting down client connection " + this.toString());
|
|
try {
|
|
if (socket != null)
|
|
socket.close();
|
|
in.close();
|
|
out.close();
|
|
} catch (IOException e) {
|
|
logger.severe("Error closing socket and/or IO-streams");
|
|
e.printStackTrace();
|
|
}
|
|
Thread.currentThread().interrupt();
|
|
}
|
|
}
|