Extracting files from an MSI package

Reminder to self, as I have searched for this too many times:

How to extract files from an MSI file without actually installing it:

msiexec /a c:downloadsWCFRestStarterKit.msi /qb TARGETDIR=c:RESTStarterKit

Run this from an elevated command prompt. The target directory does not have to be created beforehand.

Posted in Uncategorized | Leave a comment

Testing from Word

Message request = Message.CreateMessage(MessageVersion.None, “Status”);

SampleProfileUdpBinding binding = new SampleProfileUdpBinding();

binding.ReliableSessionEnabled = false;

 

Posted in Uncategorized | Leave a comment

WCF Extensibility part 5: Make your endpoints behave

In the previous post we looked at an operation behavior that applied the operation formatter to a particular operation description. Because this is default behavior for all operations in the interface defined, we will make life a little easier on us to have the operation behaviors applied automatically. A WCF endpoint consists of address, binding and contract. The latter is represented by the [ServiceContract] annotated interface, in our case IRcon and the target of our exercise.

image

The extensibility point that the WCF runtime provides is an endpoint behavior. Endpoint behaviors allow you to manipulate an endpoint’s definition. To create an endpoint behavior you need to implement the System.ServiceModel.Description.IEndpointBehavior interface:

public interface IEndpointBehavior
{
    void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters);
    void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime);
    void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher);
    void Validate(ServiceEndpoint endpoint);
}

This should look pretty familiar to you if you have read the previous part in this series. Again, you can apply your behavior both on the client and service side. There’s another validation moment in the Validate method and you can add binding parameters to the binding context for later use.

The implementation of ApplyClientBehavior is the most interesting one. Here we will apply the operation behavior to each of the endpoint’s operations.

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
    if (endpoint.Binding is SourceRconTcpBinding)
    {
        foreach (OperationDescription description in endpoint.Contract.Operations)
        {
            ApplyFormatterBehavior(description, endpoint);
        }
    }
}

private void ApplyFormatterBehavior(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
    if (operationDescription.Behaviors.Find<SourceRconOperationFormatterBehavior>() == null)
    {
        SourceRconOperationFormatterBehavior formatterBehavior = new SourceRconOperationFormatterBehavior();
        operationDescription.Behaviors.Add(formatterBehavior);
    }
}

Inside the implementation a simple loop over the operation descriptions in the contract is enough to get things going. The helper method ApplyFormatterBehavior makes sure that the SourceRconOperationFormatterBehavior behavior is applied only once.

An endpoint behavior needs to be added to the Behaviors collection of an endpoint to make it do its work. Given the client-side interface definition IRconProxy (which derives from both IRcon and IClientChannel) you can create a channel factory. The factory holds the the definition of the endpoint, provided by the implicit ABC in line 1 (address and binding are obvious, the generic <T> of the ChannelFactory represents the contract).

ChannelFactory<IRconProxy> factory = new ChannelFactory<IRconProxy>(binding, new EndpointAddress(uri));
factory.Endpoint.Behaviors.Add(new SourceRconEndpointBehavior());
factory.Open();

Line 2 adds the behavior to the Behaviors collection of the endpoint. When the factory opens, the behavior gets applied. The operation formatters get applied at that moment as well. The operation formatters are used when the actual calls through the channel are made.

Side note: if you were to use a ClientBase<T> derived proxy, you would need to drill down into the proxy.ChannelFactory.Endpoint.Behaviors to get at the Behaviors collection, or use the proxy.Endpoint property for easier access.

To summarize, an endpoint behavior allows you to manipulate your endpoint. Behaviors are an opt-in, so it is your choice whether to apply them or not.

Posted in Uncategorized | Leave a comment

WCF Extensibility part 4: Applying formatting to operations

In the previous part we inspected the way you can influence the transition from a service operation to a WCF Message object. This was accomplished with an implementation of the IClientMessageFormatter interface, in our case the SourceRconOperationFormatter class. Now it’s time to look at how to apply this message formatter to the client channel stack.

image

