private async void ConnectCallback(IAsyncResult ar)
        {
            var client = ar.AsyncState as TcpClient;

            try
            {
                if (client != _serverClient)
                {
                    throw new Exception("TcpClient Mismatch");
                }

                client.EndConnect(ar);
                Debug.Log("Authenticating with server");

                using (var networkStream = client.GetStream())
                {
                    await PerformHail(networkStream);

                    var        buffer        = new byte[1024];
                    NetMessage dataBuffer    = null;
                    var        bufferSize    = 0;
                    var        lengthBuffer  = new byte[2];
                    var        bytesReceived = 0;
                    int        readBytes;


                    var authMessages = new Queue <NetMessage>();
                    while (!_shutdownQueued)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length);

                        if (readBytes > 0)
                        {
                            var readMessage = NetMessage.GetMessages(buffer, readBytes, ref bytesReceived,
                                                                     ref dataBuffer, ref lengthBuffer, ref bufferSize, authMessages.Enqueue);
                            if (readMessage >= 1)
                            {
                                break;
                            }
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }

                    if (authMessages.Count == 0)
                    {
                        throw new Exception("Could not read auth result");
                    }
                    var authMsg = authMessages.Dequeue();

                    var auth = authMsg.ReadBoolean();
                    authMsg.ReadPadBits();
                    if (!auth)
                    {
                        string reason;
                        if (!authMsg.ReadString(out reason))
                        {
                            reason = "Not authorized";
                        }
                        Debug.LogError("Could not connect to server. {0}", reason);
                        ServerStatus = ConnectionStatus.FailedToConnect;
                        ServerStatusChanged.TryRaise(Debug.Logger);
                        return;
                    }
                    Guid guid;
                    if (!authMsg.ReadGuid(out guid))
                    {
                        throw new Exception("Could not read room guid");
                    }

                    RoomId = guid;
                    Debug.Log("Connected to dispatcher. Id is {0}", RoomId);
                    Server = new Server(this)
                    {
                        NetworkStream = networkStream, TcpClient = client
                    };
                    ServerStatus = ConnectionStatus.Connected;
                    ServerStatusChanged.TryRaise(Debug.Logger);

                    //and drain the rest of messages that might have come after the auth
                    while (authMessages.Count > 0)
                    {
                        EnqueueMessage(authMessages.Dequeue());
                    }

                    while (!_shutdownQueued)
                    {
                        readBytes = await networkStream.ReadAsync(buffer, 0, buffer.Length);

                        if (readBytes > 0)
                        {
                            NetMessage.GetMessages(buffer, readBytes, ref bytesReceived, ref dataBuffer,
                                                   ref lengthBuffer, ref bufferSize, EnqueueMessage);
                        }
                        if (!client.Connected)
                        {
                            return;
                        }
                    }
                }
            }
            catch (ObjectDisposedException ode)
            {
                if (!_shutdownQueued)
                {
                    Debug.LogException(ode, "{0} disposed when it shouldn't have", ode.ObjectName);
                }
            }
            catch (IOException ioe)
            {
                if (!(ioe.InnerException is SocketException))
                {
                    Debug.LogException(ioe);
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
            finally
            {
                if (client != null)
                {
                    client.Close();
                }
                ServerStatus = ConnectionStatus.Disconnected;
                ServerStatusChanged.TryRaise(Debug.Logger);
            }
        }