XAML Playground
about XAML and other Amenities

Consume a Socket using Reactive Extension

2011-06-29T09:43:23+01:00 by Andrea Boschin

In my last post I wrote about writing a TCP server using the Reactive Extensions library. It was not a Silverlight related post, but it simply introduces the server side component that I will use in this post to show you how to use the same library to consume the incoming data and present it in Silverlight. The interesting part is to understand how rx can simplify the programming model when dealing with asynchronicity both in Silverlight and in server side full .NET programming.

The server I presented was a very simple socket listener that waits for connections and then, when the channel has been established, it push to the client a continuous stream of data that represent the current state of the CPU and memory of the server. With this huge amount of informations incoming we can create a little application that is able to show a chart and some gauges, updated almost in realtime.

The application, developed following the MVVM pattern, is made of a simple view containing the controls used to present the informations. These controls are feeded by a couple of properties in the ViewModel that are updated with the incoming data. So the most of the work is done by the ViewModel that is responsible of connecting to the socket and read the information stream to update the properties. In a real world solution probably you will have some kind of layer between the ViewModel and the socket, but for the sake of the post we will keep it simple as much as we need to understand how it works.

Consuming a socket in Silverlight means using an instance of the Socket class that represents the connection and a SocketAsyncEventArgs that is used when you call the methods of the connection to make the requests and receive responses. So, as an example, when you have to establish the connection you have to create the instance of the Socket class and the call the ConnectAsync method providing the SocketAsyncEventArgs initialized with the address of the endpoint to connect to. When the connection has been established the SocketAsyncEventArgs class will raise a Completed event that notify about the result of the operation. Doing it with Reactive Extensions mean something like this:

   1: protected void Connect()
   2: {
   3:     this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
   4:  
   5:     SocketAsyncEventArgs arguments = new SocketAsyncEventArgs();
   6:     arguments.RemoteEndPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, 4530);
   7:  
   8:     var socketAsObservable = from args in Observable.FromEvent<SocketAsyncEventArgs>(
   9:                                  ev => arguments.Completed += ev,
  10:                                  ev => arguments.Completed -= ev)
  11:                              select args.EventArgs;
  12:  
  13:     socketAsObservable
  14:         .Where(args => args.LastOperation == SocketAsyncOperation.Connect)
  15:         .Subscribe(
  16:         args =>
  17:         {
  18:             args.Dispose();
  19:             this.Receive();
  20:         });
  21:  
  22:     this.Socket.ConnectAsync(arguments);
  23: }

In the line #3 it is created the Socket with the common parameter that is used in Silverlight for a TCP channel. Then an instance of the SocketAsyncEventArgs is initialized and its property RemoteEndPoint is provided with and instance of DnsEndPoint that represente the address of the server to connect to. The port is 4530 like we defined in the previour article.

At this point it is created a stream, called socketAsObservable, from the Completed event of the SocketAsyncEventArgs. the stream filter the LastOperation to be "Connect", as we expect and in the Subscribe method disposes the SocketAsyncEventArgs instance and starts to receive data. The SocketAsyncEventArgs instance can be used only once so we have to carefully dispose it to avoid memory leaks.

Once the connection has successfully established you have to put your socket in Receive. When incoming data is detected you will be notified and you can fetch it from the SocketAsyncEventArgs and put again the socket in Receive. Here is how it appear with Reactive Extensions:

   1: protected void Receive()
   2: {
   3:     SocketAsyncEventArgs arguments = new SocketAsyncEventArgs();
   4:     arguments.SetBuffer(new byte[1024], 0, 1024);
   5:  
   6:     var socketAsObservable = from args in Observable.FromEvent<SocketAsyncEventArgs>(
   7:                                  ev => arguments.Completed += ev,
   8:                                  ev => arguments.Completed -= ev)
   9:                              select args.EventArgs;
  10:  
  11:     socketAsObservable
  12:         .Where(args => args.LastOperation == SocketAsyncOperation.Receive)
  13:         .Throttle(TimeSpan.FromMilliseconds(500))
  14:         .ObserveOnDispatcher()
  15:         .Subscribe(OnReceive);
  16:  
  17:     if (this.Socket.Connected)
  18:         this.Socket.ReceiveAsync(arguments);
  19: }

Once again we create the instance of the SocketAsyncEventArgs. It is now initialized with a SetBuffer that allocates a buffer of 1 KByte that is used by the socket to compy the incoming data. Then the socketAsObservable is created using the FromEvent; This method is important because it is in charge of attaching and detaching the Completed event so we avoid to have unwanted delegates around. Again the socketAsObservable is filtered selecting only when LastOperation equals to Receive and we also apply a Throttling of about 500 milliseconds. It is made to discart updated when they are too fast. One update every half a second suffice to say that the UI is up to date with the server.

Fially we marshal the stream to the UI Thread using the ObserveOnDispatcher and the received events are forwarded to the OnReceive method that is responsible of parsing the received data and updating the UI.

   1: protected void OnReceive(SocketAsyncEventArgs args)
   2: {
   3:     string data = Encoding.UTF8.GetString(args.Buffer, 0, args.BytesTransferred);
   4:  
   5:     IEnumerable<Sample> samples = this.GetSamples(ref data);
   6:  
   7:     Array.Clear(args.Buffer, 0, 1024);
   8:  
   9:     if (data.Length > 0)
  10:     {
  11:         byte[] bytes = Encoding.UTF8.GetBytes(data);
  12:         Array.Copy(bytes, args.Buffer, bytes.Length);
  13:         args.SetBuffer(bytes.Length, 1024 - bytes.Length);
  14:     }
  15:     else
  16:         args.SetBuffer(0, 1024);
  17:  
  18:     if (this.Socket.Connected)
  19:         this.Socket.ReceiveAsync(args);
  20:  
  21:     this.Update(samples);
  22: }

The method peek up the received data and then calls again the ReceiveAsync method of the connection to make again the channel ready to receive other informations. Then the Update method is called to update the properties binded to the view.

The code is simple and obviously it need some additional check, as an example it needs to verify the communication errors that here are swallowed. I hope it shows, once again, how reactive extension can help you to simplify the consumption of asynchronous streams.

A TCP Server with Reactive Extensions

2011-06-17T14:17:05+01:00 by codeblock

I know, from the title of this post you may understand that the topic I’m about to cover is not really Silverlight related. Please be patient and it will become clear that there is a relation with Silverlight in the next part when I will complete my exposition.

After a long pause, today I return to the Reactive Extensions, I’ve temporarily shelved for lack of time, and I want to present the implementation of a little server that uses a socket and takes advantage of the Extensions. A socket server usually listens to a TCP port and it can be easily consumed by a Silverlight application. This is not a usual scenario because often it is hard to get rid of firewalls and security people in a company, so the use of HTTP is way better in most of the cases. But, sometimes, tipically when you need a reactive communication that let the application to be always up to date with events on the server, the use of a Socket is an effective soluzione

For such people that are not aware of how a socket server works, a brief explanation. A regular socket server usually opens a port on the address it is binded. The port is represented by a number between 1024 and 65535 (numbers lower than 1024 are reserved) and it is expressed after the ip or dns name separated by a colon.