The message formatting happens based on the formatter that is specified as part of the description of an operation. This means that in theory you could change the formatter from operation to operation. In order to get the formatter in place you need to change the Formatter property of the System.ServiceModel.Description.OperationDescription for the operation of your choice. Obviously this has to be done before the first method call is made. The extensibility point that allows you define which formatters are used for client and service operations is an operation behavior. When applied an operation behavior will influence the way an operation behaves when called. Hence the name.

Operation behaviors must implement the System.ServiceModel.Decription.IOperationBehavior interface. First of all look at that interface definition:

public interface IOperationBehavior
{
    void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters);
    void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation);
    void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation);
    void Validate(OperationDescription operationDescription);
}

As you can see it has two methods to apply the specifics of your behavior to an operation description: one for client-side and one for service-side operations. We need to fill in the client-side proxy part of it only. Furthermore, the behavior can validate the operation to which it is applied. More on this in a moment. And finally, should the behavior need to add specific parameters to the entire binding (which can be accessed later on from the binding context) it is free to do so in the AddBindingParameters method.

The SourceRconOperationFormatterBehavior class explicitly implements the IOperationBehavior interface. There is no point to have public method as it is unlikely that the implementation will be called other than via the interface.

public class SourceRconOperationFormatterBehavior: IOperationBehavior
{
    #region IOperationBehavior Members

    void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    {
        // Nothing for us to do
    }

    void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    {
        // Apply our own formatter
        clientOperation.Formatter = new SourceRconOperationFormatter(operationDescription);

        // This behavior takes care of both request and replies at client
        clientOperation.SerializeRequest = true;
        clientOperation.DeserializeReply = true;
    }

    void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
    {
        // Client-side only
        throw new NotImplementedException();
    }

    void IOperationBehavior.Validate(OperationDescription operationDescription)
    {
        // Always valid?
        // In our case we cannot have ref or out parameters
        // We could check that parameters are primitive types
    }

    #endregion
}

The ApplyClientBehavior method set the Formatter property of the client operation to which the behavior is applied. It also expresses that the client operation will serialize and deserialize both request and reply messages.

Inside the Validate method we could check whether the operation is compatible with the behavior. For example, we should check that there are no ref or out parameters. We could check that the parameters are either representable as a string, and whether the return value is either of type string (the reply messages always contain string data) or that it is deserializable from a string. I have not been able to get the validate method to be triggered and all implementations of IOperationBehavior inside the framework have an empty method body. With Reflector you can see that the client validations on behaviors should go off when the ChannelFactory is opening. I’m not sure why it does not fire.

You can go the extra mile and have your behavior derive from Attribute:

[AttributeUsage(AttributeTargets.Method)]
public sealed class SourceRconOperationFormatterBehaviorAttribute : Attribute, IOperationBehavior

so it can be used as an attribute above a method:

