In-Depth Async in Akka .NET: Why We Need PipeTo()

Update 21st August 2016: I wrote this article based on outdated Akka .NET documentation that discouraged async/await within actors and suggested using PipeTo() instead. Akka .NET now does support async/await (thanks to the ReceiveAsync() method), and PipeTo() is not a replacement for it. Aaron Stannard (in a comment on this post) and Roger Alsing (on Reddit) from the Akka .NET team were very prompt in correcting various misconceptions, and Aaron Stannard has since updated the Petabridge blog post about PipeTo(). See my followup post for the latest best practices.

Tasks and the more recent async/await syntactic sugar have been a blessing for .NET developers aiming to keep their applications responsive despite increasing requirements for I/O and CPU-intensive requests.

Thus it was really odd for me to learn that Akka .NET, an emergent framework for distributed computing, not only does not support async/await directly within actors, but actually discourages its use (going as far as calling them “code smell”).

In fact, they implemented this PipeTo() workaround that you need to use, sending the result of a task to an actor for processing. You can’t use async/await; you have to resort to the old ContinueWith() way of chaining tasks if you want to do any post-execution logic. If you’ve worked with ContinueWith() in the past, you’ll know it can get ugly really fast.

Why is it such a problem to have elegant asynchrony in our actors, seeing how competitor Microsoft Orleans has no problem with it? As Natan Vivo said in the comments of The Top 7 Mistakes Newbies Make with Akka.NET:

“The fact I decided to use DbCommand.ExecuteNonQueryAsync() instead of DbCommand.ExecuteNonQuery() shouldn’t force me to break a single message into multiple messages with PipeTo.”

Update 20th August 2016: Thanks to the Reddit user who brought to my attention that there actually is proper async support (though apparently not yet documented anywhere). Use the ReceiveActor’s ReceiveAsync() method.

Why Akka .NET Discourages async/await

To learn why awaiting in an actor is bad, let’s break the rules and do it.

    public class BusyActor : UntypedActor
    {
        protected override void OnReceive(object message)
        {
            Console.WriteLine($"Begin processing {message.ToString()}");

            Thread.Sleep(2000);

            Console.WriteLine($"End processing {message.ToString()}");
        }
    }

I have this example actor. For now it’s doing synchronous stuff, sleeping for a couple of seconds and writing something before and after so we can see the behaviour.

        static void Main(string[] args)
        {
            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                var actor = actorSystem.ActorOf(Props.Create<BusyActor>(), "BusyActor");

                actor.Tell("Task 1");
                actor.Tell("Task 2");
                actor.Tell("Task 3");

                Console.ReadLine();
            }
        }

The main program simply creates the actor system and the actor, and then sends it three messages in succession.

akkanet-async-synchronous-output

As you can see, the messages are handled sequentially and there is no overlap.

Now let’s change the actor to work asynchronously instead:

    public class BusyActor : UntypedActor
    {
        protected override async void OnReceive(object message)
        {
            Console.WriteLine($"Begin processing {message.ToString()}");

            await Task.Delay(2000);

            Console.WriteLine($"End processing {message.ToString()}");
        }
    }

Run it again…

akkanet-async-async-output

What happened here? All three messages were processed in quick succession, and they have been interleaved. This is very bad, and in fact we were warned about it. Quoting the questions on the official PipeTo() sample:

“Await breaks the “actors process one message at a time” guarantee, and suddenly your actor’s context might be different. Variables such as the Sender of the previous message may be different, or the actor might even be shutting down when the await call returns to the previous context.”

Why Processing Messages Asynchronously Causes Interleaving

We can learn a lot about how actors process messages by investigating the Akka .NET source code. This method in Mailbox.cs seems to be more or less where actors begin to process their messages:

        private void ProcessMailbox(int left, long deadlineTicks)
        {
            while (ShouldProcessMessage())
            {
                Envelope next;
                if (!TryDequeue(out next)) return;

                DebugPrint("{0} processing message {1}", Actor.Self, next);

                // not going to bother catching ThreadAbortExceptions here, since they'll get rethrown anyway
                Actor.Invoke(next);
                ProcessAllSystemMessages();
                if (left > 1 && (Dispatcher.ThroughputDeadlineTime.HasValue == false || (MonotonicClock.GetTicks() - deadlineTicks) < 0))
                {
                    left = left - 1;
                    continue;
                }
                break;
            }
        }

From Actor.Invoke(), there is a succession of method calls that ends in a method called Receive() in UntypedActor.cs:

        protected sealed override bool Receive(object message)
        {
            OnReceive(message);
            return true;
        }

Our OnReceive() method, where implement our message-handling logic for our actors, is subsequently called.

Now, the code above may look confusing, but the point here is not to understand what it’s doing exactly. Take a closer look. The methods in the call stack are mostly void (or otherwise returning simple types). There are no Tasks to be seen anywhere.

What does this mean for us? It means that we’re doing something very bad when we declare our message handler as async void.

Understanding async void

In order to better understand why the approach we took earlier will never work, it’s best to look at a much simpler example:

    class Program
    {
        static void Main(string[] args)
        {
            RunAll();
            Console.ReadLine();
        }

        static void RunAll()
        {
            RunJob("Job 1");
            RunJob("Job 2");
            RunJob("Job 3");
        }

        static void RunJob(string str)
        {
            Console.WriteLine("Start " + str);

            Thread.Sleep(2000);

            Console.WriteLine("End " + str);
        }
    }

Here we’ve reproduced the earlier scenario, but with no Akka .NET. And with the synchronous implementation, it works just fine:

akkanet-async-taskasync-output

Let’s change RunJob() to run asynchronously:

        static async void RunJob(string str)
        {
            Console.WriteLine("Start " + str);

            await Task.Delay(2000);

            Console.WriteLine("End " + str);
        }

When we run it, the following happens:

akkanet-async-taskasync2-output

This is exactly the same interleaving problem we had with Akka .NET, except that this time we have no Akka .NET.

The real reason why we have this problem is due to an incorrect use of asynchrony. As you can read in Stephen Cleary’s MSDN Magazine article, “Async/Await – Best Practices in Asynchronous Programming” (March 2013), async void methods can be pretty dangerous to work with. When you call an async void method, you have two main problems: you have no way of awaiting completion of the method, and exceptions can bring the whole application down.