The server initially reserves the port and starts to listen for incoming connections. Until the arrive of a connection the server is substantially idle but when the connection is detected it has to "accept" the request and initialize the channel that will be used by both the parts to exchange the informations.

The acceptance phase of the server must handle the new connection like it is a completely new channel, so the problem is that the server will have a main channel where it accept connections and a number of channels, one for each client that has requested the connection. Usually this means that the server must spawn a new thread for each connection it accepts and the thread will separately handle its channel leaving the main thread free of returning to the listening phase.

Using Reactive Extension properly makes these operations very easy and the code required to handle the listening and acceptance is really compact. In my sample I use a Console Application that starts the listening ad finally remain available until someone hit enter and definitely closes the application. In the following box the main function:

   1: static CancellationTokenSource cts = new CancellationTokenSource();
   2:  
   3: /// <summary>
   4: /// Mains the specified args.
   5: /// </summary>
   6: /// <param name="args">The args.</param>
   7: static void Main(string[] args)
   8: {
   9:     if (IPAddress.Loopback != null)
  10:     {
  11:         TcpListener listener = new TcpListener(IPAddress.Loopback, 4530);
  12:         listener.Start();
  13:  
  14:         Console.WriteLine("Service is listening on {0} port {1}.", IPAddress.Loopback, 4530);
  15:         Console.WriteLine("Press enter to stop");
  16:  
  17:         Func<IObservable<TcpClient>> accept =
  18:             Observable.FromAsyncPattern<TcpClient>(listener.BeginAcceptTcpClient, listener.EndAcceptTcpClient);
  19:  
  20:         accept()
  21:             .Where(o => o.Connected)
  22:             .ObserveOn(Scheduler.NewThread)
  23:             .Subscribe(acceptedClient => OnAccept(acceptedClient, accept));
  24:  
  25:         Console.ReadLine();
  26:         cts.Cancel();
  27:     }
  28: }

In the first lines the server binds to the port 4530 of the localhost ip (127.0.0.1) and it starts to listen using the Start method. Then using the FromAsyncPattern method it is created an observable source that will notify once a new connection is detected. The observable will give the channel ready to communicate. So, the Subcribe method forward the channel to the OnAccept method that is responsible to feed the channel with informations retrieved by the computer (in this case if gives cpu usage and memory size in realtime). Obviously this is the operation we should spawn in a separate thread and the trick here is done by the ObserveOn(Scheduler.NewThread) that automatically initialize and start the thread using the body of the OnAccept method. Let me continue with the OnAccept method:

   1: static void OnAccept(TcpClient client, Func<IObservable<TcpClient>> accept)
   2: {
   3:     accept()
   4:         .Where(o => o.Connected)
   5:         .ObserveOn(Scheduler.NewThread)
   6:         .Subscribe(acceptedClient => OnAccept(acceptedClient, accept));
   7:  
   8:     Console.WriteLine("channel opened");
   9:  
  10:     while (!cts.Token.WaitHandle.WaitOne(100))
  11:     {
  12:         try
  13:         {
  14:             if (client.Connected)
  15:             {
  16:                 byte[] message = GetMessage();
  17:                 client.Client.Send(message);
  18:             }
  19:         }
  20:         catch (Exception ex)
  21:         {
  22:             Console.WriteLine(ex.Message);
  23:             break;
  24:         }
  25:     }
  26:  
  27:     Console.WriteLine("channel closed");
  28:     client.Close();
  29: }

As you can see the OnAccept method receives the connected TcpClient side by side with the instance of the observable and in the very first lines puts the main thread again on listen, just before starting its work. This operation closes the loop because the listener will continue to wait for new connections and the new thread will send the informations along the channel.

To gracefully handle the closure of the server, once you hit the enter key a CancellationTokenSource is used to forward to alle the threads the request of exit. The method GetMessage simply reads the informations of cpu and memory and translates them to a byte array that is sent on the channel.

   1: const ulong Mega = 1048576;
   2: static PerformanceCounter cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
   3:  
   4: static byte[] GetMessage()
   5: {
   6:     ulong totalPhisicalMemory = 0;
   7:     ulong availablePhisicalMemory = 0;
   8:     ulong totalVirtualMemory = 0;
   9:     ulong availableVirtualMemory = 0;
  10:     float cpu = cpuCounter.NextValue();
  11:  
  12:     NativeMethods.MEMORYSTATUSEX memStatus = new NativeMethods.MEMORYSTATUSEX();
  13:  
  14:     if (NativeMethods.GlobalMemoryStatusEx(memStatus))
  15:     {
  16:         totalPhisicalMemory = memStatus.ulTotalPhys / Mega;
  17:         availablePhisicalMemory = memStatus.ulAvailPhys / Mega;
  18:         totalVirtualMemory = memStatus.ulTotalVirtual / Mega;
  19:         availableVirtualMemory = memStatus.ulAvailVirtual / Mega;
  20:     }
  21:  
  22:     return Encoding.UTF8.GetBytes(
  23:         string.Format(
  24:             CultureInfo.InvariantCulture,
  25:             "{0:0.0}:{1}:{2}:{3}:{4}{5}",
  26:             cpu,
  27:             totalPhisicalMemory,
  28:             availablePhisicalMemory,
  29:             totalVirtualMemory,
  30:             availableVirtualMemory,
  31:             Environment.NewLine));
  32: }

To have a try with the server please runs the code and then open a command prompt and type the following

telnet 127.0.0.1 4530
 

You will see a continuous stream of informations displayed on the console and you can also try to run multiple command prompt with the same instruction and all the connections will be connected. This example shows the powerfulness of the reactive extensions. In the next post I will show you how to use the library to consume this socket.

Handling errors when calling network with Observable.FromEvent

2011-03-30T16:11:10+01:00 by Andrea Boschin

In my I've show a new way to write methods to call network resources like feeds, WCF methods and so on. I've proposed two solution that take advantage of Reactive Extension to call operations that follow the Begin-End pattern and also operation that use an event driven pattern. Today I would like to make another step forward to make the event driven side of the problem more reliable. Most of the times when you call the network you deal with this pattern instead of the Begin-End. Calling WCF and WebClient follow this pattern and we need to accurately handle the errors when we get the result from the calls.

The problem is that when you call a network resource this way you eventually get exceptions as a value of a property of the result instead of having them thrown as you may expect. This is obviously understandable due to the asynchronous nature of the calls. Also if the runtime will throw exceptions you would not be able to catch them because they are generated in another thread so the sole way to get them is that the runtime catch every exception and forward it using the Error property of the result. So here is how you commony handle the errors in network calls:

   1: public void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
   2: {
   3:     if (e.Error != null)
   4:     {
   5:         // there is an exception
   6:         MessageBox.Show(e.Error.Message);
   7:     }
   8:     else
   9:     {
  10:         // no error occured: do what you want with the result
  11:     }
  12: }

Using my Reactive Extensions way to the asynchronicity this issue may be a big problem because, since the Subscribe method is able to catch exceptions along the execution of the event, it does not understand about the Error resulting from an asynchronous network call. In my last example I showed this code:

   1: IObservable<SyndicationFeed> result = Observable.FromEvent<DownloadStringCompletedEventHandler, DownloadStringCompletedEventArgs>(
   2:     ev => new DownloadStringCompletedEventHandler(ev),
   3:     ev => client.DownloadStringCompleted += ev,
   4:     ev => client.DownloadStringCompleted -= ev)
   5:     .Select(o => o.EventArgs.Result)
   6:     .ConvertToFeed();

