UCSD Main WebsiteUCSD Jacobs SchoolDepartment of Computer Science and Engineering
spacer gif
spacer gif
CSE 223B
spacer gifspacer gif
spacer gif
spacer gifCourse Overview
spacer gifspacer gifStructure
spacer gifspacer gifGrading
spacer gifspacer gifUseful books
spacer gif
spacer gifspacer gifSchedule
spacer gif
spacer gifspacer gifReadings
spacer gif
spacer gifLabs
spacer gif   Lab 1
spacer gif   Lab 2
spacer gif   Lab 3
spacer gif
spacer gif
spacer gif
Search
spacer gifspacer gifspacer gif
Advanced search  arrows gif

spacer gif
spacer gifspacer gif
spacer gif
spacer gif
spacer gif
spacer gif
spacer gifspacer gifspacer gif
spacer gif Lab 2: A Concurrent MTA
Due: 11:00am, Tuesday, April 19th, 2011

Preliminaries

As promised, in this lab you're extending the functionality of the simple Mail Transfer Agent (MTA) you wrote for Lab 1. In particular, you're going to write an event-driven server that can processes multiple messages concurrently. By concurrently, I mean that, if your MTA is waiting for some additional information from one client, it should be able to process requests from additional clients. In particular, your server should be able to successfully receive and forward a mail message from one client while receiving a message from another. Further, your MTA should support concurrent forwarding. Namely, if a message has multiple recipients, the lack of response from one destination should not delay the delivery of the message to the others. Finally, you should be able to receive additional messages from the same client even before the previous one has been forwarded. Note this may lead to out-of-order forwarding of messages in many cases.

Specification

Your MTA will continue to use the Internet-standard Simple Mail Transfer Protocol (SMTP) documented in RFC 2821. You still don't need to handle local delivery of mail messages.

You are responsible for the following requirements. Most of them are the same as in Lab 1. New ones are in bold:

  • Your MTA is able to properly receive multiple, simultaneous messages from well-behaved MUAs like Netscape, Outlook Express, or Mozilla. This will require you to support the following SMTP commands: HELO, MAIL, DATA, RCPT, QUIT, and RSET.
  • You may not use the fork() system call.
  • You do not need to handle messages with more than 255 recipients.
  • You do not need to handle mail messages larger than 65535 bytes.
  • Your MTA should deliver each message to every specified recipient if possible. If an error occurs, and it is possible for your MTA to continue processing additional messages, it should do so. If it encounters an unrecoverable error, i.e., socket(), bind(), or listen() fails, it should print an error message and call exit(1).
  • If message delivery for any particular recipient fails at all the available mail exchangers, the message should be queued for an additional attempt. The amount of time to wait before attempting a second delivery should be specified on the command line. If, after two attempts at every listed mail exchanger, the message cannot be delivered to a particular recipient, an "undeliverable mail" message should be generated.
You do not need to bother with the following things. You should just ignore them as best you can.
  • You don't need to support local destinations or source-routed messages. If the argument to the RCPT TO: command is not of the form user@domain.name, you should refuse to accept the message.
  • Your MTA may block (and not process any other messages or clients) during a call to gethostbyname()/getmxrr() or the other provided MX record retrieval functions.
  • You do not need to support the use of dotted-quad IP addresses instead of domain names in both the HELO, MAIL, and RCPT commands.
  • You don't need to implement any other SMTP commands like EXPN, VRFY, HELP, ETRN, NOOP, or VERB. You may simply return an error message if your MTA receives one of these commands.
  • ESMTP extensions. You do not need to recognize EHLO or any of the additional parameters to standard SMTP commands.
  • You do not need to implement the data transparency procedure described in Section 4.5.2 of the RFC. Basically, you can assume your MTA will never receive a message with a period as the first character of a line.
  • You should ignore all headers in the DATA portion of the message. Further, you do not need to implement any sort of loop detection.
If you are able to send multiple, simultaneous email messages from two or more MTAs, you're in good shape.

Building your MTA (C/C++)

We have provided an initial skeleton directory to get you started. It is available as /cse223b/sp11/labs/lab2/lab2.tgz on the class machines. You should copy this file to your working directory. The following sequence of commands should extract the files and build the initial (useless) executable:
% tar xzf lab2.tgz
% cd lab2
% gmake
The tarball contains four files: domain.c, domain.h, Makefile, and mta2.C. mta2.C contains some initial code to get you started. Currently, it just accepts TCP connections, prints debugging information, and waits for others. It also runs a toy timer set to the delay value specified on the command line. You can run the executable by typing:
% ./mta2 30 2225
Where 30 is the number of seconds to wait between delivery attempts, and 2225 is the port you want it to listen on. In order not to conflict with the already running MTA (sendmail), you should run your MTA on a port other than 25 (larger than 1024). During testing you're likely to want to use something other than 2225 as well so it doesn't conflict with other students working on their projects.

The provided code has the makings of a select-based event loop, as discussed in class. I have also included an example of how to set a timer, although you will likely need to do something more sophisticated since you may need keep track of timers for multiple messages at once. As you can see, each connection is managed by its own object, which defines callbacks to be called from the event loop. Feel free to change our object structure around as you see fit.