But here, we have also seen a third problem: that the method effectively exits when you await, returning execution control to the caller. In Akka .NET, this means that the next message will begin processing while the current one hasn’t finished yet.

async void methods should be restricted to methods at the beginning of the call chain (such as event handlers and WPF command handlers). You can’t sneak asynchrony into an otherwise synchronous call stack by introducing an async void. If you do async, it has to be all the way.

So it really seems that the problem with having asynchronous actor logic is simply that Akka .NET was never really designed to work with asynchronous methods.

Asynchrony in Akka .NET with PipeTo()

It should be clear by now that doing async/await in actors is not an option. So how do we go about doing our asynchronous work? We do that by using the PipeTo() pattern (because in Akka .NET, everything is called a pattern).

Let’s go back to our original example with the BusyActor. We left off with this code:

    public class BusyActor : UntypedActor
    {
        protected override async void OnReceive(object message)
        {
            Console.WriteLine($"Begin processing {message.ToString()}");

            await Task.Delay(2000);

            Console.WriteLine($"End processing {message.ToString()}");
        }
    }

Now, we need to refactor this to do the asynchronous operation (in this case Task.Delay()) in a fire-and-forget manner, and send the result as a separate message to an actor. We’re going to need separate messages for this:

    public class TaskMessage
    {
        public string Message { get; }

        public TaskMessage(string message)
        {
            this.Message = message;
        }

        public override string ToString()
        {
            return this.Message;
        }
    }

    public class ResultMessage
    {
        public string Message { get; }

        public ResultMessage(string message)
        {
            this.Message = message;
        }

        public override string ToString()
        {
            return this.Message;
        }
    }

Since our message handling is going to grow a little, UntypedActor is no longer suitable for what we need. Instead, we’ll refactor BusyActor as follows:

    public class BusyActor : ReceiveActor
    {
        public BusyActor()
        {
            this.Receive<TaskMessage>(m => Handle(m));
            this.Receive<ResultMessage>(m => Handle(m));
        }

        public void Handle(TaskMessage message)
        {
            Console.WriteLine($"Begin processing {message.ToString()}");

            Task.Delay(2000)
                .ContinueWith(x => new ResultMessage(message.Message),
                    TaskContinuationOptions.AttachedToParent
                    & TaskContinuationOptions.ExecuteSynchronously)
                .PipeTo(Self);
        }

        public void Handle(ResultMessage message)
        {
            Console.WriteLine($"End processing {message.ToString()}");
        }
    }

Similarly to the official example (which shows how to do an HTTP GET request within an actor), we are firing off an asynchronous request but not awaiting it. This happens in fire-and-forget manner as far as the actor is concerned. When the asynchronous operation is done, we create a new message and send it to the same actor so that he can log the end of the task.

Note that we have those two TaskContinuationOptions settings. You can read more about them in the official PipeTo() blog post, but the point I want to make here is that you need to remember to include them, and this makes this approach pretty error-prone.

Back in our main program, we need to send a TaskMessage instead of a simple string now:

        static void Main(string[] args)
        {
            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                var actor = actorSystem.ActorOf(Props.Create<BusyActor>(), "BusyActor");

                actor.Tell(new TaskMessage("Task 1"));
                actor.Tell(new TaskMessage("Task 2"));
                actor.Tell(new TaskMessage("Task 3"));

                Console.ReadLine();
            }
        }

Let us now run this code:

akkanet-async-pipeto-interleaving

This is bad. Even with PipeTo(), we still have the same interleaving problem as before. If you think about it, it makes sense.

What we are doing is firing off a fire-and-forget task, and the method can return immediately, thus allowing the next message to be processed before the asynchronous operation has completed. This is exactly the same problem we had when using async void.

If you’re firing off an asynchronous operation that doesn’t touch anything else and you just want to take its result, then the suggested PipeTo() approach will work. But if you need a guarantee on message order because your message processing is touching some state (thus an older message might overwrite the results of a newer message), then this is going to be a problem.

Coupling and Cohesion

Another problem with using PipeTo() is that it… complicates things. You can already see how our original example has been bloated into something a lot less easy to work with, just for the sake of not using async/await. But there’s more.

One common pitfall I see when developers begin to understand the importance of decoupled software is that they go to the other extreme: they split up components into extremely granular classes. In doing so, they breaking the companion principle of coupling: cohesion. While coupling dictates that software components should have minimal dependencies between themselves, cohesion suggests that components with strong direct interrelations should work closely together. Making classes too granular, for instance, is another way to end up with messy software.

At the beginning of this article, I quoted Natan Vivo’s comment about having to break a database operation into multiple operations. Typically, in ADO .NET, a database operation would look something like this:

  1. Open a connection to the database.
  2. Execute a command (query, nonquery, etc) against the database.
  3. In case of a query, iterate over the rows and do something with them.

Each of the three operations above can be done asynchronously in sequence. They are meant to be together because they are part of the same cohesive operation. But if you break each of these operations into different messages and different message handlers, you’re going to scatter this otherwise contiguous operation all over the place. And that makes software a lot harder to maintain.

So when I see something like (to again quote the questions from the official Akka .NET PipeTo() sample) this:

“So just don’t do it. Await is evil inside an actor. Await is just syntactic sugar anyway. Use ContinueWith and PipeTo instead.”

…I feel the need to remind people that syntactic sugar is really important to make our software easier to write, but more importantly, easier to maintain.

For the reasons outlined above, I believe that the PipeTo() ‘pattern’ is really an anti-pattern, and I appeal for native asynchronous support in Akka .NET rather than quirky workarounds.

Multiplayer Game with Akka .NET and Publish/Subscribe

This article shows how to develop the basis of a client/server multiplayer game. The clients move around the playing field and their movements are broadcasted to all other clients via the server. This is done using the Publish/Subscribe (or Observer) pattern. The software is developed using Akka .NET, and the network communications implementation is based on Akka.Remote.

The source code for this article is available at the Gigi Labs BitBucket Repository.

Prerequisites