Unfortunately it works perfectly when the network call returns a valid response but it is unable to catch an exception if something goes wrong. To solve this problem I wrote an extension method that can collect possible exceptions and rethrow them. The trick is made using a base class named "AsyncCompletedEventArgs" that is used by every EventArgs returned by a network call. Having this common base class is key to write a single method to handle a lot of cases. Here is the code from the ThrowIfError() method:

   1: public static IObservable<IEvent<T>> ThrowIfError<T>(this IObservable<IEvent<T>> observable)
   2:     where T : AsyncCompletedEventArgs
   3: {
   4:     return observable.SelectMany(
   5:         o =>
   6:         {
   7:             if (o.EventArgs.Error != null)
   8:                 throw o.EventArgs.Error;
   9:  
  10:             return Observable.Return(o);
  11:         });
  12: }

The method is able to intercept and IObservable<IEvent<T>> that is the interface resulting from Observable.FromEvent() method. Once it receive the interface it examine the content and if it detects an error simple throw it. This make the runtime catch the exception and forward it to the OnError method of the Observer<T> that is the second parameter of a Subscribe method. If there is not any error the method simply returns the observable itself so the chain of method can be continued seamless. I use the SelectMany method to flatten the results from IObservable<IObservable<IEvent<T>>> (it's not a joke) to IObservable<IEvent<T>>. So now we can use the method everywhere we have to place a network call:

   1: public static IObservable<SyndicationFeed> DownloadFeedWebClient(Uri uri)
   2: {
   3:     WebClient client = new WebClient();
   4:  
   5:     IObservable<SyndicationFeed> result = Observable.FromEvent<DownloadStringCompletedEventHandler, DownloadStringCompletedEventArgs>(
   6:         ev => new DownloadStringCompletedEventHandler(ev),
   7:         ev => client.DownloadStringCompleted += ev,
   8:         ev => client.DownloadStringCompleted -= ev)
   9:         .ThrowIfError()
  10:         .Select(o => o.EventArgs.Result)
  11:         .ConvertToFeed();
  12:  
  13:     client.DownloadStringAsync(uri);
  14:  
  15:     return result;
  16: }

This does not change anything to the way you can call the DownloadFeedWebClient method because it returns always an IObservable<T> so you can simply Subscribe to it and specify and handler for the OnError part of the Observer<T>. To view an example please visit my .

Using a new pattern to call the network with Reactive Extensions

2011-03-30T01:17:20+01:00 by codeblock

Recently I’m trying the Reactive Extensions, an interesting set of extensions that aim to improve the handling of asynchronous programming with an innovative implementation of the observer pattern. These extensions provide some useful methods that solve in an elegant way some recurring problems that everyone have found for sure when calling the network. So, after lot of attempts I found a pattern I will start to use implementing the Data Access facade in my Silverlight applications.

Before discovering the Reactive Extensions (starting from here I will refer to them using the abbreviation RX), I was habit to use a widely adopted pattern that exposes two additional parameters to every method of the Data Access class. For instance, a method made to download a feed from the network may have the following signature and body:

   1: public static void DownloadFeed(Uri uri, Action<SyndicationFeed> success, Action<Exception> fail)
   2: {
   3:     try
   4:     {
   5:         HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
   6:  
   7:         request.BeginGetResponse(
   8:             asyncResult =>
   9:             {
  10:                 try
  11:                 {
  12:                     WebResponse response = request.EndGetResponse(asyncResult);
  13:  
  14:                     using (StreamReader sReader = new StreamReader(response.GetResponseStream()))
  15:                     {
  16:                         using (StringReader reader = new StringReader(sReader.ReadToEnd()))
  17:                         {
  18:                             using (XmlReader xReader = XmlReader.Create(reader))
  19:                             {
  20:                                 Deployment.Current.Dispatcher.BeginInvoke(
  21:                                     () => success(SyndicationFeed.Load(xReader)));
  22:                             }
  23:                         }
  24:                     }
  25:                 }
  26:                 catch (Exception ex)
  27:                 {
  28:                     fail(ex);
  29:                 }
  30:             }, null);
  31:     }
  32:     catch (Exception ex)
  33:     {
  34:         fail(ex);
  35:     }
  36: }

Using the HttpWebRequest made the code more complicated but the WebClient does not makes significant changes to the way the network call works. This pattern is interesting because using some lambda expression the resulting code remain compact. The drawback is that every method has two more parameters so the code is hardest to be understood.

The RX framework contains two methods that are useful to handle a network connection; Observable.FromAsyncPattern is really useful if you want to use an HttpWebRequest because it can automatically handle the Begin and End parts of the asynchronous pattern. On the other side, Observable.FromEvent can attach an event and gracefully detach when it is not reqired anymore; it is the case of the WebClient class tha expose a DownloadStringCompleted event. So we start handling the async pattern of an HttpWebRequest:

   1: public static IObservable<SyndicationFeed> DownloadFeedWebRequest(Uri uri)
   2: {
   3:     HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
   4:  
   5:     return Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)
   6:         .Invoke()
   7:         .ReadToEnd()
   8:         .ConvertToFeed()
   9:         .ObserveOnDispatcher();
  10: }

These few lines does the trick: The Observable.FromAsyncPattern method encapsulates BeginGetResponse and EndGetResponse. The resulting object is a synchronous representation of the async pattern. The Invoke method call the service then two methods I wrote read the resulting stream and convert the string to a syndicationfeed. Finally, with the ObserveOnDispatcher method I marshal the thread to the user interface using the dispatcher.

The return value is an IObservable<SyndicationFeed> instance that enable the caller to listen for the completion of the operation. The way the method is called is very similar to my previous patter but the method now has only the needed parameters:

   1: DataSource.DownloadFeedWebRequest(new Uri("http://api.twitter.com/1/statuses/public_timeline.atom"))
   2:     .Subscribe(
   3:         r =>
   4:         {
   5:             feed.ItemsSource = r.Items;
   6:         }, HandleExceptions);
The Subscribe method I use here exposes two callbacks, one provides the result of the method and the other is called when an exception occur. If you prefer to use the WebClient you can use the Observable.FromEvent method the complete the same operation.

   1: public static IObservable<SyndicationFeed> DownloadFeedWebClient(Uri uri)
   2: {
   3:     WebClient client = new WebClient();
   4:  
   5:     IObservable<SyndicationFeed> result = Observable.FromEvent<DownloadStringCompletedEventHandler, DownloadStringCompletedEventArgs>(
   6:         ev => new DownloadStringCompletedEventHandler(ev),
   7:         ev => client.DownloadStringCompleted += ev,
   8:         ev => client.DownloadStringCompleted -= ev)
   9:         .Select(o => o.EventArgs.Result)
  10:         .ConvertToFeed();
  11:  
  12:     client.DownloadStringAsync(uri);
  13:  
  14:     return result;
  15: }

