Pants First, Then Shoes: More Argument for Pre-Commit Code Review

In my opinion, at least for The MarkUs Project, post-commit code review would probably be analogous to putting on your shoes before your pants.  And though I mentioned earlier that there is plenty of preference for post-commit, I forgot to include this juicy little tidbit.

Click here to read one of the developers of ReviewBoard state his case for pre-commit code review.

To each their own.  But I dig his points.

Screencasting Code Reviews is Hard

I’ve been trying to record myself performing code reviews for The MarkUs Project.

It’s a lot harder than I thought it’d be.  The screencasts are really only useful if I’m saying what I’m thinking, and I’m finding it difficult to maintain stream of consciousness and perform an effective/thorough review.  The last few times I’ve tried it, I find myself blurting an expletive, stopping the recording in frustration, and then starting the review over so that I can do a good, proper job.

I think this is going to take more practice.

The Importance of First Impressions: How Theatre Criticism Might Inform Peer Code Review

Discussion Plays

I have seen plays that have very clear stories, and very clear plots.  I leave the theatre knowing what has happened, and I can be pretty confident that the people who sat around me in the theatre all got the same message as I did.

I have also seen plays that are completely the opposite.  There doesn’t appear to be a story.  There doesn’t appear to be plot.  There are no real characters.  For these plays, all of a sudden, I have to do the work in order to make sense of it all.  And you can be pretty sure that every single audience member got something different out of it.

I want to talk about this second kind of play.  For now, I’m going to call this kind of play a discussion play, because for me, the best part about these kinds of plays is the discussion I have with my friends afterwards. We’ll all sit down in a restaurant or a cafe, order some food, and try to figure out what the hell we just saw.  Theories are tossed around.  Everybody brings their own unique impressions and observations to the table.  A very rich ecosystem of ideas develops.

Back to Peer Code Reviews

(trust me, this all ties together in the end)

When Jason Cohen did his Peer Review at Cisco Study, he noticed that code that had been prepared by the author for review seemed to have a lower defect density than code that had not been prepared.

What do I mean by prepared?  I’ll let Jason Cohen explain:

The idea of “author preparation” is that authors should annotate their source code before the review begins.  Annotations guide the reviewer through the changes, showing which files to look at first and defending the reason and methods behind each code modification.  The theory is that because the author has to re-think all the changes during the annotation process, the author will himself uncover most of the defects before the review even begins, thus making the review itself more efficient.  Reviewers will uncover problems the author truly would not have thought of otherwise.

(Best Kept Secrets of Peer Code Review, p80-81)

Looking at the data, author preparation does seem to have a palpable effect.  As Cohen notes, “for all reviews with at least one author preparation comment, defects density is never over 30; in fact the most common case is for there to be no defects at all!”.

The study has two explanations for this:

  1. Authors gave their code such a thorough look while annotating them, that most defects were eliminated right off the bat.
  2. Since authors were actively explaining, or defending their code, this sabotaged the reviewers ability to do their job effectively.

Cohen buys into the first explanation.  He writes:

A survey of the reviews in question show the author is being conscientious, careful, and helpful, and not misleading the reviewer.  Often the reviewer will respond to or ask a question or open a conversation on another line of code, demonstrating that he was not dulled by the author’s annotations.

I have huge respect for this study.  But I don’t entirely buy this explanation.  As Cohen later mentioned in an email to me, this conclusion is not derived from a controlled experiment, and also suffers from selection bias.

Back to those Discussion Plays

One of the worst things that can happen to me before going into a discussion play is for someone who has already seen it to tell me their impressions of what they thought was going on.  As soon as I hear their opinion, my own objectivity is compromised.  Whether I want to or not, I’ll have their impressions in the back of my mind, and I’ll be using it as a measuring stick or reference point for my own opinions and critiques. They’ve carved a cognitive path through the work, and I’m doomed to notice that path, and react to it.

This is horrible.  This limits me.  This more or less hobbles my ability to contribute something unique to the pool of ideas and criticisms in the after-play discussion.  Every impression I have is tainted by someone else’s first impression.

