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