In the method we have to specify the attach and detach actions. These action will be called by the RX when the Subscribe method is complete; Here we do not need to call the ReadToEnd method because the WebClient returns directly a string and also we do not have to marshal to the UI Thread because the WebClient already does the trick. The select method convert the resulting EventArgs to the value expected from the ConvertToFeed.

I’m very intersted in your opinion on this example. My feel is that the code is more reusable, and compact, but if someone have a suggestion to improve the method pleare

FormsAuthentication and ClientHttpStack with mixed applications

2010-08-30T16:41:47+01:00 by Andrea Boschin

If you ever tried to have mixed applications, with some regular ASP.NET pages and a bunch of Silverlight applications, where the forms authentication is made with a traditional ASP.NET login page, you have for sure found that you are forced to use the BrowserHttp stack into the Silverlight applications because the FormsAuthentication cookie is not shared between the ASP.NET page and the new ClientHttp stack that is available since Silverlight 3.0.

Since the new ClientHttp stack for many reasons is a huge improvement, is would be a beautiful thing being able to use this stack every time there is the need to place HTTP calls. Finally I found a way to share this cookie across the two stacks, but I want to warn you that the sole way to accomplish this task require a little "dirty hack", that someone might consider unacceptable while it opens some minor security concerns I will detail at the end of the post.

Before continue reading this post please have in mind that my suggestion is to always use the BrowserHttp stack in these scenario, until you do not really need the new stack, e.g. if you have to use some special verb or for some other particular reason.

The dirty hack explained

The first thing you have to know is that when you are using the ClientHttp stack you are free to access the cookies issued by the server and it is also possible to add some cookies to attach to a call. The task we would have to accomplish is simply to read a cookie (often called .ASPXAUTH) from the BrowserHttp stack and add it to the ClientHttp stack and it may seems and easy task.

Unfortunately the BrowserHttp Stack prevent us from accessing the cookies. The cookies management is one of the features that has been added by the new ClientHttp stack and there is not any way to pump out them from the old one.

So my first try was to use the HtmlPage.Document.Cookies property, as I found in some examples on the Internet. Perhaps this may work when the authentication cookie is issued by a custom authentication system, but with FormsAuthentication it is another failed try because the cookies issued by the ASP.NET engine are HttpOnly. This attribute, added since IE6 SP1, prevents the browser scripts - and Silverlight is considered a client script - from accessing these cookies that remain hidden.