Don’t get me wrong – I love hearing about everyone’s impressions.  But after I have formed my own. This way, I believe we cover more ground.  A group of us watching a discussion play will carve unique cognitive paths through the work without influencing one another.  When we finally open up and present these paths and ideas to one another over food and drink, I believe we cover more ground.

I have no data to back this up.  Only years of theatre-going experience.

A Code Review Anecdote

I recently received an email from a colleague of mine.  She wanted me to go over some of her Javascript to make sure it was up to snuff, since she was relatively new to the language.  I noticed that she had also sent a copy of the email to another developer who has pretty sharp Javascript chops.

When I finally had some free time, I went back to her email to write up the review.  I felt bad – it was late, and the other reviewer hadn’t made a peep on the email thread, and she was hoping to use the code relatively soon.  So I dove in, wrote my review, and sent it off.

A little while later, the other developer sent me his review, saying:

And here was my answer, which I didn’t send to you so as not to influence your reply.  ;)

So the author of the code received two unique reviews, and neither of them had influenced the other.  When I read his review, I noticed that we covered some similar ground, but a lot of unique ground as well.  I suspect this wouldn’t have been the case had he sent his review to me first.

The Hypothesis

I hypothesize that author preparation in code review sabotages reviewers abilities to objectively carve their own unique cognitive paths through the code.  They see things from the author’s point of view, and this dulls their critical eye.  Because of this, I believe fewer defects are detected.

I will take this hypothesis one step further.

I suspect any review, by the author or otherwise, will taint future reviews.  If someone has already reviewed some code, I suspect this review will impact and possibly limit the ability of other reviewers to look at the code objectively.  Like author preparation, I suspect this prevents reviewers from getting their own unique, valuable first impressions of the code.  And I suspect that this causes some defects to go undetected.

Testing This Hypothesis

It’s a simple idea really.  Take a chunk of code, and get some number of developers to review it.  Take this same code, add some author preparation comments, and get more developers to review it.  Do all of the normal balancing, etc.

The question:  do the number of detected defects drop?  If so, this looks like evidence that author preparation sabotages review ability.

Take the experiment one step further.  Take some code, have someone else review it, and then have participants review this code, having seen the first review.  What happens to the number and type of defects that they find?  What happens if they don’t see that initial review?  What yields high defect detection?

Sounds doable.  Sounds interesting.  Sounds like something that would answer a few questions.

Implications and Ideas

So what if one or both of my hypotheses are true?  What does this mean for peer code review?

Well, if author preparation alone sabotages review ability, then the answer is simple:  don’t let the authors prepare the review.  The code goes up, and they stay silent.

But what if both are true?

An idea:  how about I tweak MarkUs’s ReviewBoard so that reviewers cannot see what other reviewers have said until they’ve given one review?  What would happen to the defect detection numbers?  Would reviewers react negatively to this?  Would there be lots of repetition in the comments?  Sounds like something worth looking into.

I’d love to hear some thoughts on this.  Anyone?

A Code Review for the iPhone DOOM Port (and some other FPS’s)

I just found this on Slashdot – a guy named Fabien Sanglard reviews the code for the iPhone DOOM port.  This is cool – I wish I had time to read it thoroughly.  It’ll have to wait until after my assignments are done.

Looks like this guy has a thing for FPS’s – he’s also done a code review for “Wolfiphone” (Wolfenstein for iPhone) and the original Quake.

I like this idea.  Why aren’t there more of these on the web?  Or am I not looking hard enough?

How to Report the News

Pre-Commit Code Review in MarkUs Development

So, for my Master’s thesis, I’ve pretty much set my heart on code review as my research area.  Here’s why:  it works.  It makes your code better.  It helps you find bugs.  And I’m not just quoting something overheard in a pub – there’s evidence to back these claims up.

And then there’s my own experience to boot – the MarkUs team has been using ReviewBoard as our pre-commit code review tool since last summer, and I wouldn’t ever go back.  If I ever have to work in a shop that doesn’t perform code reviews, I’ll campaign my butt off.

