Announcements
- A6 due December 8 (9th for Extension).
- During reading period, you may submit up to one assignment for regrading for up to 90% of the total points on the assignment. Should you wish to do this, send mail to margo@eecs.harvard.edu when you have submitted the version you wish to be graded. Also, please make sure the commit says, "RESUBMIT GRADE ME."
- All work (resubmissions and A6) must be submitted by the end of day (5:00 PM) on December 10.
- The final exam is on Saturday, December 12 from 9:00 AM to Noon. We are in Lowell Lecture Hall. There are a few outlets, but not many, so please bring your laptop charged. We will try to make the outlets available, so you can recharge for a brief period and then return to your seat so others can do the same.
- The exam will be completed online as the midterm was. I have created
the final directory in the
cs61-psets
repository. Please follow the standard procedure (as outlined in each problem set and the midterm examination) to pull the repository and have your final exam entry on the grading server reference your repository (not your partner's). PLEASE DO THIS BEFORE THE EXAM, so that we don't end up with any last minute panic the morning of the exam. I will undoubtedly edit the exam.txt until about Wednesday, 12/10, so you may want to pull now to make sure you're all set up and then re-pull again towards the end of next week to get the most up to date version of the exam.txt file. - Please fill out the Q Guide surveys (and equivalent for the extension school). We take feedback quite seriously and appreciate any feedback you can offer. The surveys are anonymous, and we do not get results until after final grades have been submitted.
Let's Review
What happened on Tuesday? We started playing with a pair of client and
server processes and then I dumped a mean, nasty client on you! The
serviceblaster
is not a nice program. It is intentionally trying to
consume resources on the server. I'm assuming that you all observed that
no matter what architecture you tried for your serviceserver
, you
ended up hitting some resource limit: open files, ability to fork
processes, memory for creating threads. Let me step back and make two
points:
1. You should not build clients like serviceblaster
. You should build
more polite clients, but you should be aware that there are people in
this world who take great delight in building clients that do bad things
do your server. (My apologies for not making this more explicit last
time.) A client like this is launching a Denial of Service Attack
(DOS). When you have such an attack launched from multiple locations,
it's called a DDOS -- Distributed Denial of Service attack.
2. You want to learn to build servers that are immune to attacks (or as immune as possible).
Learning Objectives
- Apply defensive coding practices to make your server immune to a DOS
attack like the one launched by
serviceblaster
.
Get the Code
We'll start with the serviceblaster
from Tuesday and a version of the
serviceserver
. You'll find this in our last cs61-exercises
directory
l26
.
What Problem do We Need to Solve
If you have not already done so, take a look at serviceblaster
and see
what makes it evil. (Note that once it establishes a connection, it
simply spins forever doing nothing! Thus it holds the connection open,
but is not sending any information over the socket, so the fgets
on
the server never returns; it blocks.)
So, what can we do on our server to ensure that we don't hang forever? We want to read from a file descriptor, but if nothing ever gets written to it, we'd like to timeout after waiting a reasonable amount of time. Do you recall what system call lets us wait on a file descriptor subject to a timeout?
Building a more Robust Server
OK, so let's figure out how to transform our server into one that is
robust against the evil serviceblaster
.
1. You may recall that when we started creating a lot of threads, we
got quite slow. So, we're going to start with an unthreaded server and
see if we can make it handle the load! So, let's start with our original
serviceserver
that looped handling individual requests. This is the
version you'll find in today's directory. Note: This means that we need
to be careful that we never let our server block, because if we do, we
may block for a long time and there are no other threads to run. You'll
want to think about that as you architect your server.
If we aren't spawning multiple threads or processes, then we need to
avoid having our server block on anything. Read the man page for
fcntl
. Look for O_NONBLOCK
. Figure out how to issue an appropriate
fcntl
call that will prevent your server from blocking on its
listening fd. Make sure your code still builds and runs, but you
haven't solved many problems yet, so there is no need to run a full
test.
Note: fcntl
is, in many ways, a huge hack. Nonetheless, it is an
enormously useful hack. You need not memorize every flag and option, but
we do recommend that you skim the manual page so you have an idea of the
kinds of things it can do. In the future, you might find the time
investment useful!
2. Let's start simple: Add a call to select
to determine if you
should try to do an accept
on the listening fd. (Do not specify a
timeout value -- two reasons -- first, we would need time to start up
our client, second we have non-blocking FDs so we shouldn't need it.)
You'll need to first construct a file descriptor set -- check the
select
man page if you've forgotten how to do that.
Build that. If you run it, you'll see that it accepts the first connection, but then hangs, why?
3. Oh right! We made the listening socket non-blocking, but what
happens when we then accept the connection and go into
handle_connection
? We block on the fgets
, because the client never
sends a message. I guess we should make this file descriptor
non-blocking as well! You know how to do that, so go for it. Now what
happens if you build and run?
If you got this right, you'll see that the server now reports an error
on every connection, because the fgets
returns having not received a
message (which is what we intended). But, rather than reporting an
error, what should we do?
4. Well, we have a couple of options. We could close down the
connection -- a reasonable response if we know that the client is evil,
but what if we don't know it's evil? We might want to keep the
connection open for awhile. Let's do this in two parts. Modify
handle_connection
so that it simply returns (without printing an error
message) when the (now non-blocking) fgets
call returns with no data.
Now what happens?
5. Yeay! If you got this far then you should now be able to run the
serviceblaster
to completion! And it runs quickly. But -- what if the
client weren't completely evil and every once in awhile it did something
productive? Is there a way that we could keep the individual connections
open for awhile in case the client sent a valid message? You'll need to
do two things: 1) do something to differentiate a connection whose
fgets
returned because no bytes were read and one where the server
sent a valid message and 2) keep track of the open connections so will
be able to handle the connections later.
There are various ways to do this, but once you do, you'll have a reasonably robust server. Here are some things to consider:
- How long should you wait before closing a connection?
- When should you close connections?
- How can you manage the set of file descriptors on which you want to select?
You can conceivably play with this for a long time -- play and experiment until you're happy that your server is behaving well and that you understand why.
If you finished all that and still have time
You are a master of the course! Congratulations.
Here's a fun little test: see if you can tweak your clients and servers
to copy files! That is, rather than specifying a protocol on the
serviceclient.c
command line, assume that the argument is a file name.
The client should send the file name to the server and then send the
contents of the file to the server; the server will write the data to a
file of the same name (be sure to run these in different directories).
Wrapping Up
No post-class survey for today! Instead, we'll have a short presentation at the end of class.