コード例 #1
0
 private static void SendServerHandshake(ServerHandshake handshake, Context context)
 {
     // generate a byte array representation of the handshake including the answer to the challenge
     string temp = handshake.ToString();
     byte[] handshakeBytes = Encoding.UTF8.GetBytes(temp);
     context.UserContext.Send(handshakeBytes, true);
 }
コード例 #2
0
 /// <summary>
 /// Handles the request.
 /// </summary>
 /// <param name="context">The user context.</param>
 public override void HandleRequest(Context context)
 {
     context.FrameReader.Append(context.Buffer, context.ReceivedByteCount);
     foreach (var frameData in context.FrameReader.ReadFrames())
     {
         if (frameData.OpCode == WebSocketOpCode.Ping)
         {
             frameData.OpCode = WebSocketOpCode.Pong;
             context.UserContext.Send(frameData);
             continue;
         }
         if (frameData.OpCode == WebSocketOpCode.Pong)
             continue;
         if (frameData.OpCode == WebSocketOpCode.Close)
         {
             context.UserContext.Send(DataFrame.CloseResponseFrame, true);
             continue;
         }
         context.UserContext.OnReceive(frameData);
     }
 }
コード例 #3
0
        public bool Authenticate(Context ctx)
        {
            var context = (ServerContext)ctx;

            if (context.ReceivedByteCount > 8)
            {
                var handshake = new ClientHandshake(context.Header);
                // See if our header had the required information
                if (handshake.IsValid())
                {
                    var origin = context.Server.Origin;
                    // Optionally check Origin and Location if they're set.
                    if (!String.IsNullOrEmpty(origin))
                    {
                        var expectedOrigin = origin;
                        if (!origin.Contains("://"))
                        {
                            expectedOrigin = "http://" + origin;
                        }

                        if (!handshake.Origin.Equals(expectedOrigin, StringComparison.InvariantCultureIgnoreCase))
                            return (false);
                    }

                    var destination = context.Server.Destination;

                    if (!String.IsNullOrEmpty(destination))
                    {
                        if (handshake.Host != destination + ":" + context.Server.Port)
                            return (false);
                    }
                    // Generate response handshake for the client
                    var serverShake = GenerateResponseHandshake(handshake, context.Server);
                    // Send the response handshake
                    SendServerHandshake(serverShake, context);
                    return (true);
                }
            }
            return (false);
        }
コード例 #4
0
        /// <summary>
        /// Processes the header.
        /// </summary>
        /// <param name="context">The user context.</param>
        public void ProcessHeader(Context context)
        {
            var serverContext = (ServerContext)context;

            // Find two line-breaks
            var buffer = context.Buffer;
            var bytesRead = context.ReceivedByteCount;
            var originalSize = context.HeaderStream.Length;

            var headerEnd = FindHeaderEnd(buffer);
            if (headerEnd < 0) // Didn't finish reading header; wait for next reader
            {
                context.HeaderStream.Write(buffer, 0, bytesRead);
                return;
            }

            context.HeaderStream.Write(buffer, 0, headerEnd);
            var headerBuffer = context.HeaderStream.ToArray();

            var headerBytesInBuffer = headerBuffer.Length - originalSize;
            var extraBytes = bytesRead - (headerBytesInBuffer);

            string data = Encoding.UTF8.GetString(headerBuffer, 0, headerBuffer.Length);
            //Check first to see if this is a flash socket XML request.
            if (data == "<policy-file-request/>\0")
            {
                //if it is, we access the Access Policy Server instance to send the appropriate response.
                serverContext.Server.AccessPolicyServer.SendResponse(context.Connection);
            }
            else //If it isn't, process http/websocket header as normal.
            {
                context.Header = new Header(data);
                switch (context.Header.Protocol)
                {
                    case Protocol.WebSocketRFC6455:
                        context.Handler = HandlerBase.GetHandler<WebSocket.rfc6455.Handler>();
                        context.FrameReader = new WebSocket.rfc6455.DataFrameReaderRfc6455();
                        break;
                    default:
                        context.Header.Protocol = Protocol.None;
                        break;
                }
                if (context.Header.Protocol == Protocol.None)
                {
                    context.UserContext.Send(Response.NotImplemented, true);
                    context.Stop();
                }

                if (context.Handler.Authentication.Authenticate(context))
                {
                    context.UserContext.OnConnected();

                    if (extraBytes > 0)
                    {
                        var extraBytesBuffer = new byte[extraBytes];
                        Array.Copy(context.Buffer, headerBytesInBuffer, extraBytesBuffer, 0, extraBytes);
                        context.ReceivedByteCount = (int)extraBytes;
                        context.Handler.HandleRequest(context);
                    }
                }
                else
                {
                    context.Stop();
                }
            }
        }