Having said all that, pre-commit reviews certainly aren’t for everyone.  Some downsides of pre-commit over post-commit:

  • It goes against “check in early, check in often
  • “The major downside of pre-checkin code review is that it puts a major bottle neck on getting changes into the system for other developers to integrate with early enough.” (from this link)
  • For some applications, testing takes hours on end.  Why wait?  Might as well toss it into the repo, let the Continuous Integration build it, and just see what happens.

There are probably more.

My response:  at least for MarkUs, pre-commit code reviews are working just fine, thank you very much.  At least we’re reviewing it – and any review is better than no review.  But to continue my response, here are a couple of advantages of pre-commit code review for the MarkUs development team:

  1. Since most students working on MarkUs are doing it for half-credits, this means there’s a lot of turnover every semester.  ReviewBoard lowers the chance of our new hotshot developers  accidentally slipping something ridiculous into the repository and having to do that neat Subversion trick of pulling it out again.  This is the obvious one.
  2. It helps all developers keep track of what everyone else is doing.  This is true for post-commit reviews too, but it’s certainly worth the mention.  It sure beats reading SVN log messages…
  3. It’s a great arena for new developers to ask questions.  Our new developers this semester have been very active on our ReviewBoard, asking plenty of questions about things that are showing up in the diffs under review.  Sometimes, “theoretical” code is posted to demonstrate how something would be done.  Post-commit does not support this nicely.
  4. It’s an excellent way of showing how you’re coming along with a task, without the embarrassment of breaking the build.  MarkUs developers sometimes post up “sneak previews” just to give everybody a taste of how their particular task is coming.  This “sneak preview” gives the opportunity for other developers to critique the direction that the submitter is going in, and offer pointers in case they seem to be heading off in a hazardous direction.

Yep, there’s just something so satisfying about seeing all of those little green “ship-it’s”, and then firing off your code into the repository… it’s positive reinforcement for code reviews.  And it’s strangely addictive to me.

Another Idea to Augment This Process

A little while ago, I wrote about what I consider to be one of the Achilles’ Heels of Peer Code Review.  Here’s another one: at least for ReviewBoard, during a review all you’re looking at is the code.  That’s all fine and dandy if you want to look at the logic of the code…but what if you want to try it?  Does trying it out help find more bugs than just looking at it?

Well, at least for MarkUs, it’s helped.  I’ve recently started checking out a fresh copy of MarkUs every time a review request is put up, and splat a copy of the diff under review on top.  I run the test suites, and if they pass, I drive it around.  I try out the new features that the diff supposedly adds, or try to recreate the bug that the diff supposedly fixes.

And I’ve caught a few bugs this way.  This is because ReviewBoard is good at showing me what is in the code, but is bad at telling me what is not there.  And that’s perfectly understandable – it’s not psychic.

So here’s an idea – how about writing a little script that checks ReviewBoard for new review requests.  When it finds one, it checks out a brand new copy of MarkUs, splats down the diff under review over top, runs the tests, and then posts back as a ReviewBoard reviewer how many tests passed, how many failed, etc. If we wanted to get fancy, the script could even do some commenting on the code – maybe using Roodi, Flog, Flay, or some of those other sadistically named Ruby tools to say things about the diff.  The script would be another reviewer.

And then the kicker – the script posts a link in its review where developers can try out a running instance of MarkUs with the applied diff.

Want a fancy name to kick around the office?  Call it pre-commit continuous integration. I just checked – it’s not a common term, but I’m not the first to use it.  Again, so much for being cutting edge.

Would this be useful?  It’s possible that the Roodi/Flog/Flay stuff would bring too much noise to the review process – that’s something to toy with later.  But what about the link to the running instance?  Will that little feature help catch more bugs in MarkUs?  How about for Basie?

I’m curious to find out.

Unfortunately, ReviewBoard doesn’t let me download diffs through its API just yet…if schoolwork lets up for a few days, I’ll look into changing that.

I’d love to hear your thoughts.

MarkUs, Squad, How’s / Refactor My Code, Belated Happy Holidays, and Oh Yeah – I’m Not Dead

Belated happy holidays! My last post was over a month ago, and so my blog has a nice layer of web-dust on it right now.  Well, here I am to ease your mind.  I’m still alive!

