Monday, January 11, 2010

.NET Framework is a surprise box!!!

Most of the time when I need to get inspiration about how to do something, I turn to the inner bits and bolts of .NET Framework, because I think that there are a few hundred men-years worth of code there, and it does have some insights.

But, some times...

I was just looking into the Dictionary<TKey, TValue> class when I came across this little bit of code:

public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
  if (info == null)
  {
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info);
  }
  // ...
}


Ok, we don't have much here, and inside the .NET Framework there are lots and lots of helper classes to aggregate common functions and adhere to the D.R.Y. principle.

However, when I dove into the ThrowArgumentNullException method, this is what I've found:

internal static void ThrowArgumentNullException(ExceptionArgument argument)
{
  throw new ArgumentNullException(GetArgumentName(argument));
}
The ExceptionArgument type is actually an enumeration, that lists the possible values for the method argument. Well, I thought that perhaps there were more than meets the eye here, but when I went through the GetArgumentName function... take a look:

internal static string GetArgumentName(ExceptionArgument argument)
{
  switch (argument)
  {
   case ExceptionArgument.obj:
        return "obj";

   case ExceptionArgument.dictionary:
        return "dictionary";

   case ExceptionArgument.dictionaryCreationThreshold:
        return "dictionaryCreationThreshold";

   case ExceptionArgument.array:
        return "array";

   case ExceptionArgument.info:
        return "info";

   case ExceptionArgument.key:
        return "key";

   case ExceptionArgument.collection:
        return "collection";

   case ExceptionArgument.list:
        return "list";

   case ExceptionArgument.match:
        return "match";

   case ExceptionArgument.converter:
        return "converter";

   case ExceptionArgument.queue:
        return "queue";

   case ExceptionArgument.stack:
        return "stack";

   case ExceptionArgument.capacity:
        return "capacity";

   case ExceptionArgument.index:
        return "index";

   case ExceptionArgument.startIndex:
         return "startIndex";

   case ExceptionArgument.value:
        return "value";

   case ExceptionArgument.count:
        return "count";

   case ExceptionArgument.arrayIndex:
        return "arrayIndex";

   case ExceptionArgument.name:
        return "name";

   case ExceptionArgument.mode:
        return "mode";
  }
  return string.Empty;
}


Ok, now you're thinking that the above function could be easily rewritten as:

internal static string GetArgumentName(ExceptionArgument argument)
{
  return argument.ToString();
}


And perhaps the whole shebang of going through three different method calls could be avoided by simply writting:

public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
  if (info == null)
  {
     throw new ArgumentNullException("info");
  }
  // ...
}


Right?!

Well that's what I thought... Until I read the source code.

Thanks to Microsoft the source code for the .NET Framework is public, so as I always like to learn, I've downloaded the full source and installed.

When I read the source for the ThrowHelper class, I've come across the following explanation:
The old way to throw an exception generates quite a lot IL code and assembly code.

Following is an example:

C# source
throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
IL code:

IL_0003: ldstr "key"
IL_0008: ldstr "ArgumentNull_Key"
IL_000d: call string System.Environment::GetResourceString(string)
IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string)
IL_0017: throw


Which is 21bytes in IL.

So we want to get rid of the ldstr and call to Environment.GetResource in IL.

In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the argument name and resource name in a small integer. The source code will be changed to
ThrowHelper.ThrowArgumentNullException (ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);

The IL code will be 7 bytes.

IL_0008: ldc.i4.4
IL_0009: ldc.i4.4
IL_000a: call void System.ThrowHelper:: ThrowArgumentNullException (valuetype System.ExceptionArgument)
IL_000f: ldarg.0


This will also reduce the Jitted code size a lot.


After reading this I started having a little bit more respect for the guys that write this stuff.

Sunday, January 10, 2010

IIS7 Virtual FTP Servers problems and solutions

I know, I know, it's old news. After all IIS7 came out with Vista a couple years back, and with it came the possibility of having multiple virtual FTP servers in the same IIS.

But until now I had no idea of this, because, in all honesty, I skipped Windows Vista altogether. I didn't installed it in my box. Went straight from XP to Windows 7.

As I have some time in my hands, and after a complete reformat of my HD, I made a list of things that needed to be done. One of them is to rewrite the application that I use to update this site.

Part of this site is updated by using Blogger.com, but another part is by a program I made myself. This program was written almost five years ago, so a LOT of things have evolved since then.

I'm currently upgrading it to Visual Studio 2010 Beta2, along with a complete, no old code, rewrite of my ancient FTP Library.

I'm not going into details of this new library (which I will post as it's ready), but during my basic tests I wasn't able to connect to my own local server, because I have set it up as a virtual FTP server, complete, with host name (that I updated the Windows\system32\drivers\etc\hosts file to emulate a live FQDN server) and login users and permissions.

When I tried to connect, I got a &dlquo;530-Valid hostname is expected&drquo; error.

What the heck?!

Because I had never played with the new IIS7 before, I thought it would handle the host name binding behind the scenes (as I have set up just a single FTP server) as the IIS does normally for the HTTP protocol.

And hence the problem. The the FTP protocol, although extensible, does not provide means to infer directly the host name for an specific connection.

For example: let's say we create two virtual FTP servers one for the FQDN ftp.example.com and another for ftp.contoso.com.

Both these virtual servers points to the same IP. And each of these virtual servers points to different location in the same server (it could even be in another server, but let's keep it simple for argument's sake).

Now, let's say that the users allowed to access ftp.example.com DO NOT have access to ftp.contoso.com.

When an FTP client connects to a full qualified domain name (like ftp.example.com) it actually makes a connection to the IP that is represented by that name (your basic DNS service) and, usually, on port 21.

After a connection is established, the FTP server sends a simple reply &dlquo;220 Connection OK&drquo;.

At this point the FTP server have NO IDEA of what FQDN the client requested. There's no way to tell. It can't even make a DNS reverse lookup, because the all the server knows at this point is that a client is connected to an specific listening port, bound to an specific address (or not so specific -- as you can set the binding to listen on all server's address).

So there are two approaches:
  1. The FTP client sends a &dlquo;HOST&drquo; command to specify which virtual host it's addressing; Or
  2. it issues a &dlquo;USER virtual.host|userName&drquo; command Older FTP clients are not prepared for this kind of situation.


And not all the newer ones are ready for this.

As an workaround Robert McMurray proposed back in '08 to use a *dlquo;Global Listener FTP Site&drquo; which it's nothing more than an unbidden FTP site that routes users to the appropriated paths.

However this approach isn't a solution as it doesn't resolve the problem of a single user that have access to more than one FTP virtual server.

So, to wrap it up, the &dlquo;virtual.host|userName&drquo; approach to connect to an FTP virtual server, is the best fall back solution for older FTP clients that are not aware of the new HOST command, and gives their users a possible mean of connection.