// SMTPSender.java (C) K. J. Turner, P. K. Johnson 04/03/06 // Simple Mail Transfer Protocol sender (client) package protocol; import java.util.Vector; import support.*; public class SMTPSender implements ProtocolEntity { private PDU pduReceived; private PDU pduSent; private ProtocolEntity peer; private Medium medium; private String name; final static String clientData = "DATA"; final static String clientFrom = "MAIL FROM: sender"; final static String clientHello = "HELO client"; final static String clientMail = "Mail message"; final static String clientQuit = "QUIT"; final static String clientRecipient = "RCPT TO: recipient"; final static String invalidRecipient = "550 Recipient invalid"; final static String invalidSender = "550 Sender invalid"; final static String okRecipient = "250 Recipient OK"; final static String okSender = "250 Sender OK"; final static String serverAccept = "250 Message accepted"; final static String serverClosing = "221 Server Closing"; final static String serverHello = "250 Server hello to client"; final static String serverReady = "220 Server ready"; final static String serverSend = "354 Send mail"; final static String tcpConnect = "TCP connect"; final static String tcpDisconnect = "TCP disconnect"; int state; // protocol state final static int idle = 0; // no connection final static int waitReady = 1; // await server ready final static int waitHello = 2; // await server hello final static int ready = 3; // ready for mail final static int waitSender = 4; // await sender answer final static int waitRecipient = 5; // await recip answer final static int waitSend = 6; // await server send final static int waitAccept = 7; // await server accept final static int waitClose = 8; // await server closing int person = 1; // sender/recipient int recipients; // number of recipients public SMTPSender(Medium m, String name) { this.name = name; medium = m; } public String getName() { return(name); } public Vector getServices() { Vector list = new Vector(); String pduType; if (state == idle) // waiting to connect? list.addElement(tcpConnect); // connect else if (pduReceived != null) { // non-empty reply? pduType = pduReceived.type; // get PDU type if (state == waitReady && // awaiting server ready? pduType.equals(serverReady)) // reply server ready? list.addElement(clientHello); // send hello from client else if (state == waitHello && // awaiting server hello? pduType.equals(serverHello)) // reply server hello? state = ready; // now ready else if (state == waitSender) { // awaiting sender response? if (pduType.equals(okSender)) { // sender is OK? recipients = 0; // no recipients yet state = waitSend; // now ready to send } else if (pduType.equals(invalidSender)) // sender is invalid? state = ready; // back to ready } else if (state == waitRecipient && // awaiting recipient response? (pduType.equals(okRecipient) || // recipient is OK or ... pduType.equals(invalidRecipient))) { // not? if (pduType.equals(okRecipient)) // recipient is OK? recipients++; // add to recipients state = waitSend; // still ready to send } else if (state == waitSend && // awaiting server send? pduType.equals(serverSend)) { // response is server send? list.addElement(clientMail); // send client mail message state = waitAccept; // wait for server accept } else if (state == waitAccept && // awaiting server accept? pduType.equals(serverAccept)) { // reply is server accept? state = ready; // back to ready } else if (state == waitClose && // awaiting server closing? pduType.equals(serverClosing)) { // reply is server closing? list.addElement(tcpDisconnect); // disconnect } if (state == ready) { // ready? list.addElement(clientFrom + person++); // propose sender list.addElement(clientQuit); // propose quit } else if (state == waitSend) { // waiting to send? list.addElement(clientRecipient + person++); // propose recipient if (recipients > 0) // recipients? list.addElement(clientData); // propose to send data } } return(list); } public void initialise() { state = idle; // initialise state pduReceived = null; // note no PDU received person = 1; // initialise sender/recipient } public Vector performService(String s) { Vector events = new Vector(); if (s.equals(clientData)) { // send client data? transmitPDU(new PDU(clientData), peer); // send client data state = waitSend; // await server send } else if (s.startsWith(clientFrom)) { // send sender? transmitPDU(new PDU(s), peer); // send sender state = waitSender; // await sender response } else if (s.equals(clientHello)) { // send client hello? transmitPDU(new PDU(s), peer); // send client hello state = waitHello; // await server hello } else if (s.equals(clientMail)) // send client mail message? transmitPDU(new PDU(clientMail), peer); // send client mail message else if (s.equals(clientQuit)) { // send client quit? transmitPDU(new PDU(clientQuit), peer); // send client quit state = waitClose; // await server closing } else if (s.startsWith(clientRecipient)) { // send recipient? transmitPDU(new PDU(s), peer); // send recipient state = waitRecipient; // await recipient response } if (s.equals(tcpConnect)) { // send TCP connect? transmitPDU(new PDU(tcpConnect), peer); // send TCP connect state = waitReady; // await server ready } else if (s.equals(tcpDisconnect)) { // send TCP disconnect? transmitPDU(new PDU(tcpDisconnect), peer); // send TCP disconnect state = idle; // back to start } if (pduSent != null) { // PDU to send? events.addElement(new ProtocolEvent(ProtocolEvent.TRANSMIT, pduSent)); events.addElement(new ProtocolEvent(ProtocolEvent.RECEIVE, pduSent)); } pduSent = null; // nullify just in case return(events); } public Vector receivePDU(PDU pdu) { pduReceived = pdu; return(new Vector()); } public void transmitPDU(PDU pdu, ProtocolEntity dest) { pdu.setSource(this); pdu.setDestination(dest); pduSent = pdu; this.peer.receivePDU(pdu); pduReceived = null; } public void setPeer(ProtocolEntity peer) { this.peer = peer; } }