Beispiel #1
0
        void commandReceived(Model.Commands.Command c)
        {
            if (c is Model.Commands.PrivateChatCommand)
            {
                Model.Commands.PrivateChatCommand chat = (Model.Commands.PrivateChatCommand)c;

                foreach (string s in chat.content.Split('\n'))
                {
                    string w = DateTime.Now.ToShortTimeString() + " " + p.username + ": " + s;
                    try
                    {
                        if (this.InvokeRequired)
                        {
                            this.Invoke(new Action(delegate() { addLine(w); }));
                        }
                        else
                        {
                            addLine(w);
                        }
                    }
                    catch (InvalidOperationException)
                    {
                    }
                }
            }
            if (c is Model.Commands.FileListing)
            {
                Model.Commands.FileListing f = (Model.Commands.FileListing)c;
                lastFileListing = f;
                if (f.path == currentPath)
                {
                    try
                    {
                        if (this.InvokeRequired)
                        {
                            this.Invoke(new Action(delegate() { doUpdate(f); }));
                        }
                        else
                        {
                            doUpdate(f);
                        }
                    }
                    catch (InvalidOperationException)
                    {
                    }
                }
            }
        }
        /// <summary>
        /// An asynchroneous method for a WebSocket request processing
        /// </summary>
        /// <param name="listenerContext">Listener context</param>
        private async void ProcessWebSocketRequestAsync(HttpListenerContext listenerContext)
        {
            // Accepting WebSocket connection from the context
            WebSocketContext webSocketContext;

            try
            {
                webSocketContext = await listenerContext.AcceptWebSocketAsync(subProtocol : null);
            }
            catch (Exception e)
            {
                // The upgrade process failed somehow. For simplicity lets assume it was a failure on the part of the server and indicate this using 500.
                listenerContext.Response.StatusCode = 500;
                listenerContext.Response.Close();
                Logger.LogError(String.Format("Exception: {0}", e));
                return;
            }

            // This is our new WebSocket object
            WebSocket webSocket = webSocketContext.WebSocket;

            lock (socketsAndMessagesLock)
            {
                // Adding the new client to the list
                connectedSockets.Add(webSocket);

                // Sending all the previous messages to the new client
                Logger.Log("Sending " + cabinetController.Cards.Count + " old cards to the new client");
                foreach (var oldCard in cabinetController.Cards)
                {
                    // Making an add_card command for the selected card
                    var addCommand     = new Model.Commands.UpdateCardCommand(oldCard.Key, oldCard.Value);
                    var addCommandGram = new TextWebSockGram(serializer.SerializeCommand(addCommand));

                    // Sending the command to the new client
                    addCommandGram.Send(webSocket).Wait();
                }
            }

            // We are expecting a command to be sent from  the client
            Expecting expecting = Expecting.Command;

            // Here the received command will be held if we will be waiting for an appended binary data
            Model.Commands.Command receivedCommand = null;

            // The received WebSocket message collector
            WebSockGram receivedGram = null;

            // Communicating
            try
            {
                byte[] receiveBuffer = new byte[16384];

                // While the WebSocket connection remains open run a simple loop that receives data and sends it back.
                while (webSocket.State == WebSocketState.Open)
                {
                    WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), CancellationToken.None);

                    if (receiveResult.MessageType == WebSocketMessageType.Close)
                    {
                        // We've got a Close request. Sending it back
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
                    }
                    else
                    {
                        // We have received a message. Text or binary. We are going to collect it to the WebSockGram object

                        if (receivedGram == null)
                        {
                            // Start building of a new message
                            receivedGram = WebSockGram.StartReceivingFromReceiveResult(receiveBuffer, receiveResult);
                        }
                        else
                        {
                            // Continue building of the message
                            receivedGram.AppendFromReceiveResult(receiveBuffer, receiveResult);
                        }

                        // If the message has just ended, let's interpret it
                        if (receivedGram.Completed)
                        {
                            // Logging the message
                            if (receivedGram is TextWebSockGram)
                            {
                                Logger.Log("Received text: \"" + receivedGram.ToString() + "\"");
                            }
                            else if (receivedGram is BinaryWebSockGram)
                            {
                                Logger.Log("Received binary: " + receivedGram.Length + " bytes");
                            }
                            else
                            {
                                throw new Exception("Invalid case");
                            }

                            // Checking what we have received (depending on what we have been expecting)
                            if (expecting == Expecting.Command)
                            {
                                // We are expecting a command. So receivedGram has to be a text
                                if (receivedGram is TextWebSockGram)
                                {
                                    var command = serializer.DeserializeCommand(receivedGram.ToString());

                                    // Executing the received command
                                    if (command is Model.Commands.UpdateCardCommand)
                                    {
                                        var updateCardCommand = command as Model.Commands.UpdateCardCommand;

                                        lock (socketsAndMessagesLock)
                                        {
                                            // Giving the received message to the controller
                                            cabinetController.UpdateCard(updateCardCommand.Id, updateCardCommand.Value);

                                            // Broadcasting the message
                                            Logger.Log("Broadcasting the new card " + updateCardCommand.Value + " to the " + connectedSockets.Count + " connected clients");
                                            receivedGram.Broadcast(connectedSockets).Wait();
                                        }
                                    }
                                    else if (command is Model.Commands.UploadImageCardCommand)
                                    {
                                        // After this command a binary should be appended (containing the image data).
                                        // So we are saving the command itself...
                                        receivedCommand = command;

                                        // ...and setting the state machine to expect binary appended to the command.
                                        expecting = Expecting.AppendedBinary;
                                    }
                                    else if (command is Model.Commands.ListCardIDsCommand)
                                    {
                                        // Sending all the cards ids
                                        IList <string> ids = cabinetController.ListCardIDs();
                                        Model.Commands.ListCardIDsCommand response = new Model.Commands.ListCardIDsCommand(ids);
                                        var         ser     = serializer.SerializeCommand(response);
                                        WebSockGram listids = new TextWebSockGram(ser);
                                        await listids.Send(webSocket);
                                    }
                                }
                                else
                                {
                                    throw new Exception("We are expecting a command, but the received WebSocket message isn't a text");
                                }
                            }
                            else if (expecting == Expecting.AppendedBinary)
                            {
                                // We are expecting an appended binary
                                if (receivedGram is BinaryWebSockGram)
                                {
                                    // We've got an appended binary
                                    if (receivedCommand is Model.Commands.UploadImageCardCommand)
                                    {
                                        // Our current command is upload_image_card
                                        var uploadImageMessageCommand = receivedCommand as Model.Commands.UploadImageCardCommand;

                                        // Saving the received image
                                        byte[] imageData          = (receivedGram as BinaryWebSockGram).Data.ToArray();
                                        var    savedImageFileName = imagesController.Add(uploadImageMessageCommand.Value.Filename, new MemoryStream(imageData));

                                        lock (socketsAndMessagesLock)
                                        {
                                            // Setting up the link to the saved file. Adding it to the received Card data
                                            var imageFileCard = uploadImageMessageCommand.Value;
                                            imageFileCard.Link = new Uri(listenerContext.Request.Url, "data/" + savedImageFileName);

                                            // Creating a new card in the controller, containing the received image
                                            cabinetController.UpdateCard(uploadImageMessageCommand.Id, imageFileCard);

                                            // Broadcasting the add_card command to all the connected clients
                                            Logger.Log("Broadcasting the new image card " + imageFileCard.Link + " to the " + connectedSockets.Count + " connected clients");
                                            var             addCommand  = new Model.Commands.UpdateCardCommand(uploadImageMessageCommand.Id, imageFileCard);
                                            TextWebSockGram addCardGram = new TextWebSockGram(serializer.SerializeCommand(addCommand));
                                            addCardGram.Broadcast(connectedSockets).Wait();
                                        }
                                    }
                                    else
                                    {
                                        throw new Exception("Strange case");
                                    }
                                }
                                else
                                {
                                    // Resetting the received command (we have a client error here)
                                    throw new Exception("We are expecting a binary appended to a command, but the received WebSocket message isn't a binary");
                                }

                                // After we received the appended binary, resetting the state machine to expect a command again
                                expecting       = Expecting.Command;
                                receivedCommand = null;
                            }
                            receivedGram = null;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Just log any exceptions to the console.
                // Pretty much any exception that occurs when calling `SendAsync`/`ReceiveAsync`/`CloseAsync`
                // is unrecoverable in that it will abort the connection and leave the `WebSocket` instance in an unusable state.
                Logger.Log(String.Format("Exception: {0}", e));
            }
            finally
            {
                // Disposing the WebSocket and removing it from the list
                try
                {
                    // Clean up by disposing the WebSocket once it is closed/aborted.
                    if (webSocket != null)
                    {
                        lock (socketsAndMessagesLock)
                        {
                            connectedSockets.Remove(webSocket);
                        }
                        webSocket.Dispose();
                    }
                }
                catch (Exception e)
                {
                    Logger.Log(String.Format("Exception during WebSocket disposure: {0}", e));
                }
            }
        }