public static bool CheckHandshake(Context context)
        {
            if(context.ReceivedByteCount > 8)
            {
                var AHandshake = new ClientHandshake(context.Header);

                // See if our header had the required information
                if (AHandshake.IsValid())
                {
                    // Optionally check Origin and Location if they're set.
                    if (Origin != string.Empty &&
                        AHandshake.Origin != "http://" + Origin)
                    {
                        return false;
                    }

                    if (Location != string.Empty &&
                        AHandshake.Host != string.Format("{0}:{1}", Location, context.Server.Port))
                    {
                        return false;
                    }

                    // Generate response handshake for the client
                    var serverShake = GenerateResponseHandshake(AHandshake);

                    // Send the response handshake
                    SendServerHandshake(serverShake, context);

                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// Sends the specified data.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="context">The user context.</param>
        /// <param name="close">if set to <c>true</c> [close].</param>
        public override void Send(byte[] data, Context context, bool close = false)
        {
            AsyncCallback ACallback = EndSend;

            if (close)
            {
                ACallback = EndSendAndClose;
            }

            context.SendReady.Wait();

            try
            {
                context.Connection.Client.BeginSend(data, 0, data.Length, SocketFlags.None, ACallback, context);
            }
            catch
            {
                context.SendReady.Release();
            }
        }
        /// <summary>
        /// Processes the header.
        /// </summary>
        /// <param name="context">The user context.</param>
        public void ProcessHeader(Context context)
        {
            string data = context.UserContext.Encoding.GetString(context.Buffer, 0, context.ReceivedByteCount);

            //Check first to see if this is a flash socket XML request.
            if (data == "<policy-file-request/>\0")
            {
                try
                {
                    //if it is, we access the Access Policy Server instance to send the appropriate response.
                    context.Server.AccessPolicyServer.SendResponse(context.Connection);
                }
                catch {}

                context.Dispose();
            }
            else//If it isn't, process http/websocket header as normal.
            {
                context.Header = new Header(data);

                switch (context.Header.Protocol)
                {
                    case Protocol.WebSocket:
                        context.Handler = WebSocketHandler.Instance;

                        break;
                    case Protocol.FlashSocket:
                        context.Handler = WebSocketHandler.Instance;

                        break;
                    default:
                        context.Header.Protocol = Protocol.None;

                        break;
                }

                if (context.Header.Protocol != Protocol.None)
                {
                    context.Handler.HandleRequest(context);
                }
                else
                {
                    context.UserContext.Send(Response.NotImplemented, true);
                }
            }
        }
 /// <summary>
 /// Handles the initial request.
 /// Attempts to process the header that should have been sent.
 /// Otherwise, through magic and wizardry, the client gets disconnected.
 /// </summary>
 /// <param name="context">The user context.</param>
 public override void HandleRequest(Context context)
 {
     if (context.IsSetup)
     {
         context.Dispose();
     }
     else
     {
         ProcessHeader(context);
     }
 }
 public abstract void Send(byte[] data, Context context, bool close = false);
 public abstract void HandleRequest(Context request);
        /// <summary>
        /// Runs the client.
        /// Sets up the UserContext.
        /// Executes in it's own thread.
        /// Utilizes a semaphore(ReceiveReady) to limit the number of receive events active for this client to 1 at a time.
        /// </summary>
        /// <param name="result">The A result.</param>
        private void RunClient(IAsyncResult result)
        {
            TcpClient connection = null;

            try
            {
                if (_listener != null)
                {
                    connection = _listener.EndAcceptTcpClient(result);
                }
            }
            catch (Exception e)
            {
                Log.Debug("Connect failed", e);
            }

            _connectReady.Release();

            if (connection == null)
            {
                return;
            }

            _clientLock.Wait();
            ClientCount++;
            _clientLock.Release();

            using (var context = new Context())
            {
                context.Server = this;
                context.Connection = connection;
                context.BufferSize = DefaultBufferSize;

                context.UserContext.ClientAddress = context.Connection.Client.RemoteEndPoint;

                context.UserContext.SetOnConnect(DefaultOnConnect);
                context.UserContext.SetOnDisconnect(DefaultOnDisconnect);
                context.UserContext.SetOnSend(DefaultOnSend);
                context.UserContext.SetOnReceive(DefaultOnReceive);

                context.UserContext.OnConnect();

                try
                {
                    while (context.Connection.Connected)
                    {
                        if (context.ReceiveReady.Wait(TimeOut))
                        {
                            context.Connection.Client.BeginReceive(context.Buffer, 0, context.Buffer.Length, SocketFlags.None, DoReceive, context);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Debug("Client Forcefully Disconnected", e);
                }
            }

            _clientLock.Wait();
            ClientCount--;
            _clientLock.Release();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="UserContext"/> class.
        /// </summary>
        /// <param name="context">The user context.</param>
        public UserContext(Context context)
        {
            _context = context;

            Header = _context.Header;
        }
        private static void SendServerHandshake(ServerHandshake aHandshake, Context context)
        {
            // generate a byte array representation of the handshake including the answer to the challenge
            byte[] handshakeBytes = context.UserContext.Encoding.GetBytes(aHandshake.ToString());

            context.UserContext.SendRaw(handshakeBytes);
        }
 /// <summary>
 /// Attempts to authenticates the specified user context.
 /// If authentication fails it kills the connection.
 /// </summary>
 /// <param name="context">The user context.</param>
 private void Authenticate(Context context)
 {
     if (WebSocketAuthentication.CheckHandshake(context))
     {
         context.UserContext.Protocol = context.Header.Protocol;
         context.UserContext.RequestPath = context.Header.RequestPath;
         context.Header = null;
         context.IsSetup = true;
     }
     else
     {
         context.Dispose();
     }
 }
        /// <summary>
        /// Sends the specified data.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="context">The user context.</param>
        /// <param name="close">if set to <c>true</c> [close].</param>
        public override void Send(byte[] data, Context context, bool close = false)
        {
            var dataFrameBytes = new DataFrame(data).ToBytes();

            AsyncCallback aCallback = EndSend;

            if (close)
            {
                aCallback = EndSendAndClose;
            }

            context.SendReady.Wait();

            try
            {
                context.Connection.Client.BeginSend(dataFrameBytes, 0, dataFrameBytes.Length, SocketFlags.None, aCallback, context);
            }
            catch
            {
                context.SendReady.Release();
            }
        }
        /// <summary>
        /// Handles the request.
        /// </summary>
        /// <param name="context">The user context.</param>
        public override void HandleRequest(Context context)
        {
            if (context.IsSetup)
            {
                context.UserContext.DataFrame.Append(context.Buffer, context.ReceivedByteCount);

                if (context.UserContext.DataFrame.State == DataFrame.DataState.Complete)
                {
                    context.UserContext.OnReceive();
                }
            }
            else
            {
                Authenticate(context);
            }
        }