/// <summary> /// Send array of friends to user. /// </summary> /// <param name="user">user.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void SendFriends(OnlineUser user) { string[] allFriends = DBoperations.GetFriends(user.Id); string[] online_users = onlineUsers.Select(x => x.Login).ToArray(); user.Client.SendMessage(new FriendsMessage { OnlineFriends = allFriends.Where(x => online_users.Contains(x)).ToArray(), OfflineFriends = allFriends.Where(x => !online_users.Contains(x)).ToArray() }); }
/// <summary> /// 上线之后通知所有在线好友 /// </summary> /// <param name="user"></param> public static void addOnlineUser(OnlineUser user) { foreach (var item in user_list.Values) { if (Program.SqlManager.isFriend(item.ID, user.ID)) { item.ReciveMessage(user.ID, new OnlineUserMessge(1, new pair <int, byte[]>(user.ID, user.IP), MySQL_Manager.getTimestampOfNow())); } } user.first_login_max_vitality(); user_list.Add(user.ID, user); }
/// <summary> /// Handle new reply in conversation. /// </summary> /// <param name="user">user.</param> /// <param name="interlocutor">interlocutor.</param> /// <param name="text">text of reply.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void HandleReply(OnlineUser user, string interlocutor, string text) { int interlocutorId = DBoperations.GetUserId(interlocutor); if (interlocutorId == 0) { return; } // time of reply DateTime time = DateTime.Now; if (DBoperations.AddNewReply(user.Id, interlocutorId, text, time)) { // send reply to user one user.Client.SendMessage(new NewReplyMessage { Interlocutor = interlocutor, Author = user.Login, Time = time, Text = text }); // send reply to user two if online OnlineUser friend = GetOnlineUser(interlocutor); if (friend != null) { friend.Client.SendMessage(new NewReplyMessage { Interlocutor = user.Login, Author = user.Login, Time = time, Text = text }); } // write notification to db else { DBoperations.AddNotification(interlocutorId, user.Id, UserActions.MessageSended, DateTime.Now); } } }
/// <summary> /// Log out user. /// </summary> /// <param name="user">user.</param> private void Logout(OnlineUser user) { log.Info($"Client disconnected. ip {((IPEndPoint)user.Client.tcpClient.Client.RemoteEndPoint).Address.ToString()}"); string[] allFriends = DBoperations.GetFriends(user.Id); string[] online_users = onlineUsers.Select(x => x.Login).ToArray(); string[] onlineFriends = allFriends.Where(x => online_users.Contains(x)).ToArray(); foreach (var login in onlineFriends) { OnlineUser friend = GetOnlineUser(login); friend?.Client.SendMessage(new UserActionMessage { UserLogin = user.Login, Action = UserActions.GoOffline }); } onlineUsers.Remove(user); user.Dispose(); }
/// <summary> /// Send array of all users to user. /// </summary> /// <param name="user">user.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void SendAllUsers(OnlineUser user) { string[] allUsers = DBoperations.GetAllUsers(); string[] incomeRequests = DBoperations.GetIncomeFriendshipRequests(user.Id); string[] outcomeRequests = DBoperations.GetOutcomeFriendshipRequests(user.Id); string[] friends = DBoperations.GetFriends(user.Id); string[] users = allUsers.Where(x => !incomeRequests.Contains(x) & !outcomeRequests.Contains(x) & !friends.Contains(x) & x != user.Login).ToArray(); string[] online_users = onlineUsers.Select(x => x.Login).ToArray(); user.Client.SendMessage(new AllUsersMessage { OnlineUsers = users.Where(x => online_users.Contains(x)).ToArray(), OfflineUsers = users.Where(x => !online_users.Contains(x)).ToArray() }); }
/// <summary> /// Send array all notifications to user. /// </summary> /// <param name="user">user.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void SendNotifications(OnlineUser user) { Notification[] notifications = DBoperations.GetNotifications(user.Id); foreach (var notification in notifications) { if (notification.accept_friendship) user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.AcceptFriendship }); else if (notification.reject_friendship) user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.RejectFriendship }); else if (notification.send_friendship) user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.SendFriendshipRequest }); else if (notification.cancel_friendship) user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.CancelFriendshipRequest }); else if (notification.remove_friend) user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.RemoveFromFriends }); } // delete notifications from db DBoperations.RemoveNotifications(user.Id); }
/// <summary> /// Send conversation to user. /// </summary> /// <param name="user">user.</param> /// <param name="interlocutor">interlocutor of user in conversation.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void SendConversation(OnlineUser user, string interlocutor) { int interlocutorId = DBoperations.GetUserId(interlocutor); if (interlocutorId == 0) return; // get replies from db ConversationReply[] replies = DBoperations.GetConversation(user.Id, interlocutorId); if (replies != null) { foreach (var r in replies) user.Client.SendMessage(new OldReplyMessage { Interlocutor = interlocutor, Author = DBoperations.GetUserLogin(r.user_id), Time = r.time, Text = r.reply }); } }
/// <summary> /// Remove user from friends. /// </summary> /// <param name="user">user.</param> /// <param name="friendLogin">friend's login.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void RemoveFriend(OnlineUser user, string friendLogin) { int friendId = DBoperations.GetUserId(friendLogin); if (friendId == 0) return; if (DBoperations.RemoveFriend(user.Id, friendId)) { // send new data to user one SendFriends(user); OnlineUser friend = GetOnlineUser(friendLogin); // send notification to user two if online if (friend != null) { friend.Client.SendMessage(new UserActionMessage { UserLogin = user.Login, Time = DateTime.Now, Action = UserActions.RemoveFromFriends }); } // write to db else { DBoperations.AddNotification(friendId, user.Id, UserActions.RemoveFromFriends, DateTime.Now); } } }
/// <summary> /// Listen to user's messages. /// </summary> /// <param name="user">user.</param> private void UserListener(OnlineUser user) { while (true) { Message message; try { // user's incoming message message = user.Client.ReceiveMessage(); } // user disconnected catch (ConnectionInterruptedException) { if (onlineUsers.Contains(user)) { log.Info($"Client disconnected. ip {((IPEndPoint)user.Client.tcpClient.Client.RemoteEndPoint).Address.ToString()}"); onlineUsers.Remove(user); user.Dispose(); } break; } // process message try { if (message is GetNotificationsMessage) { SendNotifications(user); } if (message is GetAllUsersMessage) { SendAllUsers(user); } else if (message is GetFriendsMessage) { SendFriends(user); } else if (message is GetIncomeFriendshipRequestsMessage) { SendIncomeFriendshipRequests(user); } else if (message is GetOutcomeFriendshipRequestsMessage) { SendOutcomeFriendshipRequests(user); } else if (message is GetConversationMessage) { SendConversation(user, ((GetConversationMessage)message).Interlocutor); } else if (message is FriendshipRequestMessage) { SetFriendshipRequest(user, ((FriendshipRequestMessage)message).LoginOfNeededUser); } else if (message is UserActionMessage) { UserActionMessage msg = (UserActionMessage)message; switch (msg.Action) { case UserActions.CancelFriendshipRequest: CancelFriendshipRequest(user, msg.UserLogin); break; case UserActions.AcceptFriendship: AcceptFriendshipRequest(user, msg.UserLogin); break; case UserActions.RejectFriendship: RejectFriendshipRequest(user, msg.UserLogin); break; case UserActions.RemoveFromFriends: RemoveFriend(user, msg.UserLogin); break; default: break; } } else if (message is NewReplyMessage) { HandleReply(user, ((NewReplyMessage)message).Interlocutor, ((NewReplyMessage)message).Text); } else if (message is LogoutRequestMessage) { Logout(user); break; } } catch (ConnectionInterruptedException e) { log.Error($"Client '{user.Login}' disconnected", e); } } }
/// <summary> /// Add user to list of online users and start to listen to him. /// </summary> /// <param name="user">user.</param> public void AddUser(OnlineUser user) { if (user != null) { onlineUsers.Add(user); // online notification to friends string[] allFriends = DBoperations.GetFriends(user.Id); string[] online_users = onlineUsers.Select(x => x.Login).ToArray(); string[] onlineFriends = allFriends.Where(x => online_users.Contains(x)).ToArray(); foreach (var login in onlineFriends) { OnlineUser friend = GetOnlineUser(login); friend?.Client.SendMessage(new UserActionMessage { UserLogin = user.Login, Action = UserActions.GoOnline }); } } // listen this user Task.Run(() => UserListener(user)); }
/// <summary> /// Try to login client. Send response about result. /// </summary> /// <param name="client">client.</param> /// <param name="message">client's message.</param> private void LoginClient(MpClient client, LoginRequestMessage message) { bool isLoggedIn = false; Message response; if (string.IsNullOrEmpty(message.Login) || string.IsNullOrEmpty(message.Password) || message.Login.Length > 20 || message.Password.Length > 30) { response = new LoginRegisterResponseMessage { Response = LoginRegisterResponse.Error }; } else if (usersHandler.GetOnlineUser(message.Login) != null) { response = new LoginRegisterResponseMessage { Response = LoginRegisterResponse.AlreadyLogin }; } else { // client's id in db if (DBoperations.Login(message.Login, message.Password, out int id)) { log.Info($"Client logged in: {message.Login}"); // user is online OnlineUser user = new OnlineUser(id, message.Login, client); usersHandler.AddUser(user); isLoggedIn = true; response = new LoginRegisterResponseMessage { Response = LoginRegisterResponse.Success }; } else { response = new LoginRegisterResponseMessage { Response = LoginRegisterResponse.Fail }; } } try { // response to client client.SendMessage(response); } catch (ConnectionInterruptedException e) { log.Error("Connection with client broke.", e); } // close connection with client if client not logged in if (!isLoggedIn) { log.Info($"Client disconnected. ip {((IPEndPoint)client.tcpClient.Client.RemoteEndPoint).Address.ToString()}"); try { client.Close(); } catch (ConnectionInterruptedException e) { log.Error(e); } } }
/// <summary> /// Send array all notifications to user. /// </summary> /// <param name="user">user.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void SendNotifications(OnlineUser user) { Notification[] notifications = DBoperations.GetNotifications(user.Id); foreach (var notification in notifications) { if (notification.accept_friendship) { user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.AcceptFriendship }); } else if (notification.reject_friendship) { user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.RejectFriendship }); } else if (notification.send_friendship) { user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.SendFriendshipRequest }); } else if (notification.cancel_friendship) { user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.CancelFriendshipRequest }); } else if (notification.remove_friend) { user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.RemoveFromFriends }); } else { user.Client.SendMessage(new UserActionMessage { UserLogin = DBoperations.GetUserLogin(notification.user_two), Time = notification.time, Action = UserActions.MessageSended }); } } // delete notifications from db DBoperations.RemoveNotifications(user.Id); }
/// <summary> /// Send array of outcome friendship requests to user. /// </summary> /// <param name="user">user.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void SendOutcomeFriendshipRequests(OnlineUser user) { user.Client.SendMessage(new OutcomeFriendshipRequestsMessage { Logins = DBoperations.GetOutcomeFriendshipRequests(user.Id) }); }
/// <summary> /// Handle new reply in conversation. /// </summary> /// <param name="user">user.</param> /// <param name="interlocutor">interlocutor.</param> /// <param name="text">text of reply.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void HandleReply(OnlineUser user, string interlocutor, string text) { int interlocutorId = DBoperations.GetUserId(interlocutor); if (interlocutorId == 0) return; // time of reply DateTime time = DateTime.Now; if (DBoperations.AddNewReply(user.Id, interlocutorId, text, time)) { // send reply to user one user.Client.SendMessage(new NewReplyMessage { Interlocutor = interlocutor, Author = user.Login, Time = time, Text = text }); // send reply to user two if online OnlineUser friend = GetOnlineUser(interlocutor); friend?.Client.SendMessage(new NewReplyMessage { Interlocutor = user.Login, Author = user.Login, Time = time, Text = text }); } }
/// <summary> /// Set friendship request in db. /// </summary> /// <param name="user">user.</param> /// <param name="friendLogin">friend's login.</param> /// <exception cref="ConnectionInterruptedException"></exception> private void SetFriendshipRequest(OnlineUser user, string friendLogin) { int friendId = DBoperations.GetUserId(friendLogin); if (friendId == 0) return; // set friendship request if (DBoperations.SetFriendship(user.Id, friendId, false)) { // send new data to user one SendAllUsers(user); SendOutcomeFriendshipRequests(user); OnlineUser friend = GetOnlineUser(friendLogin); // send notification to user two if online if (friend != null) { friend.Client.SendMessage(new UserActionMessage { UserLogin = user.Login, Time = DateTime.Now, Action = UserActions.SendFriendshipRequest }); } // write to db else { DBoperations.AddNotification(friendId, user.Id, UserActions.SendFriendshipRequest, DateTime.Now); } } }
/// <summary> /// Try to login client. Send response about result. /// </summary> /// <param name="client">client.</param> /// <param name="message">client's message.</param> private void LoginClient(MpClient client, LoginRequestMessage message) { bool isLoggedIn = false; Message response; if (string.IsNullOrEmpty(message.Login) || string.IsNullOrEmpty(message.Password) || message.Login.Length > 20 || message.Password.Length > 30) { response = new LoginRegisterResponseMessage { Response = LoginRegisterResponse.Error }; } else if (usersHandler.GetOnlineUser(message.Login) != null) { response = new LoginRegisterResponseMessage { Response = LoginRegisterResponse.AlreadyLogin }; } else { int id; // client's id in db if (DBoperations.Login(message.Login, message.Password, out id)) { log.Info($"Client login: {message.Login}"); // user is online OnlineUser user = new OnlineUser(id, message.Login, client); usersHandler.AddUser(user); isLoggedIn = true; response = new LoginRegisterResponseMessage { Response = LoginRegisterResponse.Success }; } else { response = new LoginRegisterResponseMessage { Response = LoginRegisterResponse.Fail }; } } try { // response to client client.SendMessage(response); } catch (ConnectionInterruptedException e) { log.Error(e); } // close connection with client if client not logged in if (!isLoggedIn) { log.Info($"Client disconnected. ip {((IPEndPoint)client.tcpClient.Client.RemoteEndPoint).Address.ToString()}"); try { client.Close(); } catch (ConnectionInterruptedException e) { log.Error(e); } } }
/// <summary> /// Listen to user's messages. /// </summary> /// <param name="user">user.</param> private void UserListener(OnlineUser user) { while (true) { Message message; try { // user's incoming message message = user.Client.ReceiveMessage(); } // user disconnected catch (ConnectionInterruptedException) { if (onlineUsers.Contains(user)) { Logout(user); } break; } // process message try { if (message is GetNotificationsMessage) { SendNotifications(user); } if (message is GetAllUsersMessage) { SendAllUsers(user); } else if (message is GetFriendsMessage) { SendFriends(user); } else if (message is GetIncomeFriendshipRequestsMessage) { SendIncomeFriendshipRequests(user); } else if (message is GetOutcomeFriendshipRequestsMessage) { SendOutcomeFriendshipRequests(user); } else if (message is GetConversationMessage) { SendConversation(user, ((GetConversationMessage)message).Interlocutor); } else if (message is FriendshipRequestMessage) { SetFriendshipRequest(user, ((FriendshipRequestMessage)message).LoginOfNeededUser); } else if (message is NewReplyMessage) { HandleReply(user, ((NewReplyMessage)message).Interlocutor, ((NewReplyMessage)message).Text); } else if (message is UserActionMessage) { UserActionMessage msg = (UserActionMessage)message; switch (msg.Action) { case UserActions.CancelFriendshipRequest: CancelFriendshipRequest(user, msg.UserLogin); break; case UserActions.AcceptFriendship: AcceptFriendshipRequest(user, msg.UserLogin); break; case UserActions.RejectFriendship: RejectFriendshipRequest(user, msg.UserLogin); break; case UserActions.RemoveFromFriends: RemoveFriend(user, msg.UserLogin); break; default: break; } } } catch (ConnectionInterruptedException e) { log.Error($"Connection with client '{user.Login}' brokes.", e); } } }