In this article, we’re going to develop a client/server application. In our solution, we’ll have two different console applications for client and server respectively. We’ll also have a third project: a class library containing message classes used by both. The client and server projects will reference this class library.

We’re going to use Akka .NET and its related Akka.Remote component in both client and server. These can be installed via NuGet.

Install-Package Akka
Install-Package Akka.Remote

Server

The server is actually the simplest part of this application. We have one actor which is a direct implementation of the Publish/Subscribe pattern. This ServerActor keeps track of subscribers (which are remote client actors in this case) using their respective subscriber GUIDs.

    public class ServerActor : TypedActor,
        IHandle<SubscribeMessage>,
        IHandle<UpdateLocationMessage>,
        IHandle<UnsubscribeMessage>
    {
        private Dictionary<Guid, IActorRef> subscribers;

        public ServerActor()
        {
            this.subscribers = new Dictionary<Guid, IActorRef>();
        }

        public void Handle(SubscribeMessage message)
        {
            this.subscribers[message.SubscriberGuid] = Sender;
        }

        public void Handle(UpdateLocationMessage message)
        {
            this.Broadcast(message);
        }

        public void Handle(UnsubscribeMessage message)
        {
            // remove subscription

            if (this.subscribers.ContainsKey(message.SubscriberGuid))
                this.subscribers.Remove(message.SubscriberGuid);

            // broadcast removal to everyone else

            this.Broadcast(message);
        }

        private void Broadcast<T>(T message) where T : class
        {
            foreach (var subscriber in this.subscribers.Values)
                subscriber.Tell(message);
        }
    }

Subscription and unsubscription are simple add/remove operations on the subscriber dictionary. When a client moves in the playing area, he sends an update to the server in the form of an UpdateLocationMessage. This is then broadcasted to all subscribers (in this case also to the sender) so that they can update the position of the client that moved.

The messages will be covered in the next section.

