protected virtual Response callChecked_ListRoomMembers(string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 2, 2, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            string roomName = commandSplit[1];

            // get the member list from the upper layer
            IEnumerable <string> memberList;
            Response             res = handle_ListRoomMembers(roomName, out memberList);

            // check result
            if (!res.Success)
            {
                return(res);
            }

            // pack the member list into the response
            string membersString = String.Join(":", memberList);

            return(new Response(true, membersString));
        }
Beispiel #2
0
        public bool Send_ListRooms(out Response response, out IEnumerable <string> roomList)
        {
            roomList = null;

            // send the command string
            string commandString  = "list_rooms";
            bool   stillConnected = m_serverSerializer.Serialize(commandString);

            if (!stillConnected)
            {
                response = null;
                return(false);  // connection was closed
            }

            // the server response will contain the room list in the message string
            stillConnected = readAck(out response);
            if (!stillConnected)
            {
                return(false);  // connection was closed
            }
            // If server acked successful, parse the message. (Actually, this operation is always successful, but it's good to check in case that ever changes.)
            if (response.Success)
            {
                roomList = CpParseUtilities.SplitMessage(response.Message, m_stringDelimiter);
            }

            return(true);  // connection still active
        }
        protected virtual Response callChecked_Connect(AmTcpClient newConnection, string commandString, out string requestedUsername)
        {
            requestedUsername = "";

            // This function is special and has to do the extra work of splitting and checking the commandstring.
            string[] commandSplit = CpParseUtilities.SplitMessage(commandString, m_stringDelimiter, 2);
            // check it is a "connect" request
            if (commandSplit[0].ToLower() != "connect")
            {
                return(new Response(false, "Expected connection request."));
            }

            // check arguments (should be 2)
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 2, 2, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            // check if name has a colon in it (not allowed)
            requestedUsername = commandSplit[1];
            if (requestedUsername.Contains(m_stringDelimiter))
            {
                return(new Response(false, String.Format("Name shall not contain the delimiter character '{0}'.", m_stringDelimiter)));
            }

            // attempt to register the user
            return(handle_Connect(requestedUsername, newConnection));
        }
Beispiel #4
0
        public bool Send_ListRoomMembers(string roomName, out Response response, out IEnumerable <string> roomMembers)
        {
            roomMembers = null;

            // send the command string
            string commandString  = String.Format("list_room_members:{0}", roomName);
            bool   stillConnected = m_serverSerializer.Serialize(commandString);

            if (!stillConnected)
            {
                response = null;
                return(false);  // connection was closed
            }

            // the server response will contain the room member list in the message string
            stillConnected = readAck(out response);
            if (!stillConnected)
            {
                return(false);  // connection was closed
            }
            // If server acked successful, parse the message.
            if (response.Success)
            {
                roomMembers = CpParseUtilities.SplitMessage(response.Message, m_stringDelimiter);
            }

            return(true);  // connection still active
        }