But that almost wasn’t true.

I won’t bore you with the details – I’ll just give you the facts, and let you fill in the blanks.

  1. My girlfriend Em, her sister Cassie, and myself, were up in Collingwood on New Years Day, enjoying a relaxing day at a Norwegian spa (the outdoor baths were amazing – how awesome is it to be in a boiling hot tub, while simultaneously, your hair is so frozen that it’s snapping off in your hands?)
  2. The roads that night were treacherous.  Snowy, un-plowed, and dark.  I had borrowed my Mom’s car for the trip, and we took it realllllly slow.
  3. After a tortoise-paced two hour ride back to Em’s place in Newmarket, and then another two hour drive from Newmarket to my home in Grimsby the next day, I was getting pretty sick of winter driving.  On top of that, the brakes seemed to be acting funny.  I found myself sliding a lot, and there didn’t seem to be a lot of resistance when I put my foot down.
  4. The next day, my Mom takes the car to go to work.  She doesn’t even leave the drive-way.  The brakes hadn’t been acting funny:  the brakes hadn’t been acting at all.  Turns out we had a leaky brake-line for the entire trip…
  5. Guts of the story:  I think we drove home from Collingwood with about 35% brake power in one of the worst snow storms I’ve ever driven in.

Breakfast tasted especially good for us that morning.

Anyhow, now where was I?  Oh yeah…

MarkUs

MarkUs 0.6 got kicked out a week or so ago.  The MarkUs Team kicked the crap out of a bunch of tickets over the holidays, and I think we ended up with a pretty solid release.  MarkUs is being used again at UofT this semester, and Byron Weber Becker is also piloting it at UWaterloo.  I’ll cautiously say that things seem to be going well for this release.  Great job, MarkUs Team!

I’m TAing the students working on MarkUs for Greg’s UCOSP course again.  We had a fantastic code-sprint this past weekend!  The new team members have already started working on tickets and submitting code to review.  I think we’re on our way into another highly productive semester.

A Few More Web-Based Code Review Tools

Remember that big list of code review tools I put up a while back?  I’ve got a few more to add:

How’s My Code

This is a pretty dead-simple code review tool that came about during a Rails Rumble a few months back.  It has that “big friendly buttons and round corners” web 2.0 thingy going on.  I haven’t gone so far as to actually try it out, but I did watch this web-cast:

Not bad if you just want to get your code out there, and get your team commenting on your changes…

