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)); }
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)); }
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 }
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)); }
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(); }
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)); }
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)); }
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)); }
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)); } }
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(); }