Beispiel #5
0
        public static Response ParseAck(string message, char delimiter)
        {
            Response response = new Response(false, "");

            // split and remove whitespace
            string[] responseSplit = CpParseUtilities.SplitMessage(message, delimiter, 2);

            if (responseSplit.Length > 1)
            {
                response.Message = responseSplit[1];
            }
            else
            {
                response.Message = "";
            }

            if (responseSplit[0].ToLower() == "ack")
            {
                response.Success = true;
            }
            else if (responseSplit[0].ToLower() == "nack")
            {
                if (String.IsNullOrWhiteSpace(response.Message))
                {
                    response.Message = "Server sent no explanation.";
                }
            }
            else
            {
                response.Message = String.Format("Server sent unexpected response '{0}'.", message);
            }

            return(response);
        }
        protected override async Task ftClientServiceLoopAsync(SslEgg egg)
        {
            FtClient client = new FtClient(egg.SslStream);

            // shortcut lambda
            Func <Response, Task <bool> > lSendResponseAsync = async(response) =>
            {
                return(await CpServersideBase.SendResponseAsync(client.SerializerAsync, response.Success, response.Message));
            };

            // the command string read from client
            var tup = await client.DeserializerAsync.DeserializeAsync("");

            bool   stillConnected = tup.Item1;
            string commandString  = tup.Item2;

            if (!stillConnected)
            {
                goto exit;
            }

            // an array of strings parsed from the sent command string by splitting by colon :
            // hard-coded max 10 substrings. Change if needed.
            string[] commandSplit = CpParseUtilities.SplitMessage(commandString, m_stringDelimiter, 10);

            switch (commandSplit[0].ToLower())
            {
            case "file_up":
            {
                Tuple <bool, Response> res = await callChecked_FileUpAsync(client, commandSplit);

                if (res.Item1)          // client still connected
                {
                    await lSendResponseAsync(res.Item2);
                }
                break;
            }

            case "file_down":
            {
                Tuple <bool, Response> res = await callChecked_FileDownAsync(client, commandSplit);

                if (res.Item1)          // client still connected
                {
                    await lSendResponseAsync(res.Item2);
                }
                break;
            }

            default:
                break;
            }

exit:
            client.Close();
        }
        protected virtual Response callChecked_Disconnect(string[] commandSplit, string username)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 1, 1, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            return(handle_Disconnect(username));
        }
Beispiel #8
0
        private void eventChannelReadLoop()
        {
            while (true)
            {
                // the command string read from client
                string commandString  = "";
                bool   stillConnected = m_serverEventDeserializer.Deserialize(ref commandString);
                if (!stillConnected)
                {
                    Logging.DebugWriteLine("Server disconnected.");
                    goto loop_exit;
                }

                // an array of strings parsed from the sent command string by splitting by colon :
                // hard-coded max 10 substrings. Change if needed.
                string[] commandSplit = CpParseUtilities.SplitMessage(commandString, m_stringDelimiter, 10);


                switch (commandSplit[0].ToLower())
                {
                case "event_disconnect":
                {
                    Response response = receiveEvent_Disconnect_checked(commandSplit);
                    goto loop_exit;
                    // [break]
                }

                case "event_message_room":
                {
                    Response resonse = receiveEvent_MessageRoom_checked(commandSplit);
                    break;
                }

                case "event_message_personal":
                {
                    Response response = receiveEvent_MessagePersonal_checked(commandSplit);
                    break;
                }

                case "event_room_deleted":
                {
                    Response response = receiveEvent_RoomDeleted_checked(commandSplit);
                    break;
                }

                default:
                    Logging.DebugWriteLine(String.Format("Server sent unknown event. '{0}'.", commandString));
                    break;
                }
            }

loop_exit:
            m_server.Close();
        }
Beispiel #9
0
        protected virtual Response receiveEvent_Disconnect_checked(string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 1, 1, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            return(handle_Disconnect());
        }
        protected virtual Response callChecked_UnsubscribeRoom(string[] commandSplit, string username)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 2, 2, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            string roomName = commandSplit[1];

            return(handle_UnsubscribeRoom(roomName, username));
        }
        protected virtual async Task <Response> callChecked_DeleteRoom(string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 2, 2, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            string roomName = commandSplit[1];

            return(await handle_DeleteRoom(roomName));
        }
Beispiel #12
0
        protected virtual Response receiveEvent_RoomDeleted_checked(string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 2, 2, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            string roomName = commandSplit[1];

            return(handle_RoomDeleted(roomName));
        }
