public StatusResponse CancelChat(string sessionID, string recipientMSISDN) { ExecuteAndHandleExceptions(() => { User senderUser = CheckUserSession(sessionID); CheckMSISDN(recipientMSISDN); User recipientUser = CheckIfUserIsOnline(recipientMSISDN); CryptoChatEntities context = new CryptoChatEntities(); // Find the existing chat session between the users var existingChatSession = (from s in context.ChatSessions where (s.FromUserId == senderUser.UserId && s.ToUserId == recipientUser.UserId) || (s.FromUserId == recipientUser.UserId && s.ToUserId == senderUser.UserId) select s).FirstOrDefault(); if (existingChatSession == null) { throw new ErrorResponseException(HttpStatusCode.NotFound, "ERR_INVALID_STATE", "No active chat session exists between " + senderUser.MSISDN + " and " + recipientUser.MSISDN + "."); } // Delete the chat session DeleteChatSession(senderUser, recipientUser); // Send a notification to the recipient user (through a message) SendMessage(senderUser, recipientUser, MessageType.MSG_CANCEL_CHAT, "Chat canceled"); }); return new StatusResponse(); }
private void DeleteAllExpiredSessionsAndMessages() { CryptoChatEntities context = new CryptoChatEntities(); DateTime minAllowedLastActivityTime = DateTime.Now.AddSeconds(-Settings.Default.HttpSessionTimeoutSeconds); // Delete any expired chat sessions in the DB string deleteChatSessionsSQL = "DELETE FROM ChatSessions " + "FROM Users u JOIN ChatSessions s " + " ON (u.UserId = s.FromUserId or u.UserId = s.ToUserId) " + "WHERE LastActivity < {0}"; context.ExecuteStoreCommand(deleteChatSessionsSQL, new object[] { minAllowedLastActivityTime }); // Delete any expired messages in the DB string deleteMessagesSQL = "DELETE FROM Messages " + "FROM Users u JOIN Messages m ON (u.UserId = m.ToUserId) " + "WHERE LastActivity < {0}"; context.ExecuteStoreCommand(deleteMessagesSQL, new object[] { minAllowedLastActivityTime }); // Send notifications about all users whose sessions were expired var usersWithExpiredSession = from u in context.Users where u.LastActivity < minAllowedLastActivityTime && u.SessionKey != null select u; foreach (var user in usersWithExpiredSession) { user.SessionKey = null; MobileCryptoChatService.SendMessageToAllOnlineUsers(user, MessageType.MSG_USER_OFFLINE, "User lost connection with the server."); } context.SaveChanges(); }
public MessageResponse GetNextMessage(string sessionID) { MessageResponse messageToReturn = null; ExecuteAndHandleExceptions(() => { User user = CheckUserSession(sessionID); CryptoChatEntities context = new CryptoChatEntities(); Message nextMsg = (from m in context.Messages.Include("FromUser") where m.ToUserId == user.UserId orderby m.MsgDate select m).FirstOrDefault(); if (nextMsg != null) { // A message is found --> return it as a result and delete it from DB messageToReturn = new MessageResponse() { MsgType = nextMsg.MsgType, MsgText = nextMsg.MsgText, Msisdn = nextMsg.FromUser.MSISDN }; context.DeleteObject(nextMsg); context.SaveChanges(); } else { // No messages are waiting --> return MSG_NO_MESSAGES messageToReturn = new MessageResponse() { MsgType = MessageType.MSG_NO_MESSAGES.ToString() }; } }); return messageToReturn; }
private void SendMessage(User senderUser, User recipientUser, MessageType messageType, string msgText) { Message msg = new Message(); msg.FromUserId = senderUser.UserId; msg.ToUserId = recipientUser.UserId; msg.MsgType = messageType.ToString(); msg.MsgDate = DateTime.Now; msg.MsgText = msgText; CryptoChatEntities context = new CryptoChatEntities(); context.Messages.AddObject(msg); context.SaveChanges(); }
private LoginResponse LoginUser(string msisdn, string authCode) { LoginResponse loginResult = null; ExecuteAndHandleExceptions(() => { CheckMSISDN(msisdn); CheckAuthCode(authCode); // Check whether the MSISDN and authCode are correct CryptoChatEntities context = new CryptoChatEntities(); var user = (from u in context.Users where u.MSISDN == msisdn && u.AuthCodeSHA1 == authCode select u).FirstOrDefault(); if (user == null) { throw new ErrorResponseException(HttpStatusCode.Forbidden, "ERR_INV_LOGIN", "Invalid MSISDN or password."); } // User found in the database -> perform login user.SessionKey = GenerateNewSessionKey(user.UserId); user.LastActivity = DateTime.Now; context.SaveChanges(); // Delete all messages waiting at the server for the just logged user DeleteWaitingMessagesAndSessions(user); // Send the "user online" notification to all online users SendMessageToAllOnlineUsers(user, MessageType.MSG_USER_ONLINE, "User logged in the system."); loginResult = new LoginResponse() { SessionID = user.SessionKey }; }); return loginResult; }
private void DeleteWaitingMessagesAndSessions(User recipientUser) { CryptoChatEntities context = new CryptoChatEntities(); // Delete any waiting messages for the user string deleteMessagesSQL = "DELETE FROM Messages WHERE ToUserId={0}"; context.ExecuteStoreCommand(deleteMessagesSQL, new object[] { recipientUser.UserId }); // Delete any existing chat sessions associated with the user string deleteChatSessionsSQL = "DELETE FROM ChatSessions WHERE " + "FromUserId={0} or ToUserId={0}"; context.ExecuteStoreCommand(deleteChatSessionsSQL, new object[] { recipientUser.UserId }); }
private void DeleteChatSession(User senderUser, User recipientUser) { CryptoChatEntities context = new CryptoChatEntities(); // Delete any existing chat sessions between the users string deleteChatSessionsSQL = "DELETE FROM ChatSessions WHERE " + "(FromUserId={0} and ToUserId={1}) or (FromUserId={1} and ToUserId={0})"; context.ExecuteStoreCommand(deleteChatSessionsSQL, new object[] { senderUser.UserId, recipientUser.UserId }); // Delete any waiting chat messages between the users string msgTypesToDelete = "'" + MessageType.MSG_CHALLENGE.ToString() + "'," + "'" + MessageType.MSG_RESPONSE.ToString() + "'," + "'" + MessageType.MSG_START_CHAT.ToString() + "'," + "'" + MessageType.MSG_CANCEL_CHAT.ToString() + "'," + "'" + MessageType.MSG_CHAT_MESSAGE.ToString() + "'"; string deleteMessagesSQL = "DELETE FROM Messages WHERE " + "((FromUserId={0} and ToUserId={1}) or (FromUserId={1} and ToUserId={0})) AND " + "(MsgType in (" + msgTypesToDelete + "))"; context.ExecuteStoreCommand(deleteMessagesSQL, new object[] { senderUser.UserId, recipientUser.UserId }); }
private User CheckUserSession(string sessionID) { CryptoChatEntities context = new CryptoChatEntities(); DateTime minAllowedLastActivityTime = DateTime.Now.AddSeconds(-Settings.Default.HttpSessionTimeoutSeconds); var dbUser = (from u in context.Users where u.SessionKey == sessionID && u.LastActivity >= minAllowedLastActivityTime select u).FirstOrDefault(); if (dbUser == null) { // The session is either too old or does not exist throw new ErrorResponseException(HttpStatusCode.Forbidden, "ERR_SESSIONID", "Invalid sessionID."); } // The user session is valid -> update the last activity time dbUser.LastActivity = DateTime.Now; context.SaveChanges(); return dbUser; }
private User CheckIfUserIsOnline(string recipientMSISDN) { CryptoChatEntities context = new CryptoChatEntities(); DateTime minAllowedLastActivityTime = DateTime.Now.AddSeconds(-Settings.Default.HttpSessionTimeoutSeconds); User user = (from u in context.Users where u.MSISDN == recipientMSISDN select u).FirstOrDefault(); if (user == null) { throw new ErrorResponseException(HttpStatusCode.NotFound, "ERR_BAD_USER", "The specified user does not exists."); } if (user.LastActivity < minAllowedLastActivityTime) { throw new ErrorResponseException(HttpStatusCode.NotFound, "ERR_USER_OFF", "The specified user is offline."); } return user; }
internal static void SendMessageToAllOnlineUsers( User senderUser, MessageType msgType, string msgText) { DateTime minAllowedLastActivityTime = DateTime.Now.AddSeconds(-Settings.Default.HttpSessionTimeoutSeconds); CryptoChatEntities context = new CryptoChatEntities(); var allUserIds = from u in context.Users where u.LastActivity >= minAllowedLastActivityTime select u.UserId; foreach (var recipientUserId in allUserIds) { if (senderUser.UserId != recipientUserId) { Message msg = new Message(); msg.FromUserId = senderUser.UserId; msg.ToUserId = recipientUserId; msg.MsgType = msgType.ToString(); msg.MsgText = msgText; msg.MsgDate = DateTime.Now; context.Messages.AddObject(msg); } } context.SaveChanges(); }
public StatusResponse StartChat(string sessionID, string recipientMSISDN) { ExecuteAndHandleExceptions(() => { User senderUser = CheckUserSession(sessionID); CheckMSISDN(recipientMSISDN); User recipientUser = CheckIfUserIsOnline(recipientMSISDN); CryptoChatEntities context = new CryptoChatEntities(); // Find the existing chat session between the users var existingChatSession = (from s in context.ChatSessions where s.FromUserId == senderUser.UserId && s.ToUserId == recipientUser.UserId select s).FirstOrDefault(); if (existingChatSession == null || existingChatSession.ChatState != ChatSessionState.RESPONSE_SENT.ToString()) { throw new ErrorResponseException(HttpStatusCode.NotFound, "ERR_INVALID_STATE", "No accepted response exists from " + recipientUser.MSISDN + " to " + senderUser.MSISDN + "."); } // Change the state of the chat session to "response sent" existingChatSession.ChatState = ChatSessionState.ACTIVE.ToString(); context.SaveChanges(); // Send a notification to the recipient user (through a message) SendMessage(senderUser, recipientUser, MessageType.MSG_START_CHAT, "Chat started"); }); return new StatusResponse(); }
public StatusResponse SendChatMessage( string sessionID, string recipientMSISDN, string encryptedMsg) { ExecuteAndHandleExceptions(() => { User senderUser = CheckUserSession(sessionID); CheckMSISDN(recipientMSISDN); User recipientUser = CheckIfUserIsOnline(recipientMSISDN); CheckEncryptedMessage(encryptedMsg); CryptoChatEntities context = new CryptoChatEntities(); // Find the existing chat session between the users var existingChatSession = (from s in context.ChatSessions where (s.FromUserId == senderUser.UserId && s.ToUserId == recipientUser.UserId) || (s.FromUserId == recipientUser.UserId && s.ToUserId == senderUser.UserId) select s).FirstOrDefault(); if (existingChatSession == null || existingChatSession.ChatState != ChatSessionState.ACTIVE.ToString()) { throw new ErrorResponseException(HttpStatusCode.NotFound, "ERR_INVALID_STATE", "No active chat session exists between " + senderUser.MSISDN + " and " + recipientUser.MSISDN + "."); } // Send the chat message to the recipient user SendMessage(senderUser, recipientUser, MessageType.MSG_CHAT_MESSAGE, encryptedMsg); }); return new StatusResponse(); }
public LoginResponse RegisterNewUser(string msisdn, string authCode) { CheckMSISDN(msisdn); CheckAuthCode(authCode); LoginResponse loginResult = null; ExecuteAndHandleExceptions(() => { // Register the user in the DB CryptoChatEntities context = new CryptoChatEntities(); User user = new User(); user.MSISDN = msisdn.ToLowerInvariant(); user.AuthCodeSHA1 = authCode; context.Users.AddObject(user); context.SaveChanges(); // Login the user into the system after the registration loginResult = LoginUser(msisdn, authCode); // Send the "user online" notification to all online users SendMessageToAllOnlineUsers(user, MessageType.MSG_USER_ONLINE, "New user registered in the system."); }); return loginResult; }
public StatusResponse LogoutUser(string sessionID) { ExecuteAndHandleExceptions(() => { User user = CheckUserSession(sessionID); CryptoChatEntities context = new CryptoChatEntities(); int updatedSessionsCount = context.ExecuteStoreCommand( "UPDATE Users SET SessionKey=null WHERE SessionKey={0}", new object[] { sessionID }); if (updatedSessionsCount != 1) { throw new ErrorResponseException(HttpStatusCode.InternalServerError, "ERR_LOGOUT_FAIL", "Logout failed unexpectedly."); } // Session sucessfully removed from DB (logout was successfull) DeleteWaitingMessagesAndSessions(user); // Send the "user online" notification to all online users SendMessageToAllOnlineUsers(user, MessageType.MSG_USER_OFFLINE, "User left the system."); }); return new StatusResponse(); }
public string[] ListUsers(string sessionID) { string[] allMSISDNs = null; ExecuteAndHandleExceptions(() => { CheckUserSession(sessionID); DateTime minAllowedLastActivityTime = DateTime.Now.AddSeconds(-Settings.Default.HttpSessionTimeoutSeconds); CryptoChatEntities context = new CryptoChatEntities(); allMSISDNs = (from u in context.Users where u.LastActivity >= minAllowedLastActivityTime orderby u.MSISDN select u.MSISDN).ToArray(); }); return allMSISDNs; }
public StatusResponse InviteUser(string sessionID, string recipientMSISDN, string challenge) { ExecuteAndHandleExceptions(() => { User senderUser = CheckUserSession(sessionID); CheckMSISDN(recipientMSISDN); User recipientUser = CheckIfUserIsOnline(recipientMSISDN); CheckChallengeCode(challenge); if (senderUser.UserId == recipientUser.UserId) { throw new ErrorResponseException(HttpStatusCode.NotFound, "ERR_AUTO_CHAT", "Users cannot send chat invitations to themselves."); } DeleteChatSession(senderUser, recipientUser); CryptoChatEntities context = new CryptoChatEntities(); // Create a new chat session between the users ChatSession newChatSession = new ChatSession(); newChatSession.FromUserId = senderUser.UserId; newChatSession.ToUserId = recipientUser.UserId; newChatSession.ChatState = ChatSessionState.CHALLENGE_SENT.ToString(); context.ChatSessions.AddObject(newChatSession); context.SaveChanges(); // Send the challenge to the recipient user (through a message) SendMessage(senderUser, recipientUser, MessageType.MSG_CHALLENGE, challenge); }); return new StatusResponse(); }