The server program does nothing more than create the ActorSystem, and an instance of the ServerActor within it:

        static void Main(string[] args)
        {
            var configManager = ConfigurationManager.AppSettings;
            string actorSystemName = configManager["actorSystemName"];

            Console.Title = $"{actorSystemName} - Server";

            try
            {
                using (var actorSystem = ActorSystem.Create(actorSystemName))
                {
                    var server = actorSystem.ActorOf(
                        Props.Create<ServerActor>(), "ServerActor");

                    string serverActorAddress = configManager["serverActorAddress"];
                    var remoteServerActor = actorSystem.ActorSelection(serverActorAddress);

                    Console.ReadLine();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

In the server’s App.config, we need to use HOCON to set up Akka.Remote, mainly defining the port at which the server will listen:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="akka" type="Akka.Configuration.Hocon.AkkaConfigurationSection, Akka" />
  </configSections>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>

  <appSettings>
    <add key="actorSystemName" value="PubSubGame" />
  </appSettings>

  <akka>
    <hocon>
      <![CDATA[
        
        akka
        {
            actor
            {
                provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
            }

            remote 
            {
                helios.tcp
                {
                    port = 7482
                    hostname = localhost
                }
            }
        }
      
      ]]>
    </hocon>
  </akka>
</configuration>

Common Messages

The message classes in the class library project, “GameMessages”, are required by both client and server because they are the means by which basic publish/subscribe interactions occur.

    public class SubscribeMessage
    {
        public Guid SubscriberGuid { get; }

        public SubscribeMessage(Guid subscriberGuid)
        {
            this.SubscriberGuid = subscriberGuid;
        }
    }

The SubscribeMessage is sent by the client when it starts. Through it, the server sets up an association between SubscriberGuid and the client’s IActorRef (with a dictionary entry). Although this association is not needed for message broadcast, it is necessary to remove the subscriber with that GUID when he unsubscribes.

    public class UnsubscribeMessage
    {
        public Guid SubscriberGuid { get; }
        public short LastX { get; }
        public short LastY { get; }

        public UnsubscribeMessage(Guid subscriberGuid,
            short lastX, short lastY)
        {
            this.SubscriberGuid = subscriberGuid;
            this.LastX = lastX;
            this.LastY = lastY;
        }
    }

The UnsubscribeMessage could in most cases be just a subscriber GUID. However, for our game, we are also including the last position of the client in the game area when he left the game. In this way, the other clients can update their view of the playing area by removing the client that left.

    public class UpdateLocationMessage
    {
        public char Avatar { get; }
        public short OldX { get; }
        public short OldY { get; }
        public short NewX { get; }
        public short NewY { get; }

        public UpdateLocationMessage(Guid subscriberGuid,
            char avatar, short oldX, short oldY, short newX, short newY)
        {
            this.SubscriberGuid = subscriberGuid;
            this.Avatar = avatar;
            this.OldX = oldX;
            this.OldY = oldY;
            this.NewX = newX;
            this.NewY = newY;
        }
    }

On startup and whenever a client moves, he sends an UpdateLocationMessage. In our case, this includes the new location of the client, his previous location, and an arbitrary character representing that client (avatar). The clients receiving this update will erase the client from the previous location, and draw him in the new location using the provided avatar.

Client Overview

akka-multiplayer-pubsub2

The client application is split up into three components.

  1. The main program logic sets up the ActorSystem and handles input from the console.
  2. The GameClientActor is responsible for communicating with the server. It sends messages to the server as a result of input coming from the main program logic, but also receives updates from the server. In both cases, updates are forwarded to the GameRenderingActor so that they can be drawn on the playing area in the console.
  3. The GameRenderingActor draws the playing area in the console. It keeps this view up to date as a result of the messages it receives from the GameClientActor.

Client – Main Program Logic

The main program for the client first takes care of setting up the ActorSystem, together with a GameClientActor and a GameRendererActor:

        static void Main(string[] args)
        {
            var configManager = ConfigurationManager.AppSettings;
            string actorSystemName = configManager["actorSystemName"];
            char avatar = configManager["avatar"][0];

            Console.Title = $"{actorSystemName} - Client";
            Console.OutputEncoding = Encoding.UTF8;
            Console.CursorVisible = false;

            try
            {
                using (var actorSystem = ActorSystem.Create(actorSystemName))
                {
                    short currentX = 40;
                    short currentY = 12;
                    Guid subscriberGuid = Guid.NewGuid();

                    var gameRendererActor = actorSystem.ActorOf(
                        Props.Create<GameRenderingActor>(), "GameRenderingActor");

                    var gameClientActor = actorSystem.ActorOf(
                        Props.Create<GameClientActor>(gameRendererActor,
                            currentX, currentY, subscriberGuid, avatar),
                        "GameClientActor");

                    HandleInput(gameClientActor);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

Once the ActorSystem is set up, the client enters a game loop, which runs indefinitely until the ESC key is pressed or the client application is killed.

        static void HandleInput(IActorRef gameClientActor)
        {
            while (true)
            {
                var key = Console.ReadKey(intercept: true);

                switch (key.Key)
                {
                    case ConsoleKey.LeftArrow:
                        gameClientActor.Tell(new MoveLeftMessage());
                        break;
                    case ConsoleKey.RightArrow:
                        gameClientActor.Tell(new MoveRightMessage());
                        break;
                    case ConsoleKey.UpArrow:
                        gameClientActor.Tell(new MoveUpMessage());
                        break;
                    case ConsoleKey.DownArrow:
                        gameClientActor.Tell(new MoveDownMessage());
                        break;
                    case ConsoleKey.Escape:
                        gameClientActor.Tell(new QuitGameMessage());
                        return;
                }
            }
        }

Since what we have here is an IActorRef of the GameClientActor rather than a direct instance, we need to communicate with it by sending messages (as opposed to calling methods on it directly).

Each of the messages used by HandleInput() is an empty class, so they are not shown here for brevity.

Although these messages could go into the “GameMessages” shared class library, I opted to put them directly in the client project because the server does not need to know about them. I consider it good practice to keep classes only within the context in which they are needed, as I believe it minimises dependencies (and therefore coupling), though your mileage may vary.

Client – GameRenderingActor

The GameRenderingActor is capable of drawing the state of clients in the playing area by doing only one thing: drawing a single character at a given location in the console window.

    public class GameRenderingActor : TypedActor,
        IHandle<DrawMessage>,
        IHandle<EraseMessage>
    {
        public void Handle(DrawMessage message)
        {
            Console.SetCursorPosition(message.X, message.Y);
            Console.Write(message.Char);
        }

        public void Handle(EraseMessage eraseMessage)
        {
            var x = eraseMessage.X;
            var y = eraseMessage.Y;
            char @char = ' '; // overwrite with space to erase whatever is drawn

            var drawMessage = new DrawMessage(x, y, @char);
            Self.Tell(drawMessage);
        }
    }

As a matter of fact, it knows how to process an EraseMessage (to clear a client’s former position) and a DrawMessage (to draw a client’s current position). These messages include a position (X and Y), and DrawMessage also includes the character to draw (typically the client’s avatar).

The EraseMessage is translated into a DrawMessage (via a message to self) where the character to be drawn is a space. This effectively erases whatever was previously drawn.

In case you’re wondering, the ‘@’ symbol is used because char is a C# reserved word, and you can’t name a variable using a reserved word. The ‘@’ symbol allows you to work around this restriction.

Client – GameClientActor – Setup

The GameClientActor is relatively large because it maintains client state and at the same time coordinates between all the other components in the system (client main program, GameRenderingActor, and the server).

    public class GameClientActor : TypedActor,
        IHandle<UpdateLocationMessage>,
        IHandle<UnsubscribeMessage>,
        IHandle<MoveLeftMessage>,
        IHandle<MoveRightMessage>,
        IHandle<MoveUpMessage>,
        IHandle<MoveDownMessage>,
        IHandle<QuitGameMessage>
    {
        private IActorRef gameRenderingActor;
        private ActorSelection remoteServerActor;

        // client actor state
        private short currentX;
        private short currentY;
        private Guid subscriberGuid;
        private char avatar;

        public GameClientActor(IActorRef gameRenderingActor, short initialX,
            short initialY, Guid subscriberGuid, char avatar)
        {
            this.gameRenderingActor = gameRenderingActor;

            string serverActorAddress = ConfigurationManager
                .AppSettings["serverActorAddress"];
            this.remoteServerActor = Context.ActorSelection(serverActorAddress);

            this.currentX = initialX;
            this.currentY = initialY;
            this.subscriberGuid = subscriberGuid;
            this.avatar = avatar;

            this.Subscribe();
        }

//...

    }

The top of the class declaration makes it immediately evident what messages the GameClientActor is capable of processing (which is one of the reasons why I prefer the IHandle<> approach over ReceiveActors). These include movement/quit messages coming from user input from the main program logic, but also UpdateLocationMessages and UnsubscribeMessages coming from the server.

The constructor takes care of initialising client game state, based on what is passed in from the main program logic. However, the GameClientActor must also keep references to the other actors it talks to, i.e. the GameRenderingActor and the ServerActor running remotely on the server.

When all this state is set up, the client subscribes with the server and sends it an initial location update so that other clients may know it exists. These operations are done thanks to the following two helper methods:

        private void Subscribe()
        {
            // send subscribe message

            var subscribeMessage = new SubscribeMessage(subscriberGuid);
            remoteServerActor.Tell(subscribeMessage, Self);

            // send initial location

            SendLocationUpdate(0, 0);
        }

        private void SendLocationUpdate(short oldX, short oldY)
        {
            var updateLocationMessage = new UpdateLocationMessage(subscriberGuid,
                avatar, oldX, oldY, currentX, currentY);
            remoteServerActor.Tell(updateLocationMessage);
        }

Something very important to note here is that we’re including Self as a second parameter when sending the SubscribeMessage. That’s because of this code in the ServerActor:

        public void Handle(SubscribeMessage message)
        {
            this.subscribers[message.SubscriberGuid] = Sender;
        }

I’ve found that if you want to use a reference to Sender, you need to pass the sender as a second parameter when sending the original message. If you don’t, Sender defaults to some weird dead letter thingy. I don’t know if this is by design or some bug, but keep it in mind because it can bite you.

Client – Configuration

The client configuration is a little bit different from that of the server.

  <appSettings>
    <add key="avatar" value="X" />
    <add key="actorSystemName" value="PubSubGame" />
    <add key="serverActorAddress" value="akka.tcp://PubSubGame@localhost:7482/user/ServerActor" />
  </appSettings>

We can specify an avatar character that will be drawn to represent this client at its position. We will change this for each instance of the client that we run, so that we can distinguish between them.

We also need to set up the endpoint of the remote ServerActor in order to be able to communicate with it.

  <akka>
    <hocon>
      <![CDATA[
        
        akka
        {
            loglevel = ERROR
        
            actor
            {
                provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
            }

            remote 
            {
                helios.tcp
                {
                    port = 0
                    hostname = localhost
                }
            }
        }
      
      ]]>
    </hocon>
  </akka>

Client connections normally don’t need to be bound to a specific port. Instead, by setting the port to 0, we let the operating system give us an available port of its own choosing for the client socket. This is perfectly fine because client connections are outgoing; so unlike server sockets, they don’t need to listen for connections on a particular port, and are not subject to firewall restrictions.

Note that we’re setting loglevel pretty high here. That’s so the typical Akka .NET output doesn’t mess with our drawing of the playing area.

Client – GameClientActor – Movement

A lot of the movement code in GameClientActor is the same: keep a copy of the old position, update the state with the new position, and then send a location update to the server with both the old and the new position. Thus a common helper method is used:

        private void MoveAndSendLocationUpdate(Action move)
        {
            short oldX = currentX;
            short oldY = currentY;

            move();

            this.SendLocationUpdate(oldX, oldY);
        }

The move action is simply a tweak in the location state. It is different for each movement message, and thus passed in to the helper method:

        public void Handle(MoveLeftMessage message)
        {
            this.MoveAndSendLocationUpdate(() => currentX--);
        }

        public void Handle(MoveRightMessage message)
        {
            this.MoveAndSendLocationUpdate(() => currentX++);
        }

        public void Handle(MoveUpMessage message)
        {
            this.MoveAndSendLocationUpdate(() => currentY--);
        }

        public void Handle(MoveDownMessage message)
        {
            this.MoveAndSendLocationUpdate(() => currentY++);
        }

The QuitMessage is a special case, as we need to send an UnsubscribeMessage to the server instead:

        public void Handle(QuitGameMessage message)
        {
            short oldX = currentX;
            short oldY = currentY;

            var unsubscribeMessage = new UnsubscribeMessage(subscriberGuid,
                oldX, oldY);
            remoteServerActor.Tell(unsubscribeMessage);
        }

Client – GameClientActor – Messages from Server

When a location update is received from the server, the GameClientActor passes instructions to the GameRenderingActor to erase the old position of the client that sent the update, and redraw it at its new position:

        public void Handle(UpdateLocationMessage message)
        {
            var eraseMessage = new EraseMessage(message.OldX, message.OldY);
            var drawMessage = new DrawMessage(message.NewX, message.NewY,
                message.Avatar);

            this.gameRenderingActor.Tell(eraseMessage);
            this.gameRenderingActor.Tell(drawMessage);
        }

The UnsubscribeMessage is handled similarly, but erases the old position only:

        public void Handle(UnsubscribeMessage message)
        {
            var eraseMessage = new EraseMessage(message.LastX, message.LastY);

            this.gameRenderingActor.Tell(eraseMessage);
        }

Let’s Run It!

Run one instance of the server. Then, run as many client instances as you like, each with a different avatar configuration. Press the arrow keys in each client console window to move your clients a little. When you move an avatar, you will see it move in all the other windows as well.

pubsubgame-output

Possible Improvement

One thing you’ll notice is that when a new client joins, he won’t see the other clients until they have moved and broadcasted an update. This is a limitation of not keeping client state on the server, and there are many ways to fix this. It is left as an exercise.

Publish/Subscribe Explained

This article explains how the classic Publish/Subscribe (also known as Observer) Design Pattern works. It is a prerequisite for the next article, “Multiplayer Game with Akka .NET and Publish/Subscribe“.

The source code for this article is available at the Gigi Labs BitBucket Repository.

Publish/Subscribe

A pretty common situation in client/server scenarios is the need to synchronise state across a number of clients. A very simple example of this is a chat web application: one of the clients writes a message, and that message needs to be sent to all the other clients.

Polling is a simple but inefficient way to do this. It means that clients periodically ask the server for updates. This is wasteful because a lot of requests are sent just to check for updates (potentially there may be none at that time), and the server needs to deal with all of them.

A much better way is to use the Observer Design Pattern, less formally known as Publish/Subscribe. In this classical pattern, clients subscribe for updates; then the server spontaneously sends updates when there are any:

pubsub-overview

This means that clients receive updates pretty much in real-time, and traffic is mostly one-way from the server (as it needs to be).

Implementing Publish/Subscribe in any language is easy. Let’s start by looking only at the interfaces our components must implement.

    public interface ISubscriber
    {
        void Notify(string message);
    }

A subscriber needs only to provide a method that the publisher can call when propagating updates.

    public interface IPublisher
    {
        void Subscribe(ISubscriber subscriber);
        void NotifyAll(string message);
        void Unsubscribe(ISubscriber subscriber);
    }

A publisher provides subscribers with the means to subscribe and unsubscribe for updates. It also provides a method used to broadcast updates to all subscribers.

The publisher can do all this simply by maintaining a collection of subscribers:

    public class Publisher : IPublisher
    {
        private List<ISubscriber> subscribers;

        public Publisher()
        {
            this.subscribers = new List<ISubscriber>();
        }

        public void Subscribe(ISubscriber subscriber)
        {
            this.subscribers.Add(subscriber);
        }

        public void NotifyAll(string message)
        {
            foreach (var subscriber in this.subscribers)
                subscriber.Notify(message);
        }

        public void Unsubscribe(ISubscriber subscriber)
        {
            this.subscribers.Remove(subscriber);
        }
    }

Subscription and unsubscription are equivalent to addition and removal from the subscriber collection respectively. In order to broadcast updates, the publisher needs only to iterate over all subscribers and call the method they provide (in this case Notify()).

The subscriber will then receive the message and do something with it. For this simple example, we will just write it to the console. In order to distinguish between subscribers, we will also give them a locally stored GUID:

    public class Subscriber : ISubscriber
    {
        private Guid subscriberGuid;

        public Subscriber()
        {
            this.subscriberGuid = Guid.NewGuid();
        }

        public void Notify(string message)
        {
            Console.WriteLine($"{this.subscriberGuid} received: {message}");
        }
    }

We can now test this using a simple application such as the following:

        static void Main(string[] args)
        {
            var publisher = new Publisher();

            var subscriber1 = new Subscriber();
            var subscriber2 = new Subscriber();
            var subscriber3 = new Subscriber();

            publisher.Subscribe(subscriber1);
            publisher.Subscribe(subscriber2);

            publisher.NotifyAll("Hello!");

            publisher.Subscribe(subscriber3);
            publisher.Unsubscribe(subscriber1);

            publisher.NotifyAll("How are you?");

            Console.ReadLine();
        }

Here is what we get if we run this:

pubsub-example-output

As you can see, NotifyAll() propagates updates to those who are subscribed. Since subscriber3 subscribed late, he missed the “Hello!” update. And since subscriber1 unsubscribed, he missed the “How are you?” update.

Summary

Publish/Subscribe, also known as the Observer pattern, is very powerful. While polling requires continuous checks for updates against the server, Publish/Subscribe reverses this approach to allow direct push notifications from the server. This greatly reduces the number of requests that the server must handle, while at the same time allowing clients to receive updates in real-time.

This pattern is so important that it serves as the foundation for other programming techniques including event-driven programming, data binding, MVVM, real-time web, and more.

Bypassing a Login Form using SQL Injection

This article was originally posted as “C# Security: Bypassing a Login Form using SQL Injection” on 5th January 2014 at Programmer’s Ranch. The article is based on ASP .NET Web Forms and ADO .NET, and the code example was originally written using Visual Studio Express for Web 2013 and SQL Server 2012 Express. This updated version removes references to particular software versions, adds syntax highlighting, and includes other simple edits where necessary.

In this article, we’re going to learn about SQL injection. We’ll use it to bypass a login form on a website, and you’ll see just how easy it is. Despite its simplicity, this article is going to be a little bit long – because we’ll need to set up a simple login form with a database that we can then use to try out the SQL injection. Naturally, you should never try out these types of attacks on someone else’s website; so when you want to learn something in practice, set up a vulnerable system of your own.

To demonstrate SQL injection, we’re going to be using ASP .NET (for the web form) and SQL Server (for the database). However, SQL injection is not tied to any technology in particular, so you could, for example, use PHP and MySQL instead. You are expected to know a little something about databases (SQL) and websites, although rest assured that there’s nothing complicated in this article.

Setting up the database

sqlinj-newdatabase

In order to create and set up our database, we’ll need to use SQL Server Management Studio. Launch it, and from the Object Explorer on the left, right click on the Databases node, and click on “New Database…”. Enter a name for your database (I’m using “sqlinjection”) and click OK.

sqlinj-newquery

You should now be able to right click on the newly created database and select “New Query”. This brings up a text editor where you can enter and run queries against the database. Enter the following script into this editor:

create table users (
    id int not null primary key identity(1,1),
    username varchar(50) not null,
    password varchar(50) not null
);

…and press F5 to execute it:

sqlinj-createtable

You should now have your users table with an id field as well as the username and password. Now, replace the script with the following:

insert into users(username, password)
values('hankmarvin', 'theshadows');

Press F5 to insert a new row where the username is “hankmarvin” and the password is “theshadows”. The id column should be filled automatically since we are using an IDENTITY on that column. Note that in this case we’re storing a password as cleartext for simplicity, but this is never a good idea – see my article “Securing Passwords by Salting and Hashing” if you don’t know why.

Creating the login form

In Visual Studio, go on File -> New Website… and create a new project of type ASP .NET Empty Web Site:

sqlinj-newproject

Next, right click on the project in Solution Explorer, and select Add -> Add New Item…, and then pick Web Form from the list of templates. Leave the name as Default.aspx.

Set up the markup in Default.aspx so that it looks like this:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            Username: <asp:TextBox ID="usernameField" runat="server" />
        </div>
        <div>
            Password: <asp:TextBox ID="passwordField" runat="server" />
        </div>
        <div>
            <asp:Button ID="loginButton" runat="server" Text="Login" OnClick="loginButton_Click" />
        </div>
        <div>
            <asp:Label ID="resultField" runat="server" />
        </div>
    </form>
</body>
</html>

It’s not wonderful HTML, and not exactly pretty, but it’s the simple login form that we need. You can see the result by pressing F5 to launch the project in your web browser:

sqlinj-loginform

Next, go into your webpage’s codebehind file (that would be Default.aspx.cs). Add the following statement near the top:

using System.Data.SqlClient;

Add the following event handler that actually takes care of the logic for logging in (your actual connection string may vary depending on how you installed SQL Server – see this if you run into issues):

    protected void loginButton_Click(object sender, EventArgs e)
    {
        String connStr = @"Data Source=localhost\SqlExpress;Initial Catalog=sqlinjection;Integrated Security=True;";
        String username = this.usernameField.Text;
        String password = this.passwordField.Text;
        String query = "select count(*) from users where username = '" + username
            + "' and password = '" + password + "'";

        try
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();

                using (SqlCommand command = new SqlCommand(query, conn))
                {
                    int result = (int)command.ExecuteScalar();
                    if (result > 0)
                        resultField.Text = "Login successful.";
                    else
                        resultField.Text = "Login failed! Go away!";
                }
            }
        }
        catch(Exception ex)
        {
            resultField.Text = ex.Message;
        }
    }

SQL Injection

You can now press F5 and test out the login form. If you enter the correct credentials, which are “hankmarvin” for username and “theshadows” as the password, then you should see the message “Login successful.” just below the form. For any other input, the login will fail.

It should be pretty evident that the code in loginButton_Click is constructing dynamic SQL based on the credentials provided. So for the correct credentials, this would build the SQL string:

select count(*) from users where username = 'hankmarvin' and password = 'theshadows'

The weakness in this is that we can write whatever we want into the username and password fields, and they’ll be included in the SQL query. Let’s see what happens when we use the following input in the password field:

' OR 1=1 --

Using this, we are logged in just fine:

sqlinj-injected-sql

Oops! What just happened here? If we take a look at the dynamic SQL that is being constructed, it becomes clear:

select count(*) from users where username = '' and password = '' OR 1=1 --'

The stuff we entered in the password field is closing off the SQL string (with the apostrophe at the beginning) and is adding a condition that will always be true (1=1). A comment (–) at the end gets rid of the remaining SQL, in this case a closing apostrophe. The query’s WHERE clause can now be read as follows:

((username = '') AND (password = '')) OR 1=1

Well, it turns out that 1=1 is always true, so the query ends up returning every row in the database. The count is greater than zero, and so the login is successful, even though we didn’t actually provide valid credentials.

Prepared Statements

The correct way to fight SQL injection is to use prepared statements. This means that the event handler changes as follows:

    protected void loginButton_Click(object sender, EventArgs e)
    {
        String connStr = @"Data Source=localhost\SqlExpress;Initial Catalog=sqlinjection;Integrated Security=True;";
        String username = this.usernameField.Text;
        String password = this.passwordField.Text;
        String query = "select count(*) from users where username = @username and password = @password";

        try
        {
            using (SqlConnection conn = new SqlConnection(connStr))
            {
                conn.Open();

                using (SqlCommand command = new SqlCommand(query, conn))
                {
                    command.Parameters.Add(new SqlParameter("@username", username));
                    command.Parameters.Add(new SqlParameter("@password", password));

                    int result = (int)command.ExecuteScalar();
                    if (result > 0)
                        resultField.Text = "Login successful.";
                    else
                        resultField.Text = "Login failed! Go away!";
                }
            }
        }
        catch(Exception ex)
        {
            resultField.Text = ex.Message;
        }
    }

Instead of building dynamic SQL, we insert named placeholders, such as @username, to stand in for parameters in the query. We then provide these values via the SqlCommand‘s Parameters property, where the values are paired up with the corresponding parameter names. Since these parameters are strongly typed, things like escaping apostrophes in strings are handled automatically, and so users can’t inject SQL via input fields.

In fact, if you try the same SQL injection attack as above, you’ll see that it doesn’t work any more:

sqlinj-injection-failed

Summary

As we have seen in this article, SQL injection is a really simple technique that can be used to breach security in vulnerable websites and applications. Bypassing login forms is only one of many things you can do with SQL injection, which is so dangerous that it has topped the OWASP Top 10 Risks for years.

To protect against SQL injection, use prepared statements to provide strongly-typed parameters in your SQL queries, and avoid dynamic SQL built directly by concatenating strings.

Securing Passwords by Salting and Hashing

This article was originally posted as “C# Security: Securing Passwords by Salting and Hashing” on 11th November 2013 at Programmer’s Ranch. This republished version is slightly edited. Although using silly passwords and the MD5 hash function is not recommended, they are used in this article to illustrate the point more easily.

Password security is often quite challenging to understand for those who are new to it (I’ve been there too, as you can see from my question about salting on StackOverflow). In this article, I am hoping to make this fascinating topic a little easier to understand. We’ll be covering two important techniques called hashing and salting. Although passwords are typically stored in a database, we’ll be using a C# dictionary to keep it simple.

Clear Text Passwords

To get started, create a new Console Application. Add the following near the top, so that we can use dictionaries:

using System.Collections.Generic;

Just inside your class Program, before your Main() method, add the following dictionary to store our users and their corresponding passwords (see “Morse Code Converter Using Dictionaries” if this seems in any way new to you):

        public static Dictionary<string, string> users = new Dictionary<string, string>()
        {
            { "johnny", "password" },
            { "mary", "flowers" },
            { "chuck", "roundhousekick" },
            { "larry", "password123" }
        };

It is now pretty simple to add a method that can check whether a given username and password result in a successful login:

        public static bool Login(string username, string password)
        {
            if (users.ContainsKey(username) && users[username] == password)
                return true;
            else
                return false;
        }

This code first checks that the username actually exists in the dictionary, and then checks whether the corresponding password matches.

We can now test this code by replacing the contents of Main() with the following code:

        public static void Main(string[] args)
        {
            Console.Write("Username: ");
            string username = Console.ReadLine();
          
            Console.Write("Password: ");
            Console.ForegroundColor = ConsoleColor.Black;
            string password = Console.ReadLine();
            Console.ResetColor();
          
            bool loggedIn = Login(username, password);
            if (loggedIn)
                Console.WriteLine("You have successfully logged in!");
            else
                Console.WriteLine("Bugger off!");
          
            Console.ReadLine();
        }

Notice that when requesting the password, we’re setting the console’s text colour to black. The console’s background colour is also black, so the password won’t show as you type, fending off people trying to spy it while looking over your shoulder.

Press F5 to try it out:

cspwsec-naive-output

Awesome – we have just written a very simple login system.

The problem with this system is that the passwords are stored as clear text. If we imagine for a moment that our usernames and passwords were stored in a database, then the actual passwords can easily be obtained by a hacker gaining illegal access to the database, or any administrator with access to the database. We can see this by writing a simple method that shows the users’ data, simulating what a hacker would see if he managed to breach the database:

        public static void Hack()
        {
            foreach (string username in users.Keys)
                Console.WriteLine("{0}: {1}", username, users[username]);
        }

We can then add the following code just before the final Console.ReadLine() in Main() to test it out:

Console.WriteLine();
Hack();

This gives us all the details, as we are expecting:

cspwsec-breach-cleartext

This isn’t a nice thing to have – anyone who can somehow gain access to the database can see the passwords. How can we make this better?

Hashing

One way is to hash the passwords. A hash function is something that takes a piece of text and transforms it into another piece of text:

cspwsec-hashfunc-1

A hash function is one-way in the sense that you can use it to transform “Hello” to “8b1a9953c4611296a827abf8c47804d7”, but not the other way around. So if someone gets his hands on the hash of a password, it doesn’t mean that he has the password.

Another property of hash functions is that their output changes considerably even with a very small change in the input. Take a look at the following, for instance:

cspwsec-hashfunc-2

You can see how “8b1a9953c4611296a827abf8c47804d7” is very different from “5d41402abc4b2a76b9719d911017c592”. The hashes bear no relationship with each other, even though the passwords are almost identical. This means that a hacker won’t be able to notice patterns in the hashes that might allow him to guess one password based on another.

One popular hashing algorithm (though not the most secure) is MD5, which was used to produce the examples above. You can find online tools (such as this one) that allow you to compute an MD5 hash for any string you want.

In order to use MD5 in our code, we’ll need to add the following statement near the top of our program code:

using System.Security.Cryptography;

At the beginning of the Program class, we can now create an instance of the MD5 class to use whenever we need:

private static MD5 hashFunction = MD5.Create();

If you look at the intellisense for MD5, you’ll see that it has a ComputeHash() method, which returns an byte array, rather than a string:

cspwsec-md5-computehash

We’re going to do some string work, so add the following near the top:

using System.Text;

Let’s write a little helper method to hash our passwords, using strings for both input and output:

        public static string Hash(String input)
        {
            // code goes here
        }

In this method, the first thing we need to do is convert the input string to a byte array, so that ComputeHash() can work with it. This is done using the System.Text.Encoding class, which provides several useful members for converting between strings and bytes. In our case we can work with the ASCII encoding as follows:

byte[] inputBytes = Encoding.ASCII.GetBytes(input);

We can then compute the hash itself:

byte[] hashBytes = hashFunction.ComputeHash(inputBytes);

Since we don’t like working with raw bytes, we then convert it to a hexadecimal string:

StringBuilder sb = new StringBuilder();
foreach(byte b in hashBytes)
sb.Append(b.ToString("x2").ToLower());

The “x2” bit converts each byte into two hexadecimal characters. If you think about it for a moment, hexadecimal digits are from 0 to f (representing 0-15 in decimal), which fit into four bits. But each byte is eight bits, so each byte is made up of two hex digits.

Anyway, after that, all we need to do is return the string, so here’s the entire code for the method:

        public static String Hash(String input)
        {
            byte[] inputBytes = Encoding.ASCII.GetBytes(input);
            byte[] hashBytes = hashFunction.ComputeHash(inputBytes);
          
            StringBuilder sb = new StringBuilder();
            foreach(byte b in hashBytes)
                sb.Append(b.ToString("x2").ToLower());
          
            return sb.ToString();
        }

We can now change our database to use hashed passwords:

        public static Dictionary<string, string> users = new Dictionary<string, string>()
        {
            { "johnny", Hash("password") },
            { "mary", Hash("flowers") },
            { "chuck", Hash("roundhousekick") },
            { "larry", Hash("password123") }
        };

In this way, we aren’t storing the passwords themselves, but their hashes. For example, we’re storing “5f4dcc3b5aa765d61d8327deb882cf99” instead of “password”. That means we don’t store the password itself any more (if you ever signed up to an internet forum or something, and it told you that your password can be reset but not recovered, you now know why). However, we can hash any input password and compare the hashes.

In our Login() method, we now change the line that checks username and password as follows:

if (users.ContainsKey(username) && users[username] == Hash(password))

Let’s try this out (F5):

cspwsec-hash-output

When the user types “johnny” as the username and “password” as the password, the password is hashed, giving us “5f4dcc3b5aa765d61d8327deb882cf99”. Since the passwords were also stored as hashes in our database, it matches. In reality our login is doing the same thing as it was doing before – just that we added a hash step (a) when storing our passwords and (b) when receiving a password as input. Ultimately the password in our database and that entered by the user both end up being hashes, and will match if the actual password was the same.

How does this help us? As you can see from the hack output (last four lines in the screenshot above), someone who manages to breach the database cannot see the passwords; he can only get to the hashes. He can’t login using a hash, since that will in turn be hashed, producing a completely different value that won’t match the hash in the database.

Although hashing won’t make the system 100% secure, it’s sure to give any potential hacker a hard time.

Salting

You may have noticed that in the example I used, I had some pretty dumb passwords, such as “password” and “password123”. Using a dictionary word such as “flowers” is also not a very good idea. Someone may be able to gain access to one of the accounts by attempting several common passwords such as “password”. These attempts can be automated by simple programs, allowing hackers to attempt entire dictionaries of words as passwords in a relatively short period of time.

Likewise, if you know the hash for common passwords (e.g. “5f4dcc3b5aa765d61d8327deb882cf99” is the hash for “password”), it becomes easy to recognise such passwords when you see the expected hash. Hackers can generate dictionaries of hashes for common passwords, known as rainbow tables, and find hashes for common words used as passwords.

We can combat such attacks by a process known as salting. When we compute our hashes, we add some string that we invent. This means changing the first line of our Hash() function as follows:

byte[] inputBytes = Encoding.ASCII.GetBytes("chuck" + input);

Both the database password and the one entered by the user will be a hash of “chuck” concatenated with the password itself. When the user tries to login, it will still work, but look at what happens now:

cspwsec-salt-output

The login worked, but the hashes have changed because of the salt! This means that even for a password as common as “password”, a hacker cannot identify it from the hash, making rainbow tables much less effective.

Summary

This article described how to store passwords securely. It started off by doing the easiest and worst thing you can do: store them as clear text. A hash function was subsequently introduced, to transform the passwords into text from which the password cannot be retrieved. When a user logs in, the hash of the password he enters is compared with the password hash stored in the database.

Finally, the hashes were salted, by adding an arbitrary piece of text to them, in order to transform the hashes into different values that can’t be used to identify common passwords.

Additional Notes

It is interesting to note that with hashes, it does not matter how long your password is. The hash is typically fixed-length (depending on the hash function you use). So if you create an account on some airline’s website and it tells you that your password is too long because they have some maximum limit… well, they don’t know what they are doing.

Hashing and salting make password storage a lot more secure. The next level is using a slow hash algorithm with a work function. You can read about this in my followup article, “Secure Authentication with BCrypt“.

"You don't learn to walk by following rules. You learn by doing, and by falling over." — Richard Branson