예제 #1
0
        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();
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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();
        }
예제 #6
0
 private void SaveCall(Database.Entities.CallRequest callRequest)
 {
     using (var database = new RozmawiatorDb())
     {
         database.CallRequests.Add(callRequest);
         database.SaveChanges();
     }
 }
예제 #7
0
        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();
        }
예제 #8
0
        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();
        }
예제 #9
0
        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();
            }
        }
예제 #10
0
        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();
        }
예제 #11
0
        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);
        }