You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
6.7 KiB
Java

// 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<String> getServices() {
Vector<String> list = new Vector<String>();
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<ProtocolEvent> performService(String s) {
Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
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<ProtocolEvent> receivePDU(PDU pdu) {
pduReceived = pdu;
return(new Vector<ProtocolEvent>());
}
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;
}
}