So, how can we share these cookies? The only thing you can do is to add the cookie to the InitParams collection when you initialize the plugin in the html page. You have to change this page to be an aspx page and then you can create two keys into the InitParams collection like the following:

   1: public string GetFormsAuthenticationCookie()
   2: {
   3:     return string.Format(
   4:         "FormsCookieName={0},FormsCookieValue={1}",
   5:         FormsAuthentication.FormsCookieName,
   6:         this.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
   7: }

Then in the plugin I would like to have a centralized class reponsible of creating the cookie and adding it to each server call I do. First of all, if you are using WCF you have to enable the CookieContainer from the ServiceReferences.ClientConfig file. You have to add an attribute that exists only in the Siverlight side of the configuration:

   1: <basicHttpBinding>
   2:     <binding name="BasicHttpBinding_IWCFService" 
   3:               maxBufferSize="2147483647"
   4:               enableHttpCookieContainer="True"
   5:               maxReceivedMessageSize="2147483647">
   6:         <security mode="None" />
   7:     </binding>
   8: </basicHttpBinding>

The enableCookieContainer attribute initializes an instance of an IHttpCookieContainerManager into the WCF client an this allow us to manage cookies using the CookieContainer collection. Now we can write a simple application service to put into the app.xaml that we can use to instantiate and initialize the client. The reason of creating an application service is to have a common place where initialize a shared cookie container that reads the InitParam and add the received cookies into it:

   1: public class ClientCreatorService : IApplicationService
   2: {
   3:     public static ClientCreatorService Current
   4:     {
   5:         get
   6:         {
   7:             return Application.Current.ApplicationLifetimeObjects.OfType<ClientCreatorService>().Single();
   8:         }
   9:     }
  10:  
  11:     private CookieContainer SharedCookies { get; set; }
  12:  
  13:     public void StartService(ApplicationServiceContext context)
  14:     {
  15:         this.SharedCookies = new CookieContainer();
  16:         string formsCookieName = context.ApplicationInitParams["FormsCookieName"];
  17:         string formsCookieValue = context.ApplicationInitParams["FormsCookieValue"];
  18:         this.SharedCookies.Add(new Uri(Application.Current.Host.Source, "../"), new Cookie(formsCookieName, formsCookieValue));
  19:     }
  20:  
  21:     public K CreateClient<T, K>()
  22:         where K : ClientBase<T>, new()
  23:         where T : class
  24:     {
  25:         K client = new K();
  26:         IHttpCookieContainerManager cookieManager = client.InnerChannel.GetProperty<IHttpCookieContainerManager>();
  27:         cookieManager.CookieContainer = this.SharedCookies;
  28:         return client;
  29:     }
  30:  
  31:     public void StopService()
  32:     {}
  33: }

During the initialization the ClientCreatorService initialize the SharedCookies with the FormsCookieName and FormsCookieValue. Then the generic CreateClient methid is able to instantiate the required client and add the SharedCookies to it. The usage of the Application Service is pretty simple. Here is how to instantiate the client and place a call:

   1: WCFServiceClient client = ClientCreatorService.Current.CreateClient<IWCFService, WCFServiceClient>();
   2: client.GetIdentityCompleted += new EventHandler<GetIdentityCompletedEventArgs>(client_GetIdentityCompleted);
   3: client.GetIdentityAsync();

If you try the code you will find that the GetIdentity method is able to retrive the membership identity from the HttpContext.Current.User property. This means your service runs in an authenticated context.

What is the drawback?

When you make a dirty thing you have to be aware that there is always almost a drawback. In this case the problem is that the injection of the authentication cookie in the InitParams opens a subtle security concern that is mitigated by the fact that the informations we are disclosing are already public even before my trick was up and running. The use of HttpOnly cookies for authentication is an important improvement that prevent the use of XSS attacks. Having the cookie injected in the page, re-open the window to some pre-IE6 SP1 scripts that could try to access the InitParams collection from javascript and simulate the authentication to the system like our Silverlight application actually does.

This problem must be always in your mind and you have to put on the scale both the advantage of having the ClientHttp working and the security concerns of this trick. My hope is that the Silverlight team will be able to solve this issue in next releases of the plugin, so we can rely on a secure implementation and avoid dirty tricks.

Categories:   Networking | TIPS
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Demo from Italy Remix 2010

2010-07-01T22:44:49+01:00 by Andrea Boschin

Last June 23 I had the pleasure of presenting an introductive session about Silverlight at . During the presentation, included in the “jump start” track, I’ve illustrated the basic capabilities of Silverlight using a simple application that consume a RSS feed from the . The feed give news about all the Earthquakes happening on the world surface and all them are geo tagged.

So, during the session, I’ve showed the application growing from a simple reader to a complex and effective tool to display the earthquakes on a map, using the Silverlight control for Bing Maps. The people was impressed by the application, so I decided to publish the sample on my blog, hoping it can become a good starting point for people wants to approach the Silverlight development.

The application is really simple, without any surprise for skilled people, but it show the main points, from where someone must start. You can see layout, shapes, brushes, animations, projections, network access, syndication and data binding, but also show the power of an Out of browser application and the customization of the window chrome. I hope you enjoy the sample.

Download: code | live demo

SilverVNC - a VNC Viewer with Silverlight 4.0 RC

2010-03-15T19:07:00+01:00 by Andrea Boschin

vnc

I confess I wrote the code of this example few months ago, when only Silverlight 3.0 was on the scene, and I retained it for me because it was a beautiful example but not really useful. Since it uses a socket connection it is a little bit complicated to use it in real world scenario due the fact it needs a policy server, and it is restricted to few number of ports that does not have anything to do with VNC standard ports.

Finally, when I got the first bits of Silverlight 4.0 I decided it would be time to push it out to the folks, thanks to the new out-of-browser feature that now support full-trust installation. I've been persuaded from the opportunity of have a relaxed security on Socket connections meaning that I will be able to connect to any socket based service through a well known port and without having to install a policy server.

So, here is today SilverVNC, a basic implementation of the Remote Framebuffer protocol (RFB) written following the standard specifications (you can download them from the RealVNC website). I've implemented the protocol using the most recent build of UltraVNC to make tests.

As I've already said the implementation is basic. Differently from commercial version I only support the RAW encoding and avoid any type of compression. This simply because handling heavy socket communications with the asyncronous model of silverlight is a kind of bounce game that make simple things really complicated. So I preferred to give a simple example that let the user understand how it works.

How it works?

The core of the example is made of an RfbClient class that encapsulate all the logic needed to communicate with the server, decoding data and rasing events to the user interface. The class is made of methods that receive and send data to the socket. I will not detail the inner content of the class because the RFB protocol specifications are out of the scope of this article. You have only to be aware that while in OOB-Fulltrust the socket may be opened on every port and without any policy.

The main page of the application use the RfbClient to connect to the VNC server and pump data from the socket and decode. Every time RfbClient receive something it raises two types of event:

ResizeFrameBuffer : it mean the server notified a change of the size of the screen. It usually happens at the start of the connection to let the client resize the drawing area.

FramBufferUpdate: it mean the server detected a change on the screen so it cut out a rectangle and send it to the client. The event handler calculate the position of the rectangle on the drawing area and write it.

Here is how to handle these events:

   1: void Client_ResizeFrameBuffer(object sender, EventArgs e)
   2: {
   3:     this.MakeWindowProportional(this.Client.Server.Width, this.Client.Server.Height);
   4:     this.BitMap = new WriteableBitmap(this.Client.Server.Width, this.Client.Server.Height);
   5:     this.vnc.Source = this.BitMap;
   6: }
   7:  
   8: private void MakeWindowProportional(double width, double height)
   9: {
  10:     double proportion = width / height;
  11:     Application.Current.MainWindow.Height = Application.Current.MainWindow.Width / proportion;
  12:     Application.Current.MainWindow.Activate();
  13: }
  14:  
  15: private void Client_FrameBufferUpdate(object sender, FrameBufferUpdateEventArgs e)
  16: {
  17:     Rect rect = e.Rectangle;
  18:  
  19:     int x = 0;
  20:     int y = 0;
  21:  
  22:     foreach (uint color in e.Colors)
  23:     {
  24:         this.BitMap.Pixels[
  25:             (y + (int)rect.Y) *
  26:             this.Client.Server.Width +
  27:             (x + (int)rect.X)] = (int)color;
  28:  
  29:         if (++x == rect.Width)
  30:         {
  31:             x = 0;
  32:             y++;
  33:         }
  34:     }
  35:  
  36:     this.BitMap.Invalidate();
  37: }

Future implementations

There is some improvements I think will apply in the future. First of all I think the algorithm writing into the buffer might be more efficient than the code I showed here. My idea is to implement a MediaStreamSource to produce a video stream you can connect to a MediaElement. This should be better not only from the performances point of view but also may be simpler to be used by developers which needs to add a remote desktop viewer to his applications.

Another improvement is to implement the other compression algorithms. Probably I will implement RRE, CoreRRE and Hex. Finally I would like to transform the viewer in a full functional remote desktop client adding the capability to remote control the target machine. This shouldn't be too difficult.

Until then please have a try to this sample and give me any feedback you think useful to improve it.

Source: http://www.silverlightplayground.org/assets/sources/SilverlightPlayground.RFB.zip
Video: http://www.silverlightplayground.org/assets/video/SilverVNC.wmv
RFB Specifications: The RFB Protocol

Categories:   Networking | News
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Writing a server-less conferencing client with Silverlight 4.0 UDP Multicast

2010-01-02T22:42:07+01:00 by Andrea Boschin

When I wrote my article about , I received many questions about writing application that communicate each other with this protocol. The reason for this request is that many people believe that Silverlight being a good platform for game developers due to its great graphical features and its simplicity, so a lot of them want to implement some kind of communication for on-line collaborative games.

Local connections have not been made for this kind of usage because them are available only for communication between application instances running in the same machine and it is not possible to use them to create gaming communications.

With Silverligth 4.0 the System.Net namespace hosts a new kind of socket communications, named UDP Multicast, that seems to be a possible solution for gaming applications but also for applications requiring fast communication between multiple clients, like conferencing applications also with video streaming support.

, also know as IP Multicast, is a well-known protocol that enables the ip infrastructure to replicate messages from multiple sources to be delivered easily to an undefined number of subscribers. The protocol works using a special class of IP addresses (224.0.0.0/4 for ipV4) where each single address represent a group of clients that is communicating each other relying on the network infrastructure for the replication of the messages. This enable the creation of client applications that do not need to have a central server where clients needs to connect using the common TCP sockets.

Like the common UDP protocol, IP Multicast is a not-connected protocol that does not guarantee the arrival of the messages and the order of delivery. So if you need a realiable channel the better is to rely on TCP sockets or you need to implement some kind of consistency check.

Writing a conferencing client

The first example I wrote to test the UDP Multicast feature is a simple conferencing client that enable people to join a multicast group and then send messages to the other members of the group.  The example you can download at the end of the article is very simplified and let the user specify an username (without checking if someone else is using the same username) and join the muklticast group. Then the user can type messages and send them to all the group members.

Silverlight 4.0 has two new classes to implement a multicast client

1) UdpSingleSourceMulticastClient let work with a single well-known source that is the unique client allowed to send to the group. This is the one-to-many communication. You can imagine to write a video source with this class and multiple clients to receive packets from it.

2) UdpAnySourceMulticastClient enables all the clients both to send and receive to or from the multicast group. This let you create something similar to a conferencing application where many-to-many connection is required.

When you use a multicast client the first thing you have to do is to join the group, using the known muticast ip address (ex: 224.0.0.1) and the port (ex: 3000). When the connection have been made you can start send and/or receive from the group. Differently from the TCP sockets with UDPMulticast you do not have a restricted set of ports to use. All the ports above of 1024 are available to the plugin.