[ServiceContract]
public interface IRcon
{
    [OperationContract(Action = "status")]
    [SourceRconOperationFormatterBehavior]
    string GetStatus();

You would probably want to change the name of the behavior/attribute class to something like SourceRconOperationAttribute so it looks like [SourceRconOperation]. This makes more sense. In our case the behavior is not really optional as we need to apply the operation formatter for every operation in a service contract to make things work. Having an interface that is only partially usable for remote control seems weird.

Having made the remarks above on how behaviors are non-optional, the next topic will be about a streamlined way to accomplish that all operations in a service contract will have the operation formatter behavior applied.

Posted in Uncategorized | Leave a comment

WCF Extensibility part 3: Formatting operations

Time to get serious and drill down into the first area of the big picture. We are going to take a look at “operation formatting”, which is roughly located in the highlighted area.

image

One of the crucial parts of the WCF channel layer is the way that method invocations get transformed into WCF messages. This capability allows the end-programmer to work with the object-oriented paradigm. This means you call methods on proxy objects, instead of having to fiddle with the messages going back and forth between a client and service yourself.

Let’s say we have a proxy that was created like so:

 

[ServiceContract]
public interface IRcon
{
    [OperationContract(Action = "kick")]
    string Kick(string steamID);
}

public interface IRconProxy : IRcon, IClientChannel { }

class Program
{
    static void Main(string[] args)
    {
        SourceRconTcpBinding binding = new SourceRconTcpBinding("abc123");
        string uri = "raw.tcp://192.168.100.101:27015";
        IRconProxy proxy = null;
        ChannelFactory<IRconProxy> factory = new ChannelFactory<IRconProxy>(binding, new EndpointAddress(uri));
        factory.Endpoint.Behaviors.Add(new SourceRconEndpointBehavior());
        factory.Open();

        proxy = factory.CreateChannel();

        string reply = proxy.Kick("1:0:1337");

 

Take a look at the last line. There you can see a method call being made on the proxy that was created with a call to ChannelFactory<IRconProxy>.CreateChannel. We want to influence the way this method call gets transformed into a specialized System.ServiceModel.Messaging.Message class, called SourceRconMessage. The regular transformation would change a method call into normal Message objects. Our message object holds the spcifics for the Source rcon protocol. Here is the shape of the class, corresponding to the elements of the rcon protocol:

public class SourceRconMessage : Message
{
    public int RequestID { get { ... } }
    public ServerData ServerData { ... } }
    public string String1 { get { ... } }
    public string String2 { get { ... } }
}

We will get back to the specifics of the message in a later post.

The process of changing a method invocation to a message and vice versa is called operation formatting. The key interfaces for all classes that performs this task are System.ServiceModel.Dispatcher.IClientMessageFormatter and IDispatchMessageFormatter. They are essentially the same but mirrored, because they represent the formatting that will happen at the client and service respectively.

public interface IClientMessageFormatter
{
	object DeserializeReply(Message message, object[] parameters);
	Message SerializeRequest(MessageVersion messageVersion, object[] parameters);
}

 

We will only look at the client message formatter, since we are building a client-side only implementation of the channel stack. The service’s side would have DeserializeRequest and SerializeReply, mirroring the direction requests and replies are sent and received.

Let’s look at each of the implementations of the two methods of the IClientMessageFormatter interface:

// Changes a list of parameters and operation description into a SourceRconMessage
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
    SourceRconMessage message = new SourceRconMessage(operationDescription.Messages[0].Action, parameters);
    message.Headers.MessageId = new UniqueId(message.RequestID.ToString());

    return message;
}

No rocket science here. The process of changing the action and parameters of the method call into a message is performed by a custom-built constructor on the SourceRconMessage class. The one thing to remember for later though is the mysterious property of MessageId in the Headers of the message that we set. This will be revisited at a later stage.

 

// Goes from SourceRconMessage to return value and parameter list
public object DeserializeReply(Message rawMessage, object[] parameters)
{
    // Deserialize message and return value
    object returnValue = null;
    SourceRconMessage message = (SourceRconMessage)rawMessage;

    // TODO: Use returnParameter.ParameterType to get the type of return parameter
	// and deserialize to that type from string
    returnValue = message.String1;

    return returnValue;
}

 

The DeserializeReply method will get a deserialized reply message that was handed from the channel stack. This should be a SourceRconMessage object (which we should probably check for to be sure it really is). Right now we only extract the single valuable piece of information from the message: the String1 property. It is passed back as the return value, which will work as long as the return value is of type string. Notice how there is no type information available for the return value and parameters.

The two methods above go into the SourceRconOperationFormatter class.

 

public class SourceRconOperationFormatter: IClientMessageFormatter
{
    // Goes from SteamRconMessage to return value and parameter list
    public object DeserializeReply(Message rawMessage, object[] parameters) { ... }

    // Changes a list of parameters and operation description into a SteamRconMessage
    public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) { ... }
}

 

The class can contain much more. A later and improved version will have a special constructor to hold the operation description details to be able to have type information on the parameters and return value for the sake of DeserializeReply.

Posted in Uncategorized | Leave a comment

WCF Extensibility part 2: The big picture

Before I drill down into each of the smaller parts of the client-side channel stack implementation, I want to sketch out an overview of some of the moving parts of the channel layer. This picture is by no means complete, and I will probably revisit it several times over the next couple of posts. It should however provide you with a better understanding of what we are trying to accomplish in what part of the channel layer. And remember, this picture is a sketch and may not be 100% exact or correct.

image

What you see in the picture is the client-side of the WCF channel layer. I am trying to convey here that from the method call to the actual transport several things happen along the way.