Beispiel #13
0
        protected virtual Response receiveEvent_MessagePersonal_checked(string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 3, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            CpParseUtilities.RecombineSplitMessage(ref commandSplit, 2);

            string fromUsername = commandSplit[1];
            string messageText  = commandSplit[2];

            return(handle_MessagePersonal(fromUsername, messageText));
        }
        protected virtual async Task <Response> callChecked_MessagePersonalAsync(string[] commandSplit, string fromUsername)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 3, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            CpParseUtilities.RecombineSplitMessage(ref commandSplit, 2);

            string toUsername  = commandSplit[1];
            string messageText = commandSplit[2];

            return(await handle_MessagePersonalAsync(toUsername, fromUsername, messageText));
        }
        protected virtual Response callChecked_CreateRoom(string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 2, 2, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            string roomName = commandSplit[1];

            Debug.Assert(m_stringDelimiter == ':');
            if (roomName.Contains(m_stringDelimiter))
            {
                return(new Response(false, "Room name shall not contain a colon."));
            }

            return(handle_CreateRoom(roomName));
        }
Beispiel #16
0
        protected override async Task <Tuple <bool, Response> > callChecked_FileUpAsync(FtClient ftClient, string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 2, 2, ref errMessage))
            {
                return(new Tuple <bool, Response>(true, new Response(false, errMessage)));
            }

            // get filename
            string filename = commandSplit[1];

            // create a file
            using (Stream fileOut = FtFileManager.OpenForWrite(filename, out errMessage))
            {
                if (fileOut == null)
                {
                    return(new Tuple <bool, Response>(true, new Response(false, errMessage)));
                }

                // send ok (ready to receive file)
                bool stillConnected = await SendResponseAsync(ftClient.SerializerAsync, true, "");

                if (!stillConnected)
                {
                    return(new Tuple <bool, Response>(false, null));
                }

                // receive file
                var fileReceiveResult = await FtFileManager.FileReceiveAsync(ftClient.Client, fileOut);

                if (!fileReceiveResult.Item1)
                {
                    return(new Tuple <bool, Response>(fileReceiveResult.Item1, null));
                }

                // send ok (file was received ok)
                return(new Tuple <bool, Response>(true, fileReceiveResult.Item2));
            }
        }