コード例 #5
0
 /// <summary>
 /// Handles the initial request.
 /// Attempts to process the header that should have been sent.
 /// </summary>
 /// <param name="context">The user context.</param>
 public override void HandleRequest(Context context)
 {
     ProcessHeader(context);
 }
コード例 #6
0
 public abstract void HandleRequest(Context context);
コード例 #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UserContext"/> class.
 /// </summary>
 /// <param name="context">The user context.</param>
 internal UserContext(Context context)
 {
     Context = context;
 }
コード例 #8
0
 private void StartContext(Context context)
 {
     SendHeader();
     BeginReceive(context);
 }
コード例 #9
0
        private void ProcessData(Context context)
        {
            if (state == WebSocketClientState.Handshaking)
            {
                // Assuming we've read the whole response, and that this response has no payload
                // Definitely not gaurenteed to be true
                var someBytes = new byte[context.ReceivedByteCount];
                Array.Copy(context.Buffer, someBytes, context.ReceivedByteCount);
                var authenticated = CheckAuthenticationResponse(someBytes);
                frameReader = new DataFrameReaderRfc6455();

                if (!authenticated)
                {
                    Disconnect();
                }
                else
                {
                    state = WebSocketClientState.Open;
                    context.UserContext.OnConnected();
                }
            }
            else
            {
                Debug.Assert(state == WebSocketClientState.Open);
                frameReader.Append(context.Buffer, context.ReceivedByteCount);
                foreach (var frameData in frameReader.ReadFrames())
                    context.UserContext.OnReceive(frameData);
            }
        }
コード例 #10
0
        private void BeginReceive(Context context)
        {
            var args = new SocketAsyncEventArgs { UserToken = context };
            args.Completed += DataReceivedHandler;
            args.SetBuffer(context.Buffer, 0, context.Buffer.Length);

            if (!context.Connection.Client.ReceiveAsync(args))
                DataReceivedHandler(context.Connection.Client, args);
        }
コード例 #11
0
        /// <summary>
        /// Begin connecting to a WebSocket server. Upon returning from this method, the server
        /// will be in the Handshaking state. This means the client is waiting for the handshake
        /// response from the server. Messages may not be sent until the OnConnected event has fired.
        /// </summary>
        public void BeginConnect()
        {
            if (state != WebSocketClientState.Closed)
                throw new InvalidOperationException();

            try
            {
                state = WebSocketClientState.Connecting;

                client = new TcpClient();
                client.Connect(host, port);

                state = WebSocketClientState.Handshaking;

                context = CreateContext();
                StartContext(context);
            }
            catch (Exception e)
            {
                state = WebSocketClientState.Closed;
                throw e;
            }
        }
コード例 #12
0
 private void OnSocketClose(Context c)
 {
     c.UserContext.OnDisconnect();
     c.Connection.Close();
 }
コード例 #13
0
        private void BeginReceive(Context context)
        {
            try
            {
                var args = new SocketAsyncEventArgs { UserToken = context };
                args.Completed += SocketReceiveHandler;
                args.SetBuffer(context.Buffer, 0, context.Buffer.Length);

                bool completedSyncronusly = !context.Connection.Client.ReceiveAsync(args);
                if (completedSyncronusly)
                    SocketReceiveHandler(context.Connection.Client, args);
            }
            catch (SocketException)
            {
                OnSocketClose(context);
            }
        }