First of all, when you call a service (or something else at the other end of the transport) you make a method invocation on a proxy. This might be

  • a raw transparent proxy like we created in the first part of the series with a call to ChannelFactory<T>.CreateChannel.
  • a ClientBase derived proxy, like the one you get when you use Add Service Reference (ASR). This proxy uses the same transparent proxy on the inside.

This method call is translated to a message object representing the method call. This message is dropped into a stack of channels that will massage the message every which way. The different channels in the stack all have their specific purpose, such as security, reliable sessions, or transport. The last channel in the stack is always the transport channel. The final transport channel will encode the message using an encoder and will serialize the bytes across the transport, whatever that may be (HTTP, MSMQ, TCP, UDP, email, …).

For Request/Reply message exchange patterns there will come a stream of bytes in response. The stream will be decoded by the message encoder, which gives another message object. The same holds true for duplex messaging, but for duplex the incoming request stream might be initiated by the service, without a previous message from us, the client. We will not encounter duplex/callback messages. Finally, the response message will be turned into the completion of the method call by yielding the return value and ref or out parameters. The method call returns to the caller. You may have guessed that this is for synchronous method calls on the proxy and you are absolutely correct. For now, we will leave asynchronous operations out of scope.

For each of the following posts I will highlight the area that we focus upon. Any feedback is welcome.

Posted in Uncategorized | Leave a comment

WCF Extensibility part 1: background on game server protocols

Talking to game servers

There are various kinds of multiplayer games that allow you to battle against other gamers. I’ll focus on the First Person Shooters (FPS) and Real Time Strategy (RTS) games and skip the (Massive Multiplayer Online) Role Playing Games (MMORPG and RPG). Usually the FPS and RTS games will connect to a central server that is located on your LAN or out in the Internet. The game players will interact by means of the server using a special protocol. The administrators of the server are regular game players for most of the time, but have elevated privileges to control the game server. Typical things that an admin will do is change the currently played map, restart game rounds, and kick or ban misbehaving players from the server.

This type of control can be done “locally” when the admin is one of the players connected to the server, or remotely. The latter is called remote control and it uses a special protocol particular to the type of game engine. Luckily most of these protocols are reasonably well documented. There are not that many game engines out there and hence a small number of protocols. The most famous ones are:

  • Unreal (1, 2 and 3)
  • Quake (1, 2 and 3)
  • Half-Life (aka Goldsource, based on Quake engine)
  • Source
  • Doom 3

Right now, we’ll zoom in on the Source engine with its protocol for remote control of game servers based on this engine.

Issuing commands

If you have a Source-based game like Half-Life 2 or Team Fortress 2 it is pretty easy to use control from the game interface. You can simply connect to the server to control by joining a multiplayer game. Once on the server you can access a console window to send commands. A comprehensive list of commands is available. Here are some examples of common commands:

rcon_password abc123

changelevel de_dust2
kick 1:0:12345
mp_restartround 1

The first command rcon_password is needed to prevent unwanted control of a game server.

You can even use remote control by specifying the server address and password first, so you do not have to connect to the game at all.

rcon_address 192.168.100.101:27015
rcon_password abc123

The game itself is needed to control the server, because the game knows the protocol specific to the engine. But other than that it is inconvenient that you would need to own and start the game just to control the server. There are a fair number of code implementations out there that capture the protocol and allow a programmer to use the API to control a server remotely. I wrote several myself, which is a nice programming exercise with an interesting theme of gaming. Well, at least it beats the common customer/order/product samples.

Understanding the protocol

The Source engine is created and maintained by Valve and their developer wiki holds a pretty good explanation of the Source remote control (rcon) protocol.

Here’s my take on the protocol:

Source uses a TCP connection from the client to the game server. After connecting the client should perform an authentication handshake. If the authentication was successful, you can start issuing commands. The protocol uses multiple message exchanges between client and server to accomplish both. Every message has the same structure:

  • packet size (int): entire message excluding packet size integer. It must be at least 10.
  • request id (int): random number used for correlating responses to requests
  • server data (int): depending on purpose of message the server data has one of the following values
    • SERVERDATA_AUTH = 3: initial authentication handshake message
    • SERVERDATA_EXECCOMMAND = 2: command message
    • SERVERDATA_RESPONSE_VALUE = 0: response from command message
    • SERVERDATA_AUTH_RESPONSE = 2: acknowledgement of authentication message
  • string1 (null-terminated string): either command to run, password or result
  • string2 (null-terminated string): reserverd, must be empty string (“”);
  • A typical rcon session will look like this:

    image

    Let’s take a look at some of the individual packets. Let’s assume that the password is “abc123” and that the command that was issued is “changelevel de_dust2”

      Authentication Junk Acknowledgment Exec command command reply
    packet size 4 + 4 + 7 + 1 == 16 4 + 4 + 1 + 1 == 10 4 + 4 + 1 + 1 == 10 4 + 4 + 21 + 1 == 30 4 + 4 + (string1.length + 1) + 1 == 10
    request id 0x2e0e0000 0x2e0e0000 0x2e0e0000 0xd2010000 0xd2010000
    server data 3 0 2 2 0
    string 1 “abc123” “” “” “changelevel de_dust2” “” (command specific,
    varies depending of success or failure of method)
    string 2 “” “” “” “” “”

    After the exec command and corresponding reply packets you can continue issuing exec commands.

    de_train1aThe sequence of message above is the ideal picture. In reality things might be a little more difficult, because:

    1. a reply may consist of multiple reply packets.
    2. authentication might not be successful because of a wrong password.

    Eventually we will take everything into account, but for now we will pretend that multi-packet responses do not exist and that authentication is always successful.

    If that works, the exchange of raw bytes across the network should look something like this (for the 5 messages listed above):

    0000   10 00 00 00 2e 0e 00 00 03 00 00 00 61 62 63 31  ............abc1
    0010   32 33 00 00                                      23..
    
    0000   0a 00 00 00 2e 0e 00 00 00 00 00 00 00 00        ..............
    
    0000   0a 00 00 00 2e 0e 00 00 02 00 00 00 00 00        ..............
    
    0000   1e 00 00 00 d2 01 00 00 02 00 00 00 63 68 61 6e  ............chan
    0010   67 65 6c 65 76 65 6c 20 64 65 5f 64 75 73 74 32  gelevel de_dust2
    0020   00 00                                            ..
    
    0000   0a 00 00 00 d2 01 00 00 00 00 00 00 00 00        ..............
    

    Next steps

    Our task at hand is to learn WCF to speak this protocol, while maintaining the channel layer concepts.

    Posted in Uncategorized | Leave a comment

    Windows Communication Foundation extensibility to the max

    Last week I visited Microsoft at the Redmond campus and spent the larger part of the week with the Windows Communication Foundation and Workflow Foundation team. I spoke with a lot of the team members and managed to get good insights into the things to come in WCF/WF 4.0.

    I got a chance to talk to Nicolas Allen and Kenny Wolf. Besides the work-related issues that I wanted to investigate I also discussed my long-running attempt to create a very odd WCF client implementation. They gave me a couple of hints on how to take the last hurdles to get everything working. While still shrugging off the last bits of jetlag I managed to get the first implementation up and running. Although WCF was never designed with such weird things in mind, this proves that WCF is extensible beyond your imagination. I’ll walk you through it all.

    Part 1: Background on game server protocols
    Part 2: The big picture
    Part 3: Formatting operations
    Part 4: Applying formatting to operations
    Part 5: Make your endpoints behave

    But, just as a teaser preview, here are some code snippets of what this will all amount to:

    [ServiceContract]
    public interface IRcon
    {
    	[OperationContract(Action = "status")]
    	string GetStatus();
    	[OperationContract(Action = "changelevel")]
    	string ChangeLevel(string mapName);
    	[OperationContract(Action = "mp_restartround")]
    	void Restart(int seconds);
    }
    
    public interface IRconProxy : IRcon, IClientChannel { } 
    
    class Program
    {
    	static void Main(string[] args)
    	{
    		SourceRconTcpBinding binding = new SourceRconTcpBinding("abc123");
    		string uri = "raw.tcp://192.168.100.101:27015";
    		IRconProxy proxy = null;
    
    		try
    		{
    			ChannelFactory<IRconProxy> factory = new ChannelFactory<IRconProxy>(binding, new EndpointAddress(uri));
    			factory.Endpoint.Behaviors.Add(new SourceRconEndpointBehavior());
    			factory.Open();
    
    			proxy = factory.CreateChannel();
    			proxy.Open(TimeSpan.FromSeconds(10));
    
    			string reply = proxy.GetStatus();
    			proxy.Restart(3);
    		}
    		catch (Exception ex)
    		{
    			Console.WriteLine(ex);
    		}
    		finally
    		{
    			proxy.Close();
    		}
    	}
    }
    

    Here, the most interesting lines of code are 31 and 32: a WCF client channel talking a proprietary, non-SOAP protocol over a TCP connection.

    Posted in Uncategorized | Leave a comment

    StackOverflow DevDays 2009

    Most of you must know the community site StackOverflow.com. But did you know that StackOverflow is also organizing the StackOverflow DevDays? “A full day of inspiration and learning for developers brought to you by the team behind StackOverflow.com and FogBugz”. The day will feature speakers like Joel Spolsky, Jeff Atwood, Scott Hanselman, Jon Skeet and many others. The DevDays tours several cities in the United States, but they are also coming to Europe! Two editions of the DevDays will take place in England (London and Cambridge) and the last one is in Amsterdam, The Netherlands. Not all speakers will make an appearance everywhere, so make sure you book the right edition to meet your favorite speaker.

    image

    Some details are on the Amsterdam edition still have to be determined, such as venue. I will be presenting a code-only (or very low PowerPoint) presentation on ASP.NET MVC. This presentation will be in English and I guess the others are in English as well given the expected international audience.

    As soon as more details are available, I will update them here. I do know that you will have to hurry, as the seats are running out. Almost every edition in the United States is sold out. In Europe, London is sold out, while Cambridge has 45 and Amsterdam 35 seats left as the time of this blogpost.

    Go book your seat now!

    Posted in Uncategorized | Leave a comment

    Catching the .NET Service Bus part 1: Exposing a service on the bus

    The last couple of evenings I spent some time getting familiar with the .NET Services and the Service Bus in particular. Here is a story of how I got my sample service to be available on the .NET Service Bus.

    I assume that you are familiar with the .NET Service Bus already; otherwise you can read some good articles on MSDN (documentation and two articles) and Clemens Vasters’ blog.

    My goals were easy: what does it take to get a pretty standard WCF service up and running using the .NET Service Bus. For completeness sake, this is the service contract (sticking with my ever lasting theme of gaming):

    namespace GamingServiceLibrary
    {
    	[ServiceContract]
    	public interface IGameServerManagement
    	{
    		[OperationContract]
    		GameServerStatus RetrieveServerStatus(IPAddress address, int port);
    	}
    }

    I wanted to have the request/reply styled service implementation available with message security enabled. Like myself you will need a .NET Services account to be able to use the .NET Services (Service Bus and Access Control service) and have a so-called solution (mine is named “KillerApps”). You will find that solution names must be globally unique, so don’t be late and find out your intended name is already taken!

    Hosting and exposing your service

    First of all you need to have the service host register your service endpoint on the service bus. A lot of the plumbing is taking care of by the NetTcpRelayBinding, which does all the negotiation with the bus. All we have to do is choose an endpoint on the service bus and authenticate ourselves to the bus. For simplicity I chose the following name “GameServerService” as the significant part of the endpoint address.

    To create the complete endpoint address you can use a helper method:

    Uri address = ServiceBusEnvironment.CreateServiceUri("sb", solutionName, "GameServerService");

     

    which will generate an URI like so sb://KillerApps.servicebus.windows.net/GameServerService. The italic/bolded parts are the pieces that get filled in for you. The scheme corresponds to the type of relay binding. For TCP it will be sb, for basic, WS, federation and web HTTP bindings it will be http or https.

    The service host needs some preparations that can be done through code or config. I did parts in both.

    string solutionName = "KillerApps";
    string solutionPassword = "test1234"; // Nope, not my real password and you should replace it with your own
    
    // Create the credentials object for the endpoint.
    TransportClientEndpointBehavior userNamePasswordServiceBusCredential = new TransportClientEndpointBehavior();
    userNamePasswordServiceBusCredential.CredentialType = TransportClientCredentialType.UserNamePassword;
    userNamePasswordServiceBusCredential.Credentials.UserName.UserName = solutionName;
    userNamePasswordServiceBusCredential.Credentials.UserName.Password = solutionPassword;
    
    // Create the service host reading the configuration.
    ServiceHost host = new ServiceHost(typeof(GameServerService), address);
    
    // Create the ServiceRegistrySettings behavior for the endpoint.
    IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);
    
    // Add the Service Bus credentials to all endpoints specified in configuration.
    foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
    {
      endpoint.Behaviors.Add(userNamePasswordServiceBusCredential);
      endpoint.Behaviors.Add(serviceRegistrySettings);
    }
    
    // Open the service.
    host.Open();

    The approach above is from the Getting Started sample in the .NET Services SDK for July 2009. Nothing fancy, just with some fixes:

    • The sample duplicates the line for setting the username instead of one for the password.
    • Also, the sample uses the old URIs for the service bus endpoints. You can now use the helper method).

    A quick disclaimer: do not store your password in your code or config like this. Keep it safe and encrypted.

    A service that wants to expose an endpoint on the Service Bus always need to authenticate, so not any odd service can claim an endpoint with your solution name in it. Likewise, the client needs to authenticate, so the service bus can check whether it is allowed to access a particular service endpoint. The endpoint behavior for password based authentication is prepared and added to all endpoints. The behavior takes care of passing a username (always the name of the solution) and password to the bus.

    There are other authentication types, such as CardSpace and certificates. The place to configure each of these authentication types is in another part of the .NET Services: the Access Control Service. That’s a topic for another post, but when you are looking for some guidance on the combination of CardSpace and the bus I can recommend the Hands-on Lab “.NET Services: Introduction to the Access Control Service” from the Geneva Training Kit. The host of your service chooses the authentication type it wants to use and the Access Control Service will perform the authentication.

    Also, the service will be added to the registry discoverable for everyone through the ServiceRegistrySetting endpoint behavior.

    The other part needed for successful hosting resides in the config file. The service’s configuration holds two endpoint definitions:

     

    <services>
      <service behaviorConfiguration="GamingServiceBehavior" name="GamingServiceLibrary.GameServerService">
                <endpoint binding="netTcpRelayBinding" bindingConfiguration="default" contract="GamingServiceLibrary.IGameServerManagement">
                    <identity>
                        <dns value="netbook01"/>
                    </identity>
                </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://netbook01:8732/Design_Time_
    Addresses/GamingServiceLibrary/GameServerService" /> </baseAddresses> </host> </service> </services>

     

    Looking at this config section you can see two endpoints: one for the actual service contract implementation and one for metadata exchange. The base address in the host element does not really matter for the first endpoint, because we are providing the sb:// specific adress in the code. Also, both the binding and the service have configurations that are being referred to.

    The binding has this configuration:

    <bindings>
        <netTcpRelayBinding>
            <binding name="default" connectionMode="Relayed">
                <security mode="Message">
                    <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security>
            </binding>
        </netTcpRelayBinding>
    </bindings>

    It specifies the connection mode of the service to the service bus and the client later on. Relayed means a client will be relayed through the service bus. Direct and Hybrid are the other options. The former allows a direct connection between client and service after service bus negotiation (which might not turn out to be possible). The latter is a mode where direct is attempted with a fallback to Relayed when direct connections fail.

    The <security> element configures the security of the messages. This is completely orthogonal to the way authentication has occurred. Security is optional to protect the communication between client and service, whereas authentication does not protect but is mandatory for exposing a service on the bus.

    Summary

    Hosting and exposing your service on the .NET Service Bus requires you to use one of the special Relay binding that are new in the Microsoft.ServiceBus assembly. Upon connection, the binding will negotiate the details of the endpoint with the host. In the process the binding will attempt to authenticate the host to the bus.

    Next time we will take a look at how to enable message security and I will also explain the security configuration, the endpoint behavior and <identity> element that is skipped over for now.

    Posted in Uncategorized | Leave a comment