private void SaveMessage(Message message) { var sender = _participants.FirstOrDefault(p => p.Id == message.Sender); using (var database = new RozmawiatorDb()) { var senderUser = database.Users.FirstOrDefault(u => u.UserName == sender.Nickname); if (senderUser == null) { return; } var conversation = database.Conversations.First(c => c.Id == _conversationId); var msg = new Database.Entities.Message { Content = message.GetTextContent(), Conversation = conversation, Sender = senderUser, Timestamp = DateTime.Now }; database.Messages.Add(msg); database.SaveChanges(); } }
public void Join(Client client) { _participants.Add(client); using (var database = new RozmawiatorDb()) { var user = database.Users.Select(u => new { u.Id, u.UserName }) .FirstOrDefault(u => u.UserName == client.Nickname); if (user != null) { var conversation = database.Conversations.First(c => c.Id == _conversationId); var participant = conversation.ConversationParticipants.FirstOrDefault(p => p.UserId == user.Id); if (participant != null) { participant.IsActive = true; } else { participant = new ConversationParticipant { Conversation = conversation, UserId = user.Id }; conversation.ConversationParticipants.Add(participant); } } database.SaveChanges(); } Broadcast(new Message(client.Id, 0, Message.MessageType.HelloConversation, client.Nickname)); ParticipantsUpdate?.Invoke(this); }
private void HandleHello(IPEndPoint endpoint, Message message) { var client = GetClient(endpoint); if (client != null) { Debug($"Client with endpoint {endpoint.Address}:{endpoint.Port} already on list ({client.Nickname})."); return; } var nickname = message.GetTextContent(); using (var database = new RozmawiatorDb()) { var user = database.Users.FirstOrDefault(u => u.UserName == nickname); if (user == null) { Debug($"Client {nickname} with endpoint {endpoint.Address}:{endpoint.Port} does not exist in database."); return; } } var newClient = AddClient(endpoint, nickname); Send(newClient, Message.Hello(Configuration.Host.Name)); Debug($"{nickname} connected ({endpoint.Address}:{endpoint.Port})"); ClientConnected?.Invoke(newClient); }
public void Start() { using (var database = new RozmawiatorDb()) { var server = database.Servers.Find(_serverGuid); if (server == null) { server = new Database.Entities.Server { Id = _serverGuid, }; database.Servers.Add(server); } server.IpAddress = "192.168.88.19"; server.Port = Configuration.Host.ListenPort; server.State = ServerState.Online; database.SaveChanges(); } Port = Configuration.Host.ListenPort; TimeoutSpan = Configuration.Client.Timeout; _listener = new UdpClient(Port); _clients.Clear(); _conversations.Clear(); State = ListenerState.Listening; Task.Factory.StartNew(ListenLoop); }
public void Stop() { using (var database = new RozmawiatorDb()) { var server = database.Servers.Find(_serverGuid); if (server != null) { server.State = ServerState.Offline; database.SaveChanges(); } } foreach (var conversation in _conversations.ToArray()) { conversation.Close(); } foreach (var client in _clients.ToArray()) { RemoveClient(client); } State = ListenerState.Idle; _listener.Close(); }
private void SaveCall(Database.Entities.CallRequest callRequest) { using (var database = new RozmawiatorDb()) { database.CallRequests.Add(callRequest); database.SaveChanges(); } }
private void HandleCall(Client sender, Message message) { var calledNickname = message.GetTextContent(); var calledUser = GetClient(calledNickname); var callRequest = new Database.Entities.CallRequest { State = CallRequestState.NoResponse }; using (var database = new RozmawiatorDb()) { var callee = database.Users.Select(u => new { u.Id, u.UserName }).FirstOrDefault(u => u.UserName == calledNickname); var caller = database.Users.Select(u => new { u.Id, u.UserName }) .FirstOrDefault(u => u.UserName == sender.Nickname); callRequest.CalleeId = callee?.Id ?? Guid.Empty; callRequest.CallerId = caller?.Id ?? Guid.Empty; } Debug($"{sender.Nickname} is trying to call {calledNickname} ({sender.EndPoint.Address}:{sender.EndPoint.Port} -> ?)"); if (calledUser == null) { Debug($"{sender.Nickname} was trying to call {calledNickname}, but {calledNickname} is offline."); Send(sender, Message.CallResponse(0, 0, Message.CallResponseType.TargetIsOffline)); SaveCall(callRequest); return; } var conversation = GetInitiatedConversation(sender); if (conversation == null) { var currentConversation = GetConversation(sender); currentConversation?.Disconnect(sender); conversation = NewConversation(sender); } SaveCall(callRequest); conversation.AddRequest(calledUser); conversation.SendRequests(); }
public void Disconnect(Client client) { Server.Debug($"{client.Nickname} disconnected from {Owner.Nickname}'s conversation."); _participants.Remove(client); using (var database = new RozmawiatorDb()) { var conversation = database.Conversations.First(c => c.Id == _conversationId); if (Owner == client) { Owner = _participants.FirstOrDefault(); if (Owner != null) { var newOwnerUser = database.Users.Select(u => new { u.Id, u.UserName }) .FirstOrDefault(u => u.UserName == Owner.Nickname); conversation.OwnerId = newOwnerUser?.Id ?? Guid.Empty; } } var user = database.Users.Select(u => new { u.Id, u.UserName }) .FirstOrDefault(u => u.UserName == client.Nickname); if (user != null) { var conversationParticipant = conversation.ConversationParticipants.FirstOrDefault(p => p.UserId == user.Id); if (conversationParticipant != null) { conversationParticipant.IsActive = false; } } database.SaveChanges(); } //Broadcast(new Message(client.Id, 0, Message.MessageType.ByeConversation, client.Nickname)); Server.SendAsClient(client, _participants, new Message(Message.MessageType.ByeConversation, client.Nickname)); ParticipantsUpdate?.Invoke(this); TryClose(); }
public Conversation(int id, Listener server, Client owner) { Id = id; Owner = owner; Server = server; _participants = new List <Client> { owner }; _callRequests = new List <CallRequest>(); using (var database = new RozmawiatorDb()) { var ownerUser = database.Users.FirstOrDefault(u => u.UserName == owner.Nickname); if (ownerUser == null) { return; } var conversation = new Database.Entities.Conversation { Type = ConversationType.Active, Owner = ownerUser, Creator = ownerUser, ConversationParticipants = new[] { new ConversationParticipant { User = ownerUser } } }; _conversationId = conversation.Id; database.Conversations.Add(conversation); database.SaveChanges(); } }
private void HandleCallResponse(Client sender, Message message) { var callingClient = GetClient(message.Receiver); if (callingClient == null) { Debug($"{sender.Nickname} was trying to respond to call, but caller is offline."); Send(sender, Message.CallResponse(0, 0, Message.CallResponseType.TargetIsOffline)); return; } var conversation = GetConversation(callingClient); if (conversation == null) { Debug($"{sender.Nickname} was trying to respond to {callingClient.Nickname}'s call, but the conversation no longer exists."); Send(sender, Message.CallResponse(0, 0, Message.CallResponseType.ExpiredCall)); return; } var request = conversation.GetRequest(callingClient, sender); if (request == null) { Debug($"{sender.Nickname} was trying to respond to {callingClient.Nickname}'s call, but the request no longer exists."); Send(sender, Message.CallResponse(0, 0, Message.CallResponseType.ExpiredCall)); return; } var response = request.ResolveRequest(message); switch (response) { case Message.CallResponseType.RequestDenied: Debug($"{sender.Nickname} declined {callingClient.Nickname}'s call."); break; case Message.CallResponseType.RequestAccepted: var currentConversation = GetConversation(sender); currentConversation?.Disconnect(sender); conversation.Join(sender); Debug($"{sender.Nickname} joined {callingClient.Nickname}'s conversation."); break; default: Debug($"Exception: Caller: {callingClient.Nickname}, Target: {sender.Nickname} - unexpected message {response}"); break; } using (var database = new RozmawiatorDb()) { var content = message.GetTextContent(); var lastTimestamp = database.CallRequests.Where( c => c.Callee.UserName == sender.Nickname).Max(c => c.Timestamp); /* * var callRequest = * database.CallRequests.LastOrDefault( * c => c.Callee.UserName == sender.Nickname && c.Caller.UserName == content); */ var callRequest = database.CallRequests.FirstOrDefault(c => c.Timestamp == lastTimestamp); if (callRequest != null) { callRequest.State = response == Message.CallResponseType.RequestAccepted ? CallRequestState.RequestAccepted : CallRequestState.RequestDenied; database.SaveChanges(); } } SendAsClient(sender, callingClient, Message.CallResponse(0, 0, response)); conversation.RemoveRequests(); }
private void HandleDirectText(Client sender, Message message) { if (sender == null) { return; } var targetNickname = message.GetDirectTextNickname(); var targetClient = GetClient(targetNickname); if (targetClient == null) { Debug($"Undelivered message from {sender.Nickname} to {targetNickname}, target client offline."); return; } using (var database = new RozmawiatorDb()) { var conversation = database.Conversations.FirstOrDefault( c => c.ConversationParticipants.Any(cp => cp.User.UserName == targetNickname)); var senderUser = database.Users.FirstOrDefault(u => u.UserName == sender.Nickname); if (senderUser == null) { SendAsClient(sender, targetClient, message); return; } if (conversation == null) { var targetUser = database.Users.FirstOrDefault(u => u.UserName == targetNickname); if (targetUser == null) { SendAsClient(sender, targetClient, message); return; } conversation = new Database.Entities.Conversation { Type = ConversationType.Passive, ConversationParticipants = new[] { new ConversationParticipant { User = senderUser }, new ConversationParticipant { User = targetUser } } }; database.Conversations.Add(conversation); } var msg = new Database.Entities.Message { Conversation = conversation, Content = message.GetDirectTextContent(), Timestamp = DateTime.Now, Sender = senderUser }; database.Messages.Add(msg); database.SaveChanges(); } var forwardMessage = new Message().DirectText(sender.Nickname, message.GetDirectTextContent()); //SendAsClient(sender, targetClient, message); SendAsClient(sender, targetClient, forwardMessage); }