One final note: by default, connect() is a blocking system call. In order to prevent your MTA from hanging while attempting to contact a remote MTA, you'll need to set the O_NONBLOCK flag on any socket you use to connect to another server. I suggest you do a man on the fcntl() system call. With the socket set non-blocking, the connect() call will return immediately, whether or not it was successful. In order to determine when the socket has successfully connected, you can check for writability in the select() loop. Once select() indicates the socket is writable, it has either connected or failed. You may find the getpeername() function useful to determine whether the connection succeeded or not.

Building your MTA (Java)

For those of you who choose to use Java, we have provided example files to get you started in /cse223b/sp11/labs/lab2/lab2.tgz. You may not import JavaMail, SMTPClient, or any other mail-related or asynchronous connection handling libraries in your code! If you are unsure about a library that you want to use, ask the TA!

MXDomain.java provides a simple method for obtaining DNS MX records, similar to what's provided in domain.c for the C/C++ skeleton code. It exports a single function called getMXRecords which, when given domain name string, returns a Java ArrayList of MXRecord objects from the DNSJava library. Be sure to include the DNSJava jar file (/usr/share/java/dnsjava.jar) in your classpath before using this class!

MTA2.java contains the skeleton MTA code. Like the C version, it provides an example of a select loop and a simple timer. Client.java and TimeHandler.java contain skeleton client and timer handlers, respectively. Feel free to change the object structure or define new objects as you see fit. You can build it by running:

% javac MTA2.java
After a successful build, you can start the server by executing:
% java MTA 30 2225
Where 30 is the number of seconds to wait between delivery attempts, and 2225 is the port you want it to listen on. In order not to conflict with the already running MTA (sendmail), you should run your MTA on a port other than 25 (larger than 1024). During testing you're likely to want to use something other than 2225 as well so it doesn't conflict with other students working on their projects.

Building your MTA (Python)

We also provide a skeleton Python file, mta2.py, in /cse223b/sp11/labs/lab2/lab2.tgz. Like the C and Java versions, it provides a simple example of a select loop and a basic timer. If you choose to use Python, you may not import email, mimelib, smtplib, asyncore, asynchat, twisted, or any other mail-related or asynchronous connection handling modules into your code! If you are unsure about a module that you want to use, ask the TA!

Looking up MX records in Python is fairly straightforward:

import dns.resolver

dns_result = dns.resolver.query('cs.ucsd.edu', 'MX')

for mx_record in dns_result:
    print mx_record
Outputs:
10 oec-vmmx.ucsd.edu
5 inbound.ucsd.edu
You can also access individual elements of the dns_result collection via standard subscript notation: dns_result[0], dns_result[1], etc., and the number of elements is available via len().

You can run the code by executing:

python mta2.py 30 2225
Where 30 is the number of seconds to wait between delivery attempts, and 2225 is the port you want it to listen on. In order not to conflict with the already running MTA (sendmail), you should run your MTA on a port other than 25 (larger than 1024). During testing you're likely to want to use something other than 2225 as well so it doesn't conflict with other students working on their projects.

Testing your MTA

The easiest way to test and debug your MTA is to use it interactively just as we did above. Of course, once your MTA accepts messages, you'll need to send them on. I'd suggest trying to send messages to yourself so you can see if it actually succeeds! You might find programs like Ethereal and Netcat (nc) useful to follow the communication between your MTA and others.

In order to test the ability of your MTA to continue to process messages while waiting for a slow peer MTA, I have provided an infinitely slow MTA running on sysnet41.ucsd.edu; it will never accept messages, just accept connections and hang. If you'd like to test your MX handling as well, there is an MX record for tarpit.sysnet.ucsd.edu that points to sysnet41.ucsd.edu. So, if you attempt to send a message to anyone@tarpit.sysnet.ucsd.edu, your MTA should never succeed, but continue processing other mail. If you find this infinite wait unsatisfying, you are welcome to add an additional timeout to your MTA that aborts open connections if they stall for longer than the specified delay.

Once you think your MTA is working, you can hook it up to a real MUA and give it a whirl. The simplest way is to use your normal mail reader (Eudora, Netscape, Mozilla, Outlook Express, etc.) and just configure it to use your MTA rather than your default one.

For Mozilla, you can do this by going to Edit->Mail and Newsgroup Account Settings and selecting the Outgoing Server (SMTP) tab. Enter the name of the machine your MTA is running on (e.g., sysnet30.ucsd.edu) and port 2225. Make sure you turn off SSL (Never) and uncheck the user name and password option.

Similar changes can be made to other mailers. I'll post them here if anyone wants to email me how to do this in your own mail reader.

Collaboration policy

All code for this assignment must be written individually. You are not allowed to look at anyone else's solutions or solutions to similar assignments you may find for courses at UCSD or other institutions. You may discuss the assignment with fellow students, but all code you submit must be either yours alone or code that was provided to you as part of the assignment.

Turnin procedure

The turnin procedure is the same as for the previous lab. When you're ready to submit your code, you can execute the following command:
% gmake turnin
which will copy your tar file to the submission directory.

spacer gif

spacer gif
spacer gifback to top ^
spacer gif
spacer gif
spacer gif
spacer gif
9500 Gilman Drive, La Jolla, CA 92093-0114
spacer gif
About CSE | CSE People | Faculty & Research | Graduate Education | Undergraduate Education
Department Administration | Contact CSE | Help | Search | Site map | Home
snoeren@cs.ucsd.edu
Official web page of the University of California, San Diego
Copyright © 2002 Regents of the University of California. All rights reserved.
spacer gif