Here is a snippet from my UDPAnySourceMulticastChannel I wrote for my example:

   1: public UdpAnySourceMulticastChannel(IPAddress address, int port, int maxMessageSize)
   2: {
   3:     this.ReceiveBuffer = new byte[maxMessageSize];
   4:     this.Client = new UdpAnySourceMulticastClient(address, port);
   5: }
   6:  
   7: public void Open()
   8: {
   9:     if (!this.IsJoined)
  10:     {
  11:         this.Client.BeginJoinGroup(
  12:             result =>
  13:             {
  14:                 this.Client.EndJoinGroup(result);
  15:                 this.IsJoined = true;
  16:                 Deployment.Current.Dispatcher.BeginInvoke(
  17:                     () =>
  18:                     {
  19:                         this.OnAfterOpen();
  20:                         this.Receive();
  21:                     });
  22:             }, null);
  23:     }
  24: }

In the constructor of the class, I've created an instance of the multicast client with the required address and port, then in the Open method I've called the BeginJoinGroup method that starts an asyncronous join request to the multicast address. As always the Silverlight's communication is asyncronous so when the callback is called I need to invoke the EndJoinGroup and then marshal the thread to the user interface with using the Dispatcher.

When the group has been joined you can start receiving and sending. This two actions are simultaneous because while you are receiving messages (or you are waiting to receive) you can also send messages to the group. So you have to invoke the BeginReceiveFromGroup method that starts listening for incoming packets and calls the callback method when something has been received. While the client is waiting for something to receive you can also call the BeginSendToGroup method to send something to the group. You have to be aware that when you send a packet to the group you will also receive the packet you sent because the multicast will replicate the message to all the joined clients.

   1: private void Receive()
   2: {
   3:     if (this.IsJoined)
   4:     {
   5:         Array.Clear(this.ReceiveBuffer, 0, this.ReceiveBuffer.Length);
   6:  
   7:         this.Client.BeginReceiveFromGroup(this.ReceiveBuffer, 0, this.ReceiveBuffer.Length,
   8:             result =>
   9:             {
  10:                 if (!IsDisposed)
  11:                 {
  12:                     IPEndPoint source;
  13:                     this.Client.EndReceiveFromGroup(result, out source);
  14:                     Deployment.Current.Dispatcher.BeginInvoke(
  15:                         () =>
  16:                         {
  17:                             this.OnReceive(source, this.ReceiveBuffer);
  18:                             this.Receive();
  19:                         });
  20:                 }
  21:             }, null);
  22:     }
  23: }
  24:  
  25: public void Send(string format, params object [] args)
  26: {
  27:     if (this.IsJoined)
  28:     {
  29:         byte[] data = Encoding.UTF8.GetBytes(string.Format(format,args));
  30:  
  31:         this.Client.BeginSendToGroup(data, 0, data.Length,
  32:             result =>
  33:             {
  34:                 this.Client.EndSendToGroup(result);
  35:             }, null);
  36:     }
  37: }

The UDPAnySourceMulticastClient class has some other interesting methods. You can send messages to the group specifing the destination so the network infrastructure will route the message to a single target. You can also block and unblock an IPAddress to prevent messages incoming from it to be received.

There is not a "Disconnect" or "Close" method but when you need to end the communication you can call the Dispose method of the client class. This will cause the pending receive to be dropped. It is important to have a flag set when the class is disposing because when the pending receive is dropped your callback is notified and you have to be aware that the client instance is not valid anymore and avoid to call the EndReceiveFromGroup method alse you will get an exception.

   1: /// <summary>
   2: /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
   3: /// </summary>
   4: public void Dispose()
   5: {
   6:     if (!IsDisposed)
   7:     {
   8:         this.IsDisposed = true;
   9:  
  10:         if (this.Client != null)
  11:             this.Client.Dispose();
  12:     }
  13: }

The client needs only to create an instance of the class an then call the Open method to join the multicast group. The channel then automatically starts listening from incoming packets and raise an event every time it detect something. So when the user hit the send button it I can call the Send() method to send a new packet and when the channel notify me about the arrival of a packet I add it to the logging listbox. I've added an AfterOpened and BeforeClose events to allow the client to send a message just after joining the group and before leaving it.

PolicyServer

Like other networking tools in Silverlight, the ip multicast requires something issuing a policy file. This is the sole server-side requirement for this protocol working fine. The policy server has to implement a two UDP messages system. The first message, sent by the client, is a datagram called "announcement" that asks the server to issue a policy file. When the server receive this message have to send an xml file that authorize to the client to communicate with a particular ip address and port. The mechanism is very similar to the TCP socket policy server but use an UDP messagging system.

To implement this server the best is downloading this project from MSDN code gallery. The project contains a working policy server that you can simply start from a console application or from a win32 service.

The drawbacks

The application I have included at the end of the article is very simple and demostrate the power of this messaging system, that was initially designed for effective video streaming. Unfortunately there is some drawbacks. First of all, also if I've entitled this example "server-less" this is true for the 99%. You need a policy issuer that is a little server, but it is not crucial for performance concerns. The system is really simpler than an always-connected TCP implementation and due to the nature of the UDP protocol really require less resources.

Another concern is about the security and realiability. The UDP protocol does not implements some infrastructure to avoid the ip spoofing and does not guarantee the packet delivery and the arrival order. In a real world solution you have to be aware of these limitation and take care of them. You have to write code to sign packets to know from whom they are issued and to handle packet loss and unordered delivery. This may be someway complex, but is a little price to pay for the effectiveness of this protocol.

Finally, the major drawback is that the most common firewalls manage to block this kind of traffic. If using a TCP socket server on a well known port is someway difficult due to the need of having firewall configurations, implementing a multicast is probably more complex specifically if you need to send the packets through the Internet. So in my opinion the most common scenario for this protocol to work is a local area network where you can manage to have firewalls and network infrastructure comply with it.

Download: SilverlightPlayground.UDPMulticast.zip (181 KB)

Categories:   Networking
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | Comment RSSRSS comment feed

How to configure an AuthenticationDomainService using Ria Services Class Library

2009-11-06T11:36:01+01:00 by Andrea Boschin

Using a Ria Services Class library to collect DomainServices and DomainContexts in a solution is a good practice because everyone know the value of having classes separated in projects instead of having them in the web project.

If you try to create this kind of project and then you add an Authentication Domain Service with the July 2009 CTP of Ria Services you will find two major drawbacks. First of all you will notice the generated code does not contains a RiaContext class. RiaContext is the class responsible to handle the User and roles and configure the type of Authentication to use in the application.

To workaround to this problem you may simply write by hand this class and put it in the client side part of the Ria Services library project. The code can be copied by an AuthenticationDomainContext generated in the web project but it is very simple and I show you the code here:

   1: public sealed partial class RiaContext : System.Windows.Ria.RiaContextBase
   2: {
   3:     #region Extensibility Method Definitions
   4:  
   5:     partial void OnCreated();
   6:  
   7:     #endregion
   8:  
   9:     public RiaContext()
  10:     {
  11:         this.OnCreated();
  12:     }
  13:  
  14:     public new static RiaContext Current
  15:     {
  16:         get
  17:         {
  18:             return ((RiaContext)(System.Windows.Ria.RiaContextBase.Current));
  19:         }
  20:     }
  21:  
  22:     public new User User
  23:     {
  24:         get
  25:         {
  26:             return ((User)(base.User));
  27:         }
  28:     }
  29: }

