Stream Upgrades, Part 3

Today's the final part of the series on the stream upgrade model (StreamUpgradeBindingElement and StreamUpgradeProvider were covered previously). I've got a sample of a stream upgrade to show next week but I figured that everyone would like a little break from the topic before jumping into that. The rest of this week has topics about transport security.

When we left off with the StreamUpgradeProvider, there were two methods on that class for creating an initiator and an acceptor. The initiator and acceptor are paired components for negotiating the upgrade and transforming the data stream. Let's start by looking at the initiator.

 public abstract class StreamUpgradeInitiator
{
   protected StreamUpgradeInitiator();

   public abstract IAsyncResult BeginInitiateUpgrade(Stream stream, AsyncCallback callback, object state);
   public abstract Stream EndInitiateUpgrade(IAsyncResult result);
   public abstract string GetNextUpgrade();
   public abstract Stream InitiateUpgrade(Stream stream);
}

Every time GetNextUpgrade is called, it returns an opaque string that specifies an upgrade type that this initiator supports. The upgrade types will be tried successively until the initiator indicates that it has no more types to attempt by returning null. The upgrade type string typically looks something like a MIME type and most initiators will only have one type to try. The SSL stream security and Windows stream security upgrades use application/ssl-tls and application/negotiate, respectively. After an upgrade is accepted, InitiateUpgrade is used in either its synchronous or asynchronous form to actually transform the data stream.

The acceptor side looks virtually the same as the initiator side.

 public abstract class StreamUpgradeAcceptor
{
   protected StreamUpgradeAcceptor();

   public virtual Stream AcceptUpgrade(Stream stream);
   public abstract IAsyncResult BeginAcceptUpgrade(Stream stream, AsyncCallback callback, object state);
   public abstract bool CanUpgrade(string contentType);
   public abstract Stream EndAcceptUpgrade(IAsyncResult result);
}

Each time the initiator proposes an upgrade type, CanUpgrade on the acceptor is called with that type string. The acceptor then says yes or no to performing the upgrade. AcceptUpgrade is the exact equivalent to InitiateUpgrade for transforming the data stream.

The stream upgrade model has been stable over the last few months. The most significant change was to add the Via parameter so that the provider can make upgrade decisions based on both the next and final hops.

Next time: Diffie-Hellman Key Exchange