Beispiel #17
0
        protected override async Task <Tuple <bool, Response> > callChecked_FileDownAsync(FtClient ftClient, string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 2, 2, ref errMessage))
            {
                return(new Tuple <bool, Response>(true, new Response(false, errMessage)));
            }

            // get filename
            string filename = commandSplit[1];

            // open the file
            using (Stream fileIn = FtFileManager.OpenForRead(filename, out errMessage))
            {
                if (fileIn == null)
                {
                    return(new Tuple <bool, Response>(true, new Response(false, errMessage)));
                }
                // send ok (ready to send file)
                bool stillConnected = await SendResponseAsync(ftClient.SerializerAsync, true, "");

                if (!stillConnected)
                {
                    return(new Tuple <bool, Response>(false, null));
                }

                // send file
                stillConnected = await FtFileManager.FileSendAsync(ftClient.Client, fileIn);

                if (!stillConnected)
                {
                    return(new Tuple <bool, Response>(false, null));
                }
            }

            return(new Tuple <bool, Response>(true, new Response(true, "")));
        }
        protected virtual Response callChecked_ListRooms(string[] commandSplit)
        {
            string errMessage = "";

            if (!CpParseUtilities.CheckArgCount(commandSplit, 1, 1, ref errMessage))
            {
                return(new Response(false, errMessage));
            }

            // get the room list from upper layer
            IEnumerable <string> roomList;
            Response             res = handle_ListRooms(out roomList);

            // the handler actually can't fail, but leave this check in anyway
            if (!res.Success)
            {
                return(res);
            }

            // pack the room list into the response message
            string roomsString = String.Join(":", roomList);

            return(new Response(true, roomsString));
        }
        private async Task cpClientServiceLoopAsync(SslEgg egg)
        {
            AmTcpClient client = new AmTcpClient(egg);

            // shortcut lambda
            Func <Response, Task <bool> > lSendResponseAsync = async(response) =>
            {
                return(await SendResponseAsync(client.Serializer, response.Success, response.Message));
            };

            // establish connection / register user
            string username;

            {
                // read from the new client (expecting a "connect" commandstring).
                var tup = await client.Deserializer.DeserializeAsync("");

                bool   stillConnected = tup.Item1;
                string commandString  = tup.Item2;

                if (!stillConnected)
                {
                    Logging.DebugWriteLine("Client connected but disconnected before trying to register.");
                    client.Close();
                    return;
                }
                // parse the command string and register the user
                Response res = callChecked_Connect(client, commandString, out username);
                await lSendResponseAsync(res);  // don't need to check result as a disconnected client will be detected upon first read

                if (!res.Success)
                {
                    Logging.DebugWriteLine(String.Format("Unable to register new client '{0}'. {1}", username, res.Message));
                    client.Close();
                    return;
                }

                Logging.DebugWriteLine(String.Format("Client '{0}' connected. {1}", username, client.RemoteEndPoint.ToString()));
            }

            while (true)
            {
                // the command string read from client
                var tup = await client.Deserializer.DeserializeAsync("");

                bool   stillConnected = tup.Item1;
                string commandString  = tup.Item2;

                if (!stillConnected)
                {
                    // remove the user from various data structures
                    Response result = handle_Disconnect(username);
                    Logging.DebugWriteLine(String.Format("Client {0} disconnected.", username));
                    if (!result.Success)
                    {
                        Logging.DebugWriteLine(result.Message);
                    }
                    goto exit_while;
                }

                // an array of strings parsed from the sent command string by splitting by colon :
                // hard-coded max 10 substrings. Change if needed.
                string[] commandSplit = CpParseUtilities.SplitMessage(commandString, m_stringDelimiter, 10);


                switch (commandSplit[0].ToLower())
                {
                case "disconnect":
                {
                    Response result = callChecked_Disconnect(commandSplit, username);
                    await lSendResponseAsync(result);

                    if (result.Success)
                    {
                        Logging.DebugWriteLine(String.Format("Client {0} disconnected gracefully.", username));
                        goto exit_while;
                    }
                    Logging.DebugWriteLine(String.Format("From server: Client {0} requested disconnect but was denied. {1}", username, result.Message));
                    break;
                }

                case "create_room":
                {
                    Response result = callChecked_CreateRoom(commandSplit);
                    await lSendResponseAsync(result);

                    if (result.Success)
                    {
                        Logging.DebugWriteLine(String.Format("Client {0} created room '{1}'.", username, commandSplit[1]));
                    }
                    break;
                }

                case "delete_room":
                {
                    Response result = await callChecked_DeleteRoom(commandSplit);
                    await lSendResponseAsync(result);

                    if (result.Success)
                    {
                        Logging.DebugWriteLine(String.Format("Client {0} deleted room '{1}'.", username, commandSplit[1]));
                    }
                    break;
                }

                case "list_rooms":
                {
                    Response result = callChecked_ListRooms(commandSplit);
                    await lSendResponseAsync(result);

                    break;
                }

                case "subscribe_room":
                {
                    Response result = callChecked_SubscribeRoom(commandSplit, username);
                    await lSendResponseAsync(result);

                    break;
                }

                case "unsubscribe_room":
                {
                    Response result = callChecked_UnsubscribeRoom(commandSplit, username);
                    await lSendResponseAsync(result);

                    break;
                }

                case "list_room_members":
                {
                    Response result = callChecked_ListRoomMembers(commandSplit);
                    await lSendResponseAsync(result);

                    break;
                }

                case "send_message_room":
                {
                    Response result = await callChecked_MessageRoomAsync(commandSplit, username);
                    await lSendResponseAsync(result);

                    break;
                }

                case "send_message_personal":
                {
                    Response result = await callChecked_MessagePersonalAsync(commandSplit, username);
                    await lSendResponseAsync(result);

                    break;
                }

                default:
                    await lSendResponseAsync(new Response(false, "Unknown command."));

                    Logging.DebugWriteLine(String.Format("Client sent unknown command. '{0}'", commandString));
                    break;
                }
            }

exit_while:
            // cleanup socket resources
            client.Close();
        }