public async Task<SendMessageResult> SendMessageAsync(Message message) { try { Dictionary<string, byte[]> keys = null; string text = message.Text; await messageRepository.AddMessageAsync(message); if (EncryptionEnabled) { var deviceIdAndPublicKeyMap = await deviceInfoProvider.GetUserDevicesAndPublicKeys((int) message.Recipient); if (deviceIdAndPublicKeyMap.Count > 0) { //don't forget current user's other devices var myDevices = await deviceInfoProvider.GetUserDevicesAndPublicKeys(Settings.MyId); foreach (var myDevice in myDevices) { if (myDevice.Key != Settings.UserDeviceId && myDevice.Key != Settings.MyId.ToString()) deviceIdAndPublicKeyMap[myDevice.Key] = myDevice.Value; } text = cryptoService.Encrypt(message.Text, deviceIdAndPublicKeyMap, out keys); } } var request = new SendMessageRequest { ReceiverUserId = message.Recipient, SenderName = Settings.NickName, MessageType = ServerClient.Entities.Ws.Requests.MessageType.Text, MessageToken = message.MessageToken, Thumbnail = message.Thumbnail, GroupId = message.GroupId, Message = text, Keys = keys, }; var response = await messagingService.SendMessage(request); if (response.Error == Errors.SendMessage_ProvideKeysForTheseDevices) { foreach (var item in response.MissedDevicesWithPublicKeysToReEncrypt) { await deviceInfoProvider.SavePublicKeyForDeviceId(item.DeviceId, item.UserId, Convert.ToBase64String(item.PublicKey)); } //try again return await SendMessageAsync(message); } if (response.Error == Errors.SendMessage_ReceiversNotFound) { return SendMessageResult.ReceiverUnknown; } if (response.Error == Errors.SendMessage_ReceiverAndSenderAreSame) { return SendMessageResult.ReceiverAndSenderAreSame; } OnMessageSent(message.MessageToken); return SendMessageResult.Ok; } catch (ConnectionException) { return SendMessageResult.ConnectionError; } catch (Exception ex) { App.Logger.Report (ex); return SendMessageResult.UnknownError; } }
public SendMessageResponse SendMessage(ISession session, SendMessageRequest request) { var response = request.CreateResponse<SendMessageResponse>(); Logger.Info("SendMessage from Id={0} (Device={1}) to Id={2} ({3} devices)", session.UserId, session.DeviceId.Cut(), request.ReceiverUserId, request.Keys != null ? request.Keys.Count : -1); Dictionary<string, long> actualMessageReceiversDevices = null; Dictionary<string, byte[]> keys = request.Keys; if (request.GroupId != Guid.Empty)// group conversation { var groupChat = _groupChatsRepository.GetChat(request.GroupId); //sender is in the group? if (groupChat.Participants.All(i => i.UserId != session.UserId)) { response.Success = false; response.Error = Errors.YouAreNotParticipantOfThatGroup; return response; } if (keys == null) //means not encrypted { keys = groupChat.Participants .SelectMany(p => p.Devices) .Where(p => p != session.DeviceId) .Distinct() .ToDictionary<string, string, byte[]>(k => k, v => null); //null value means unencrypted } else { //it means we will check all provided devices below (see if (actualMessageReceiversDevices != null)) -- just to avoid copy-paste actualMessageReceiversDevices = new Dictionary<string, long>(); foreach (var groupChatParticipant in groupChat.Participants) { foreach (var device in groupChatParticipant.Devices) { actualMessageReceiversDevices[device] = groupChatParticipant.UserId; } } } } else // private conversation { if (request.ReceiverUserId == session.UserId) { response.Success = false; response.Error = Errors.SendMessage_ReceiverAndSenderAreSame; return response; } if (keys == null)//means not encrypted { keys = _devicesRepository.GetDevices(request.ReceiverUserId).ToDictionary<string, string, byte[]>(k => k, v => null); } else { //it means we will check all provided devices below (see if (actualMessageReceiversDevices != null)) -- just to avoid copy-paste actualMessageReceiversDevices = _devicesRepository.GetDevices(request.ReceiverUserId).ToDictionary(k => k, v => request.ReceiverUserId); } } if (actualMessageReceiversDevices != null) //TODO: uncoment later { var providedDevices = keys.Select(i => i.Key); List<string> union; List<string> notProvidedDevices; //conversation has more devices than user provided as targets List<string> wrongDevices; //some of the devices user provided are not members of that conversation actualMessageReceiversDevices.Select(i => i.Key) .FindIntersectionAndDifference(providedDevices, out union, out notProvidedDevices, out wrongDevices); if (notProvidedDevices.Any()) { response.Success = false; response.Error = Errors.SendMessage_ProvideKeysForTheseDevices; //we will help the user - provide public keys as well response.MissedDevicesWithPublicKeysToReEncrypt = notProvidedDevices .Where(d => session.DeviceId != d) .Select(d => new PublicKeyInfo { DeviceId = d, PublicKey = _devicesRepository.GetPublicKeyForDevice(d), UserId = actualMessageReceiversDevices[d] }) .ToList(); return response; } //cut receivers not in the conversation //TODO: uncomment it later /*foreach (var key in wrongDevices) { keys.Remove(key); }*/ } keys.Remove(session.DeviceId); if (keys.Count < 1) { response.Success = false; response.Error = Errors.SendMessage_ReceiversNotFound; return response; } foreach (var key in keys) { var innerMsg = new Message { SenderAccessToken = session.AccessToken, Text = request.Message, GroupId = request.GroupId, SenderId = session.UserId, SenderDeviceId = session.DeviceId, SenderName = request.SenderName, ReceiverId = request.ReceiverUserId, MessageTypeId = (int)request.MessageType, Thumbnail = request.Thumbnail, ReceiverDeviceId = key.Key, EncryptionKey = key.Value, MessageToken = request.MessageToken, }; _messageEventManager.DeliverEventToDevice(innerMsg); } return response; }
private static async void ProcessConsoleCommand(string line) { var args = new List<string>(); if (CommandParser.ParseCommand(line, "BeginTyping", 1, ref args)) { var receiverId = long.Parse(args[0]); await messagingService.SendIsTyping(new SendIsTypingRequest { IsTyping = true, Devices = new List<string> { receiverId.ToString() }}); } else if (CommandParser.ParseCommand(line, "EndTyping", 1, ref args)) { var receiverId = long.Parse(args[0]); await messagingService.SendIsTyping(new SendIsTypingRequest { IsTyping = false, Devices = new List<string> { receiverId.ToString() }}); } else if (CommandParser.ParseCommand(line, "CreateGroup", -1, ref args)) { var participants = args .Select(long.Parse) .ToList(); var createGroupChatResponse = await groupChatsService.CreateGroupChat(new CreateGroupChatRequest { GroupName = "Foo", Participants = participants}); Out.WriteLine("Group is created: {0}", createGroupChatResponse.GroupId); } else if (CommandParser.ParseCommand(line, "AddParticipant", -1, ref args)) { var groupId = Guid.Parse(args[0]); await groupChatsService.AddParticipants(new AddParticipantsRequest { GroupId = groupId, ParticipantIds = args.Skip(1).Select(long.Parse).ToList()}); } else if (CommandParser.ParseCommand(line, "KickParticipant", -1, ref args)) { var groupId = Guid.Parse(args[0]); await groupChatsService.KickParticipants(new KickParticipantsRequest { GroupId = groupId, ParticipantIds = args.Skip(1).Select(long.Parse).ToList() }); } else if (CommandParser.ParseCommand(line, "LeaveGroup", 1, ref args)) { var groupId = Guid.Parse(args[0]); await groupChatsService.LeaveGroup(new LeaveGroupRequest {GroupId = groupId}); } else if (CommandParser.ParseCommand(line, "SetGroupName", 2, ref args)) { var groupId = Guid.Parse(args[0]); await groupChatsService.ChangeGroup(new ChangeGroupRequest {GroupId = groupId, NewGroupName = args[1]}); } else if (CommandParser.ParseCommand(line, "GetGroupInfo", 1, ref args)) { var groupId = Guid.Parse(args[0]); var getGroupChatInfoResponse = await groupChatsService.GetGroupChatInfo(new GetGroupChatInfoRequest {GroupId = groupId}); Out.WriteLine("GetGroupInfo: Name={0}, Participants.Count={1}", getGroupChatInfoResponse.GroupInfo.Name, getGroupChatInfoResponse.GroupInfo.Participants.Count); } else if (CommandParser.ParseCommand(line, "GetMyGroups", 0, ref args)) { var getGroupsResponse = await groupChatsService.GetGroups(new GetGroupsRequest()); Out.WriteLine("GetMyGroup: Groups.Count={0}", getGroupsResponse.Groups); } //private message else if (CommandParser.ParseCommand(line, "SendMessage", 2, ref args)) { var receiverId = long.Parse(args[0]); string text = args[1]; var sendMsgRequest = new SendMessageRequest { ReceiverUserId = receiverId, Message = text, //Keys = new Dictionary<string, byte[]> { { receiverId.ToString(), new byte[1] } }, MessageToken = Guid.NewGuid(), SenderName = "ConsoleAppFor_" + myUserId }; await messagingService.SendMessage(sendMsgRequest); Out.WriteLine(" server received your message"); } //group message else if (CommandParser.ParseCommand(line, "SendGroupMessage", 2, ref args)) { var groupId = Guid.Parse(args[0]); string text = args[1]; var sendMsgRequest = new SendMessageRequest { ReceiverUserId = 0, GroupId = groupId, Message = text, //Keys = new Dictionary<string, byte[]> { { receiverId.ToString(), new byte[1] } }, MessageToken = Guid.NewGuid(), SenderName = "ConsoleAppFor_" + myUserId }; await messagingService.SendMessage(sendMsgRequest); Out.WriteLine(" server received your message"); } else { Out.WriteLine("Command is not recognized"); } }
public Task<SendMessageResponse> SendMessage(SendMessageRequest request) { return _connectionManager.SendRequestAndWaitResponse<SendMessageResponse>(request); }