With this class you can configure the Authentication Domain Context as you did with the generated class. So you have to add it to the App.config, in the ApplicationLifetimeObjects tag and then add a kind of authentication like the WindowsAuthentication and FormsAuthentication.

The second drawback is that if you run the project this way and then you call the Login() method (or any other method) of the RiaContext you will get an error:

The DomainContextType is null or invalid and there are no contexts generated from AuthenticationBase<T>

This probably come from the fact that the RiaContext is not correctly initializated so when the class search for a valid domaincontext to handle the Login call it fails because it does not find it. The tip to correct this behavior is to specify the DomainContext property in the Authentication you have choosed. Here is how to change the App.xaml file:

   1: <Application.ApplicationLifetimeObjects>
   2:     <slpgria:RiaContext>
   3:         <slpgria:RiaContext.Authentication>
   4:             <appsvc:FormsAuthentication>
   5:                 <appsvc:FormsAuthentication.DomainContext>
   6:                     <slpgdc:MyAuthenticationDomainContext />
   7:                 </appsvc:FormsAuthentication.DomainContext>
   8:             </appsvc:FormsAuthentication>
   9:         </slpgria:RiaContext.Authentication>
  10:     </slpgria:RiaContext>
  11: </Application.ApplicationLifetimeObjects>

As you can see you have simply to give an instance of the generated Authentication Domain context class to the FormsAuthentication (or Windows Authentication as well). The RiaContext need to have this instance to make the calls to the BL methods in the Domain Service.

I really do not know if this behavior will be corrected in the next releases of RiaServices. The solution is pretty simple but take me some hours to understand what are going wrong. So I hope this may help you to spare some time making your experiments with the current release.

Categories:   TIPS | Networking
Actions:   E-mail | del.icio.us | Permalink | Comments (5) | Comment RSSRSS comment feed

Handling duplicated connections on Polling Duplex

2009-10-23T00:46:00+01:00 by Andrea Boschin

The last tip I would like to propose is a tecnique to avoid a single client machine connect multiple times to the same polling server. This may be the case when the user starts two or more instances of the browser or open the same page in multiple tabs. In this scenario may be unuseful to have every page connected to the server.

In Silverlight 3.0 there is a way to check when a plugin has been loaded many times. When you try to create a LocalReceiver with the same name from two instances you get an exception because they cannot share the same name. So using a LocalReceiver you can check if another browser is open.

   1: public override void Start()
   2: {
   3:     LocalMessageReceiver receiver = this.CreateReceiver();
   4:  
   5:     if (receiver != null)
   6:     {}  // receiver created: I'm the master...
   7:     else
   8:     {}  // cannot create receiver: I'm a slave...
   9: }
  10:  
  11: private LocalMessageReceiver CreateReceiver()
  12: {
  13:     try
  14:     {
  15:         LocalMessageReceiver receiver = new LocalMessageReceiver("PollingReceiver");
  16:         receiver.Listen();
  17:         return receiver;
  18:     }
  19:     catch(ListenFailedException)
  20:     {
  21:         return null;
  22:     }
  23: }

 

Checking the presence of another instance is only half of the work to do. When you detect you are a slave in the machine you need to avoid connecting - slave does nothing because a master already exists - and probably you have to change the user interface to let the user know that there is another instance running.

In my application I need to check the presence of the master every few seconds to let a slave becoming a master. To do this I've created two classes MasterPollingClientCode  SlavePollingClientCore implementing the same interface IPollingClientCore. The first class connect to the server and the other class simply does nothing.

   1: public override void Start()
   2: {
   3:     LocalMessageReceiver receiver = this.CreateReceiver();
   4:  
   5:     if (receiver != null)
   6:         this.Core = new MasterPollingClientCore(this.SessionId, this.EndPoint, receiver);
   7:     else
   8:         this.Core = new SlavePollingClientCore(this.LocalId, 
                          new LocalMessageSender("PollingSender" + this.LocalId.ToString()));
   9:  
  10:     this.Core.AlarmReceived += new EventHandler<NotifyAlarmReceivedEventArgs>(Core_AlarmReceived);
  11:     this.Core.Connected += new EventHandler(Core_Connected);
  12:     this.Core.Disconnected += new EventHandler(Core_Disconnected);
  13:     this.Core.Fault += new EventHandler<PollingFaultEventArgs>(Core_Fault);
  14:     this.Core.Start();
  15:     base.Start();
  16: }
 

The container class, then starts a thread. This thread try to create a new LocalReceiver and when it is able to get an instance it change the core class from slave to master and connect to the server. This way the client is always connected to the server with alwasy one simple connection:

   1: protected override void ThreadProc()
   2:     {
   3:         Debug.WriteLine("ThreadProc");
   4:  
   5:         while(WaitHandle.WaitTimeout == WaitHandle.WaitAny(this.ExitHandles, 5000))
   6:         {
   7:             if (this.Mode != PollingClientMode.Master)
   8:             {
   9:                 Deployment.Current.Dispatcher.BeginInvoke(
  10:                     ()=> this.TryConvertToMaster());
  11:             }
  12:         }
  13:     }
  14:  
  15:     /// <summary>
  16:     /// Tries the convert to master.
  17:     /// </summary>
  18:     private void TryConvertToMaster()
  19:     {
  20:         Debug.WriteLine("TryConvertToMaster");
  21:  
  22:         LocalMessageReceiver receiver = this.CreateReceiver();
  23:  
  24:         if (receiver != null)
  25:         {
  26:             Debug.WriteLine("created");
  27:  
  28:             // detach all
  29:             this.Core.Stop();
  30:             this.Core.AlarmReceived -= new EventHandler<NotifyAlarmReceivedEventArgs>(Core_AlarmReceived);
  31:             this.Core.Connected -= new EventHandler(Core_Connected);
  32:             this.Core.Disconnected -= new EventHandler(Core_Disconnected);
  33:             this.Core.Fault -= new EventHandler<PollingFaultEventArgs>(Core_Fault);
  34:             // create new core
  35:             this.Core = new MasterPollingClientCore(this.SessionId, this.EndPoint, receiver);
  36:             // attach all
  37:             this.Core.AlarmReceived += new EventHandler<NotifyAlarmReceivedEventArgs>(Core_AlarmReceived);
  38:             this.Core.Connected += new EventHandler(Core_Connected);
  39:             this.Core.Disconnected += new EventHandler(Core_Disconnected);
  40:             this.Core.Fault += new EventHandler<PollingFaultEventArgs>(Core_Fault);
  41:             this.Core.Start();
  42:         }
  43:     }
 
 

If you are brave you can try to implement a communication between Slave and Master using a LocalSender. Using the code I provider this task cannot be too hard.

Good Work

Categories:   Networking
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | Comment RSSRSS comment feed

How to avoid flooding a PollingDuplex server

2009-10-06T14:37:39+01:00 by Andrea Boschin

Returning on the PollingDuplex argument, today I would like to illustrate a tecnique I used to avoid the flooding in my Polling Duplex service. The problem come from the fact that my server retain a list of connected clients and is unable to detect the disconnection in a short time. After a while the notification from the server to the disconnected client will timeout so the server handle the timeout and remove the client from its list. But if for some reason a client Register itself multiple times the server notification list will grow and this may become a problem causing the service to slow down its response time.