A few things caught my attention:

  • It’s a web service, so you don’t install it…you sign up for it
  • It currently only supports Git.  :(
  • There doesn’t seem to be any support for contextual per-line commenting…I think it’s just file by file commenting.  I’d love it if I could comment on a single line of code…

Still, if I was working on a project hosted on a Git repo, and I needed a dead-simple code review service, and I needed it quickly, I could probably do a lot worse than this.

Click here to check out How’s My Code

Squad

Remember that time when I wrote about how it might be neat if somebody created a code review tool on top of Google Wave? (or Bespin for that matter – though I didn’t mention it, and should have)

Looks like somebody else was thinking the same thing. And a few months earlier.  I guess it’s not easy to be super cutting-edge.

Anyhow, looks like something Wave-ish (yet simpler, more streamlined) has been developed.  Check out Squad.

I just tried this thing out for free (with ads, features locked, etc), and it was pretty cool.  I could see something like this being very useful for showing new MarkUs team members how to do things.  Actually, I just used it to show a new member of the MarkUs team how to use Shoulda.  Pretty useful.  It sure beats coding through IRC and Pastie.org.

A few things to keep in mind:

  1. Super simple to get going – open up a session, and send someone a generated link, and you’re both coding in no time
  2. One person codes at a time…so while one person edits, the screen is locked for everyone else
  3. Ads on the left are a little annoying
  4. Sports syntax highlighting for a number of languages – though I noticed that Ruby wasn’t one of them.  :/

I can see this becoming second nature, like Pastie.org.

Who knows – I might find more reasons to use Squad as the semester rolls, and MarkUs picks up speed.  I’ll keep you posted.

If you missed the link I put in above, click here to check out Squad

Refactor My Code

This service crowd-sources code review requests, so don’t expect to get deep architectural feedback, because it’ll probably come from strangers who don’t/barely know your code base.

The idea is – slap a piece of code that you’d like refactored up on the site, and then others swoop in with brilliant suggestions (assuming of course, you asked your question properly…check this out…what the…?)

This is the sort of thing that CS instructors probably wouldn’t want their students using too much…it’d then become solve-my-CS-programming-assignment.com.

Still, I think it counts as peer code review.  And it’s way different that anything else I’ve been looking at.  Nice.

Click here to check out Refactor My Code

Anyhow, I just thought I’d mention those.

Fiddling Around with Skype

As I said last week, I’ve been working with a partner (Mohammad Jalali) on a project for our networks course.

The idea:  given an arbitrary IP and port number, we want to find a way of determining whether or not there is an FTP server, an HTTP server, or a Skype node on the other side.  FTP and HTTP are trivial – those protocols essentially announce themselves to the world.

Skype clients, on the other hand, act a little more strangely.  Skype goes out of its way to hide its traffic – from straight-up encryption, down to making their client executable really hard to reverse engineer.  Because of this, Skype has been an interesting challenge to the hacker community.

Anyhow, my partner and I have learned a few interesting things about Skype – and in particular, we’ve found a reliable way to determine whether or not Skype is running behind an arbitrary IP and port.  Cool.

Fact 1:  Skype pretends to be an HTTP server

I’m serious, it does.  Using Wireshark, we noticed that both UDP and TCP packets were being sent to one particular port.  Pretty funny behavior…so, we took a closer look.  And this is what we found.  Pop open your Skype client, connect to the network, then use nmap to find the ports that Skype is using:


$>nmap localhost -p10000-50000

Starting Nmap 5.00 ( http://nmap.org ) at 2009-12-01 20:33 EST
Interesting ports on localhost (127.0.0.1):
Not shown: 39999 closed ports
PORT      STATE SERVICE
48915/tcp open  unknown

Ok, cool – there’s something at 48915, and it looks like it accepts TCP connections.  Pop open Telnet, connect to it, and feed it an HTTP request:


$>telnet localhost 48915
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.0 404 Not Found
Connection closed by foreign host.

Ok, we got an HTTP response – looks like there’s an HTTP server back there, right?

Wrong.  Reconnect, and send it some garbage:


$>telnet localhost 48915
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
thisissomegarbagetextthatisnotanHTTPrequest
��Nun��2�=���1��N$O/(����
���u.)(yy�g��$
ș�oT�b렑�-z#x�&���[P���\��(yVO���

See all of those funny characters down at the bottom?  That’s what I got back.  In the words of Obi-Wan Kenobi…that’s no HTTP server…it’s a space station (Skype node).

So we’ve learned something here – Skype opens a port, and “spoofs” an HTTP server.  We can easily check for this – just write a script that connects to a port, spews some garbage, and check to see if we got binary garbage back.

It’s so easy, that someone else has already done it.  Remember that nmap tool we used earlier?  Somebody over in that camp wrote a script for the Nmap Scripting Engine that runs this exact analysis on some ip/port.  Don’t believe me?  Read the script yourself! We stumbled upon that script while trying to figure out what Skype was doing with the spoofed HTTP server.
And sure enough:

$>nmap localhost -p48915 --script skype.nse
Starting Nmap 5.00 ( http://nmap.org ) at 2009-12-01 20:45 EST
Interesting ports on localhost (127.0.0.1):
PORT      STATE SERVICE
48915/tcp open  skype2

Nmap done: 1 IP address (1 host up) scanned in 0.14 seconds

Hmph.  So much for cutting edge, never-been-done research.  Go figure.

Fact 2:  Given some UDP packets, Skype echos back a predictable pattern

For this part, we’re pretty sure no one else has tried this.

While connected to Skype, we recorded some packets with tcpdump.  We wrote a script that loaded up those packets, and could “replay” the packet payloads to an arbitrary IP and port.

So, we played some packets against an IP/port with Skype behind it.  Most of the time, we got TCP packets with RST flags (which is TCP’s way of telling us to “shut yer trap”).  But wayyyy down in the middle, there was a section of UDP packets that actually got a response:

From Misc Blog Images

192.168.0.19 was the computer we were playing the packets from, and 192.168.0.14 was the computer with Skype running on it. See those UDP packets that are getting echoed back?  That’s the interesting part…instead of just shutting us down with RST’s, Skype appears to be saying something back.

So, is there a pattern in all of this?  Actually yes.  We isolated 4 of those UDP packets, and repeatedly fired them at the same IP/Port on the computer running Skype, and we found a pattern.

The pattern:  the first two bytes that are sent in our UDP packets are echo’d back to us in the first two bytes of the UDP packets that come back.

So, for example,  one UDP payload we sent looked like this:

92 40 02 a1 66 65 ea 0d 8c 82 c3 0c 27 cd c5 e7
4e 78 fe a1 50 a6

And we got back:

92 40 17 c0 a8 00 13 74 a0 41 f0

See that common 92 40?  Bingo.  ;)

And it’s pretty consistent – if we repeat the same UDP packet, we get (almost) the same response.


92 40 67 c0 a8 00 13 11 00 10 4f

And if we repeat again…


92 40 37 c0 a8 00 13 68 08 43 3a

92, 40, and c0, a8, 00, 13. Nice!  Looks like a fingerprint to me!

Except…

Except, remember, we already found a way of determining whether or not Skype was running behind a given IP/port.  This last finding was just bonus.  My partner and I aren’t sure if our instructor is going to let us stay with this topic, seeing as how it’s pretty much been solved by other people before.  We’ve only got 2 weeks before this project is due, so…if we get another project, let’s hope it’s relatively simple.  Push come to shove, we could always try to fingerprint a different protocol…maybe BitTorrent clients.

Either way, working on this stuff has been pretty cool…and it let me try out some pretty neat tools that are usually reserved for the people with coloured hats (and no, I didn’t mean Red Hat):

  • nmap: port scanner that can also do service/os fingerprinting
  • Scapy: sculpt, gut, spoof, manipulate, and send packets – the power of C, with the simplicity of Python!  We used Scapy as a library while writing our scripts.  Lots of potential with this tool.  Feel like poisoning an ARP cache?  Scapy is for you!
  • Wireshark: a network student’s best friend.

Click here to check out Mohammad’s blog post about this project.

Can Google Wave Bring Something New to Peer Code Review?

If you haven’t already heard about Google Wave, watch this video.

In a nutshell, Google Wave is an attempt at integrating wikis, instant messaging, email and social networking, into a nice, tight, Google-y ball of goodness.

What’s particularly interesting, is that developers can write “gadgets” by coding against the Google Wave API.  Check this out – a collaborative tool for systems modeling built into the Google Wave client.  That’s pretty cool!

Which makes me wonder… could a code review tool be built on top of Google Wave?  And if so, what services, if any, does the Wave protocol offer that might make such an application superior to other web-based code review tools?

What does Google Wave offer that would make such a code review tool special, more effective, and better?

Playing Around with FTP

I’m taking a Computer Networks course this semester, and for my final project, my partner and I are trying to create signatures for FTP, HTTP, and Skype packets.

The big idea:  we want to create some signatures, and then “replay” those signatures against some arbitrary IP and port.  If we get a response, we analyze the response to see if it matches what we expect from the signature.  If it matches, chances are we’ve determined what kind of server is behind that IP/Port.

FTP and HTTP are the trivial ones.  Skype is going to be quite a bit harder.

Anyhow, here is what I’ve found out about FTP…

FTP

FTP runs over a TCP connection, so if you’ve got Telnet, then you’ve got a basic FTP client.  Traditionally, FTP servers run on port 21 – but really you could put one on whichever port you feel like.

So, I’m going to try to futz around with the Mozilla public FTP server, and show you what I get.

First, I’ll connect to the FTP server with Telnet, like so:


mike@faceplant-linux:~$ telnet ftp.mozilla.org 21

Here’s what comes back:


Trying 63.245.208.138...
Connected to dm-ftp01.mozilla.org.
Escape character is '^]'.
220-
220-   ftp.mozilla.org / archive.mozilla.org - files are in /pub/mozilla.org
220-
220-   Notice: This server is the only place to obtain nightly builds and needs to
220-   remain available to developers and testers. High bandwidth servers that
220-   contain the public release files are available at ftp://releases.mozilla.org/
220-   If you need to link to a public release, please link to the release server,
220-   not here. Thanks!
220-
220-   Attempts to download high traffic release files from this server will get a
220-   "550 Permission denied." response.
220

If I type in anything and press RETURN, the server responds with:
530 Please login with USER and PASS.
Since I don’t have an account, I’ll just use the basic anonymous one:

USER anonymous

The server responds back with:

331 Please specify the password.

I don’t have a password, so I’ll just try a blank one…

PASS

and blam, I get a ton of stuff back:

230-
230-   ftp.mozilla.org / archive.mozilla.org - files are in /pub/mozilla.org
230-
230-   Notice: This server is the only place to obtain nightly builds and needs to
230-   remain available to developers and testers. High bandwidth servers that
230-   contain the public release files are available at ftp://releases.mozilla.org/
230-   If you need to link to a public release, please link to the release server,
230-   not here. Thanks!
230-
230-   Attempts to download high traffic release files from this server will get a
230-   "550 Permission denied." response.
230 Login successful.

Hey alright, I’m in!  Er…where exactly am I, though?  I type in PWD, and the server responds with “/”.  So I’m in the root.  Nice.

So what’s in the root directory, anyhow?  I type in LIST.  Here’s what I get back:

425 Use PORT or PASV first.

And here’s where it gets interesting.  This Telnet session I’ve got here is like a control window.  But if I want any actual data from the server, I’m going to need to either open up one of my ports (and do some port-forwarding on my router) to receive it (PORT), or connect to another port that the FTP server can pipe data through (with PASV).

I’d rather not go through all of the trouble of port-forwarding, so I’m going to choose the latter.  I type in PASV.  The server responds with:

227 Entering Passive Mode (63,245,208,138,225,55)

So what does that big string of numbers mean?  The first 4 are the IP address I’m to connect to (63.245.208.138).  The last two tell me what PORT to connect to.  The formula to determine the port number is N1*256 + N2.  N1, in this case, is 225.  N2 is 55.  So 225*256 + 55 is 57655.

So I open another Telnet in a separate window, connect to 63.245.208.138 on port 57655, and get….

nothing.

Yep, just a blank.  I’ve made the connection, but I haven’t asked for any data, so there’s nothing for the connection to say.

However, if I type LIST again in the command window, I get

150 Here comes the directory listing.
226 Directory send OK.

sent into the control window, and

-rw-r--r--    1 ftp      ftp           528 Nov 01  2007 README
-rw-r--r--    1 ftp      ftp           560 Sep 28  2007 index.html
drwxr-xr-x   34 ftp      ftp          4096 Nov 24 23:32 pub
Connection closed by foreign host.

pumped into my data window.  Notice that the connection closed in the data window.  That means that, for every bit of data I want, I either need to redo the whole PASV thing, or supply a PORT that the server can connect to.  Bleh.

Let’s see what else I can do.  I type in “CWD pub” to change to the pub directory.  Using PASV and LIST, I get the following from another data window:

drwxrwxr-x    3 ftp      ftp          4096 Jun 05  2002 OJI
-rw-rw-r--    1 ftp      ftp          1144 Jul 03  2001 README
drwxr-xr-x 5561 ftp      ftp        430080 Nov 24 22:14 addons
drwxr-xr-x    2 ftp      ftp          4096 Jul 05  2005 artwork
drwxr-xr-x    2 ftp      ftp          4096 Jun 13  2008 bouncer
drwxrwxr-x    5 ftp      ftp          4096 Apr 20  2009 calendar
drwxrwxr-x    6 ftp      ftp          4096 Aug 11  2008 camino
drwxr-xr-x   16 ftp      ftp          4096 Oct 16  2006 cck
drwxrwxr-x    3 ftp      ftp          4096 Jul 10  2004 chimera
drwxrwxr-x   12 ftp      ftp          4096 Aug 31  2001 data
drwxrwxr-x    8 ftp      ftp          4096 Jun 19  2007 directory
drwxr-xr-x    4 ftp      ftp          4096 May 17  2005 diskimages
drwxrwxr-x    4 ftp      ftp          4096 Jul 26  2008 extensions
drwxrwxr-x    4 ftp      ftp          4096 May 16  2003 firebird
drwxrwxr-x    5 ftp      ftp          4096 Aug 12  2008 firefox
drwxrwxr-x    3 ftp      ftp          4096 Aug 07  1999 grendel
drwxrwxr-x    5 ftp      ftp          4096 Mar 22  2009 js
drwxrwxr-x    4 ftp      ftp          4096 Oct 22  2004 l10n-kits
drwxrwxr-x    2 ftp      ftp          4096 Nov 24 20:28 labs
-rw-r--r--    1 ftp      ftp       1868178 Sep 17  2003 ls-lR
-rw-rw-r--    1 ftp      ftp        169159 Sep 17  2003 ls-lR.gz
drwxr-sr-x    4 ftp      ftp          4096 Sep 15  2005 minimo
drwxrwsr-x   12 ftp      ftp          4096 Nov 11 06:09 mobile
drwxrwxr-x   15 ftp      ftp          4096 Jan 04  2008 mozilla
lrwxrwxrwx    1 ftp      ftp             1 Sep 15  2006 mozilla.org -> .
drwxrwxr-x    2 ftp      ftp          4096 Aug 25  1998 msgsdk
drwxrwxr-x    5 ftp      ftp          4096 Jul 09  2002 nspr
drwxrwxr-x    4 ftp      ftp          4096 Sep 23  2002 phoenix
drwxrwxr-x    3 ftp      ftp          4096 Aug 03  2000 profiles
drwxrwxr-x    6 ftp      ftp          4096 Aug 12  2008 seamonkey
drwxrwxr-x    5 ftp      ftp          4096 May 04  2006 security
drwxr-xr-x    5 ftp      ftp          4096 Aug 13  2008 static-analysis
drwxrwxr-x    8 ftp      ftp          4096 Sep 24 19:03 thunderbird
drwxrwsr-x    4 ftp      ftp         20480 Nov 19 02:26 webtools
drwxrwxr-x    6 ftp      ftp          4096 Aug 11  2008 xulrunner
drwxr-xr-x    2 ftp      ftp          4096 Sep 12 05:51 zz
Connection closed by foreign host.

Nice.  Alright, now let’s see if I can download one of those files.  I’m going to try to download README.  Using PASV, I create a new data window, and then I type:

RETR README

And, after a little wait, my data window gets:

Welcome to ftp.mozilla.org!
This is the main distribution point of software and developer tools
related to the Mozilla project.  For more information, see our home
page (http://www.mozilla.org/) Go here to download Netscape Communicator:

http://home.netscape.com/download/
A list of ftp.mozilla.org's mirror sites can be found at:
http://www.mozilla.org/mirrors.html
This site contains source code that is subject to the U.S. Export
Administration Regulations and other U.S. law, and may not be exported
or re-exported to certain countries (currently Afghanistan (Taliban
controlled areas), Cuba, Iran, Iraq, Libya, North Korea, Sudan and
Syria) or to persons or entities prohibited from receiving U.S.
exports (including Denied Parties, entities on the Bureau of Export
Administration Entity List, and Specially Designated Nationals).
If you plan to mirror our site read our crypto FAQ. Send mail to
mirrors@mozilla.org to be added to our mirrors list.
http://www.mozilla.org/crypto-faq.html#2-1
We do not guarantee that any source code or executable code
available from the mozilla.org domain is Year 2000 compliant.
Connection closed by foreign host.

Awesome! I think I have enough information to come up with some kind of signature.

Resources

What, you think I figured all this stuff out alone?  No way – I had some help: