package dslab.client; import at.ac.tuwien.dsg.orvell.StopShellException; import at.ac.tuwien.dsg.orvell.annotation.Command; import dslab.ComponentFactory; import dslab.authentication.AuthenticationException; import dslab.crypto.MessageClientHash; import dslab.mailbox.MessageNotFoundException; import dslab.protocol.Message; import dslab.protocol.dmap.MessageMetadata; import dslab.protocol.dmtp.InvalidMessageException; import dslab.protocol.dmtp.NoOpenMessageException; import dslab.rmi.channel.SocketChannel; import dslab.rmi.stub.dmap.DmapClientStub; import dslab.routing.Address; import dslab.routing.AddressResolutionException; import dslab.util.ComponentId; import dslab.util.Config; import dslab.util.MessageClientConfig; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.net.Socket; import java.nio.channels.ClosedChannelException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import static java.lang.Integer.parseInt; public class MessageClient implements IMessageClient, Runnable { private final InputStream in; private final PrintStream out; private final ComponentFactory componentFactory; private final MessageClientConfig config; private final MessageClientHash hash; private static final Logger LOG = Logger.getLogger(MessageClient.class.getSimpleName()); private DmapClientStub dmap; /** * Creates a new client instance. * * @param componentId the id of the component that corresponds to the Config resource * @param config the component config * @param in the input stream to read console input from * @param out the output stream to write console output to */ public MessageClient(String componentId, Config config, InputStream in, PrintStream out) { componentFactory = new ComponentFactory(new ComponentId(componentId), config); this.in = in; this.out = out; this.config = componentFactory.getMessageClientConfig(); this.hash = new MessageClientHash(); } public static void main(String[] args) throws Exception { IMessageClient client = ComponentFactory.createMessageClient(args[0], System.in, System.out); client.run(); } @Override public void run() { dmap = componentFactory.getDmapClientStub(); try { dmap.startsecure(); dmap.login(config.mailboxUser(), config.mailboxPassword()); } catch (AuthenticationException e) { throw new RuntimeException( "The username " + config.mailboxUser() + " or the corresponding password was incorrect." + "Check the credentials in the .properties file.", e); } catch (ClosedChannelException e) { LOG.log(Level.SEVERE, "Failed to set up connection to DMAP server", e); } componentFactory.createShell(this, in, out).run(); } @Override @Command public void inbox() { try { List list = dmap.list(); for (MessageMetadata m : list) { out.println(m.getId() + "\n" + dmap.show(m.getId()).toGuiString()); } } catch (AuthenticationException e) { throw new RuntimeException(e); //never happens } catch (MessageNotFoundException e) { out.println(e.getMessage()); } catch (Exception e) { out.println(e.getMessage()); } } @Override @Command public void delete(String id) { try { dmap.delete(parseInt(id)); out.println("ok"); } catch (AuthenticationException e) { throw new RuntimeException(e); //never happens } catch (MessageNotFoundException e) { out.println(e.getMessage()); } } @Override @Command public void verify(String id) { try { out.println(hash.isValid(dmap.show(parseInt(id))) ? "ok" : "error invalid hash"); } catch (MessageNotFoundException | NumberFormatException e) { out.println(e.getMessage()); } catch (AuthenticationException e) { throw new RuntimeException(e); //never happens } } @Override @Command public void msg(String to, String subject, String data) { try { var socket = new Socket(config.transferHost(), config.transferPort()); var channel = new SocketChannel(socket); var message = new Message(); try (var dmtp = componentFactory.newDmtpInstance(channel)) { String[] raw = to.split(","); List
rx = new ArrayList<>(); for (String r : raw) { rx.add(new Address(r)); } message.setSender(config.transferEmail()); message.setRecipients(rx); message.setSubject(subject); message.setData(data); dmtp.begin(); dmtp.to(rx); dmtp.from(config.transferEmail()); dmtp.subject(subject); dmtp.data(data); hash.calculateAndSet(message); dmtp.hash(message.getHash()); dmtp.send(); channel.close(); socket.close(); } catch (AddressResolutionException e) { channel.write("error address resolution failed"); } catch (NoOpenMessageException e) { channel.write("error missing "); } catch (InvalidMessageException e) { channel.write("error message build failed"); } } catch (IOException e) { throw new RuntimeException( "Couldn't establish a connection to the DMTP server. Are you sure it is running?"); } } @Override @Command public void shutdown() { dmap.quit(); this.componentFactory.shutdown(); throw new StopShellException(); } }