In a recent project I have to address this issue because of the way the polling client works. Imagine having a instant messaging client using PollingDuplex in all the pages of a portal. When the user navigate in the website the polling client will repeatly connect and disconnect from the polling server because the user may change page after short time.

How to generate a persistent ClientID

To handle this problem I need to have a globally unique id identifing the connecting client. If the ID is unique across different connected clients the server can use this ID to search previuos instances of the client in his notification list and if found it discart the old client and replace it with the new one. The solution is pretty simple but it require the ability to generate a very unique id (obviously a Guid) and then persist it across different browser session.

The trick is to use the Isolated Storage. The first time I start the client it generate the Guid and save it in the IsolatedStorageSettings collection. Then it use the guid to connect and register to the polling server.

All the other times the client find the Guid in the IsolatedStorageSettings and avoid to generate another Guid but use the old identifier. Here is the code to generate the guid or take id from the storage:

   1: private void Application_Startup(object sender, StartupEventArgs e)
   2: {
   3:     Guid key;
   4:  
   5:     if (!IsolatedStorageSettings.ApplicationSettings.Contains("InstanceKey"))
   6:     {
   7:         key = Guid.NewGuid();
   8:         IsolatedStorageSettings.ApplicationSettings["InstanceKey"] = key;
   9:         IsolatedStorageSettings.ApplicationSettings.Save();
  10:     }
  11:     else
  12:         key = (Guid)IsolatedStorageSettings.ApplicationSettings["InstanceKey"];
  13:  
  14:     this.RootVisual = new MainPage(key.ToString());
  15: }

I put the code in the Application_Startup method then I pass the key to the MainPage constructor because it must use the guid to connect to the server.

On the server side I've slightly changed the Register method and the Polling thread to handle the new guid. First of all I request the id in the Register method:

   1: public void Register(string sessionId)
   2: {
   3:     IPollingServiceClient client =
   4:         OperationContext.Current.GetCallbackChannel<IPollingServiceClient>();
   5:  
   6:     PollingMonitor.Current.Register(client, sessionId);
   7: }

Then the server checks his notification list to add or change the callback client:

   1: /// <summary>
   2: /// Adds the specified item.
   3: /// </summary>
   4: /// <param name="item">The item.</param>
   5: public void Add(IPollingServiceClient client, string sessionId)
   6: {
   7:     var found = (from c in this
   8:                  where c.SessionId == sessionId
   9:                  select c).SingleOrDefault();
  10:  
  11:     if (found != null)
  12:         found.ChangeClient(client);
  13:     else
  14:         this.Add(new PollingClient(client, sessionId));
  15: }

The ChangeClient() method simply put the new callback client in the object instance representing the client in the list.

There are only two drawbacks in this tecnique. The first is that the user can clear his IsolatedStorage using the Silverlight context menu. This deletes the saved Guid so the next time the client connect to the server it generate another Guid. On the other side someone may discover some privacy concerns on having an id globally identifying the client because this may become a way to track the user activities. You have to be aware of this problem and eventually you can mitigate the problem using a TTL to invalidate the Guid after some hours or days so the client will change the Guid and the tracking become hardest.

Categories:   TIPS | Networking
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Handling faults on PollingDuplex while server is not available

2009-09-25T15:57:34+01:00 by Andrea Boschin

During the development of the project I'm currently working I've implemented a polling duplex client and I found some improvements to the code I've published some weeks ago in this post.

The problem I would like to answer here is caused by server unavailability that may origin in many causes. In my scenario I'm using a WCF service hosted by Internet Information Server. While I'm using a server-side thread running in the context of the Application Pool there may be some conditions where Application Pool is recycled so the server thread is aborted and the PollingDuplex communication stops.

There is many reasons why we have to avoid this condition. In my case it is important that the client continue receive updates from the polling server without it require a page refresh from the user. So I've implemented a fault handling procedure that let my client detect when the server become unavailable and then it retry connecting and restart server side thread.

First of all we have to write a registration procedure. My duplex channel work using a Register() ServiceOperation called by the client that subscribe the client in the server thread for updates notification. The client callback contract has a single NotifyAlarm() method used by the server to notify messages to client. Here is the client-side code I use to start the polling:

   1: /// <summary>
   2: /// Registers this instance.
   3: /// </summary>
   4: private void Register()
   5: {
   6:     this.Client = new PollingServiceClient(
   7:         new CustomBinding(
   8:             new PollingDuplexBindingElement
   9:                 {
  10:                     InactivityTimeout = new TimeSpan(1, 0, 0),
  11:                     ClientPollTimeout = new TimeSpan(0, 1, 0)
  12:                 },
  13:             new BinaryMessageEncodingBindingElement(),
  14:             new HttpTransportBindingElement()),
  15:         this.EndPoint);
  16:  
  17:     this.Client.NotifyAlarmReceived += 
  18:         new EventHandler<NotifyAlarmReceivedEventArgs>(Client_NotifyAlarmReceived);
  19:     this.Client.InnerChannel.Faulted += 
  20:         new EventHandler(Client_Faulted);
  21:     this.Client.RegisterCompleted += 
  22:         new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(Client_RegisterCompleted);
  23:     this.Client.RegisterAsync(this.SessionId);
  24: }

To handle channel fault I subscribe the Faulted event in the InnerChannel. I cannot find any other way to detect when the polling fail due to server unavailability. If you trace the polling of the client and then simulate the server unavailability, recycling the application pool you will see a 404 error (if you use ClientHttpStack the error will be more specific).

Untitled

When this error occur the InnerChannel.Faulted event is raised so you can restart the polling calling the Register() method again. In the Faulted event handler I simply call the Register method again. 

   1: /// <summary>
   2: /// Handles the Faulted event of the Client control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
   6: void Client_Faulted(object sender, EventArgs e)
   7: {
   8:     Deployment.Current.Dispatcher.BeginInvoke(
   9:         () =>
  10:         {
  11:             this.OnDisconnected();
  12:             this.Register();
  13:         });
  14: }

The better will be starting a Timer to retry connection on a regular timeout to let the client returning online after longer server unavailability. This may be useful also when we start the polling because we can dowload the Silverlight application from a server but then it starts the polling to another server. So I've added some code in the RegisterCompleted event handler and when I get an exception from the Register() method I start a separate thread. It waits for 60 seconds then recall the Register() method again.

   1: void Client_RegisterCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
   2: {
   3:     if (e.Error == null)
   4:         this.OnConnected();
   5:     else
   6:     {
   7:         this.OnFault(e.Error);
   8:  
   9:         ThreadPool.QueueUserWorkItem(
  10:             (o) =>
  11:             {
  12:                 Thread.Sleep(60000);
  13:  
  14:                 Deployment.Current.Dispatcher.BeginInvoke(
  15:                     () => this.Register());
  16:             });
  17:     }
  18: }

You have to be aware that the Faulted event require you to marshal the context of the thread before updating any UI element. In my code I raise an event of a wrapper object to let UI reflect the temporary disconnection. So I have to use the Dispatcher to marshal the Thread to the UI.

This is all for now. I will write more on this argumet on the next days to handle a different condition.

Categories:   Networking
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed