public static void MessageToServer(ChatTwo_Protocol.MessageType type, byte[] data = null, string text = null) { Message message = new Message(); if (_user != null) { message.From = _user.ID; } else { message.From = Int32.MaxValue; } message.To = ChatTwo_Protocol.ServerReserrvedUserID; message.Type = type; if (data != null && data.Length != 0) { message.Data = data; } if (!String.IsNullOrEmpty(text)) { message.Text = text; } message.Ip = _serverAddress; MessageTransmissionHandler(message); }
public static void MessageToIp(IPEndPoint toIp, ChatTwo_Protocol.MessageType type, byte[] data = null, string text = null) { Message message = new Message(); message.From = ChatTwo_Protocol.ServerReserrvedUserID; message.Type = type; if (data != null && data.Length != 0) { message.Data = data; } if (!String.IsNullOrEmpty(text)) { message.Text = text; } message.Ip = toIp; MessageTransmissionHandler(message); }
public static void MessageToUser(int to, ChatTwo_Protocol.MessageType type, byte[] data = null, string text = null) { Message message = new Message(); message.From = _user.ID; message.To = to; message.Type = type; if (data != null && data.Length != 0) { message.Data = data; } if (!String.IsNullOrEmpty(text)) { message.Text = text; } if (_contacts.Any(x => x.ID == to)) { message.Ip = _contacts.Find(x => x.ID == to).Socket; } MessageTransmissionHandler(message); }
public static void MessageReceivedHandler(object sender, PacketReceivedEventArgs args) { if (args.Data[0] == 0x92) { string sharedSecret; // Position of the Type byte is 30 (SignatureByteLength + MacByteLength + TimezByteLength + UserIdByteLength). ChatTwo_Protocol.MessageType type = (ChatTwo_Protocol.MessageType)args.Data[ChatTwo_Protocol.SignatureByteLength + ByteHelper.HashByteLength + 4 + 4]; // Position of the UserID bytes is 26 (SignatureByteLength + MacByteLength + TimezByteLength) with a length of 4. int senderId = ByteHelper.ToInt32(args.Data, ChatTwo_Protocol.SignatureByteLength + ByteHelper.HashByteLength + 4); if (type == ChatTwo_Protocol.MessageType.CreateUserReply) { sharedSecret = ChatTwo_Protocol.DefaultSharedSecret; } else if (senderId == 0) { sharedSecret = ServerSharedSecret; } else { sharedSecret = _contacts.Find(x => x.ID == senderId).Secret; // Testing!!!! REMOVE THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sharedSecret = ChatTwo_Protocol.DefaultSharedSecret; } if (ChatTwo_Protocol.ValidateMac(args.Data, sharedSecret)) { Message message = ChatTwo_Protocol.MessageReceivedHandler(args); switch (message.Type) { case ChatTwo_Protocol.MessageType.CreateUserReply: { // Fire an OnCreateUserReply event. CreateUserReplyEventArgs argsCreateUser = new CreateUserReplyEventArgs(); argsCreateUser.Success = message.Data[0] == 0x00; switch (message.Data[0]) { case 0: // Success. break; case 1: // Username already exist. argsCreateUser.Message = "A user already exist with that name."; break; case 2: argsCreateUser.Message = "Username is too short or too long."; break; } OnCreateUserReply(argsCreateUser); break; } case ChatTwo_Protocol.MessageType.LoginReply: { // Fire an OnLoginReply event. LoginReplyEventArgs argsLogin = new LoginReplyEventArgs(); argsLogin.Success = message.Data[0] == 0x00; switch (message.Data[0]) { case 0: // Success. int userId = ByteHelper.ToInt32(message.Data, 1); string username = Encoding.Unicode.GetString(ByteHelper.SubArray(message.Data, 5)); LogIn(userId); _user.Name = username; argsLogin.Name = username; break; case 1: // Wrong password. argsLogin.Message = "Wrong username or password."; break; case 2: // Already online. argsLogin.Message = "That user is already online."; break; } OnLoginReply(argsLogin); break; } case ChatTwo_Protocol.MessageType.ContactRequestReply: { // Fire an OnAddContactReply event. AddContactReplyEventArgs argsAddContact = new AddContactReplyEventArgs(); argsAddContact.Success = message.Data[0] == 0x00; switch (message.Data[0]) { case 0: // Success. break; case 1: // No user with that name. argsAddContact.Message = "No user with that name."; break; case 2: // You can't add your self. argsAddContact.Message = "You can't add your self."; break; case 3: // User is already a contact. argsAddContact.Message = "User is already a contact."; break; } OnAddContactReply(argsAddContact); break; } case ChatTwo_Protocol.MessageType.ContactStatus: { int contactId = ByteHelper.ToInt32(message.Data, 0); int nameLength = ((31 & message.Data[4]) * 2); ContactObj contact; if (_contacts.Any(x => x.ID == contactId)) { contact = _contacts.Find(x => x.ID == contactId); } else { contact = new ContactObj(); contact.ID = contactId; contact.Name = Encoding.Unicode.GetString(message.Data, 5, nameLength); _contacts.Add(contact); } contact.Online = ByteHelper.CheckBitCodeIndex(message.Data[4], 7); contact.RelationshipTo = ByteHelper.CheckBitCodeIndex(message.Data[4], 6); contact.RelationshipFrom = ByteHelper.CheckBitCodeIndex(message.Data[4], 5); if (contact.Online) { int port = ByteHelper.ToInt32(message.Data, 5 + nameLength); contact.Socket = new IPEndPoint(new IPAddress(ByteHelper.SubArray(message.Data, 5 + nameLength + 4)), port); } // Fire an OnContactUpdate event. OnContactUpdate(); break; } case ChatTwo_Protocol.MessageType.Message: { ContactObj contact; if (_contacts.Any(x => x.ID == message.From && x.RelationshipTo && x.RelationshipFrom)) { contact = _contacts.Find(x => x.ID == message.From); OpenChat(contact.ID); message.Text = Encoding.Unicode.GetString(message.Data); contact.ChatWindow.ReceiveMessage(message.Text); } else #if DEBUG { throw new NotImplementedException("You received a message from someone that isn't your contact?"); } #else { return; } #endif break; } } } #if DEBUG else { throw new NotImplementedException("Could not validate the MAC of received message."); } // Need to add a simple debug message here, but this works as a great breakpoint until then. #endif } #if DEBUG else { throw new NotImplementedException("Could not validate the signature of the received message. The signature was \"0x" + args.Data[0] + "\" but only \"0x92\" is allowed."); } // Need to add a simple debug message here, but this works as a great breakpoint until then. #endif }
public static void MessageReceivedHandler(object sender, PacketReceivedEventArgs args) { if (!DatabaseCommunication.Active) #if DEBUG { throw new NotImplementedException("Database connection was not active and a reply for this have not been implemented yet."); } // Need to add a simple debug message here, but this works as a great breakpoint until then. // Also need to make some kind of error message I can send back to the client. #else { return; } #endif if (args.Data[0] == 0x92) { string sharedSecret; // Position of the Type byte is 30 (SignatureByteLength + MacByteLength + TimezByteLength + UserIdByteLength). ChatTwo_Protocol.MessageType type = (ChatTwo_Protocol.MessageType)args.Data[ChatTwo_Protocol.SignatureByteLength + ByteHelper.HashByteLength + 4 + 4]; // Position of the UserID bytes is 26 (SignatureByteLength + MacByteLength + TimezByteLength) with a length of 4. int userId = ByteHelper.ToInt32(args.Data, ChatTwo_Protocol.SignatureByteLength + ByteHelper.HashByteLength + 4); if (type == ChatTwo_Protocol.MessageType.CreateUser) { sharedSecret = ChatTwo_Protocol.DefaultSharedSecret; } else if (type == ChatTwo_Protocol.MessageType.Login) { #if DEBUG byte[] test = ByteHelper.SubArray(args.Data, ChatTwo_Protocol.SignatureByteLength + ByteHelper.HashByteLength + 4); #endif // Don't take the Timez as part of the sharedSecret. This is mostly because of a problem I have in the client where I make the sharedSecrt before I add the Timez. sharedSecret = ByteHelper.GetHashString(ByteHelper.SubArray(args.Data, ChatTwo_Protocol.SignatureByteLength + ByteHelper.HashByteLength + 4)); } else { if (!_users.Any(x => x.ID == userId)) { return; // This is mostly to prevent clients with a connection to a previces server instants from crashing the server. Need to fix this. } sharedSecret = _users.Find(x => x.ID == userId).Secret; } if (ChatTwo_Protocol.ValidateMac(args.Data, sharedSecret)) { Message message = ChatTwo_Protocol.MessageReceivedHandler(args); switch (message.Type) { case ChatTwo_Protocol.MessageType.CreateUser: { string passwordHash = Convert.ToBase64String(message.Data, 0, ByteHelper.HashByteLength); string username = Encoding.Unicode.GetString(ByteHelper.SubArray(message.Data, ByteHelper.HashByteLength)); if (username.Length < 1 || username.Length > 30) { // Username is too short or too long. MessageToIp(message.Ip, ChatTwo_Protocol.MessageType.CreateUserReply, new byte[] { 0x02 }); return; } bool worked = DatabaseCommunication.CreateUser(username, passwordHash); if (!worked) { // Some error prevented the user from being created. Best guess is that a user with that name already exist. MessageToIp(message.Ip, ChatTwo_Protocol.MessageType.CreateUserReply, new byte[] { 0x01 }); return; } // Uesr creation was successful! MessageToIp(message.Ip, ChatTwo_Protocol.MessageType.CreateUserReply, new byte[] { 0x00 }); break; } case ChatTwo_Protocol.MessageType.Login: { string passwordHash = Convert.ToBase64String(message.Data, 0, ByteHelper.HashByteLength); string username = Encoding.Unicode.GetString(ByteHelper.SubArray(message.Data, ByteHelper.HashByteLength)); UserObj user = DatabaseCommunication.LoginUser(username, passwordHash); if (user == null) { // Have to send back a LoginReply message here with a "wrong username/password" error. _tempUsers.Add(message.Ip, sharedSecret); MessageToIp(message.Ip, ChatTwo_Protocol.MessageType.LoginReply, new byte[] { 0x01 }); return; } if (_users.Any(x => x.ID == user.ID)) { // Have to send back a LoginReply message here with a "User is already online" error. _tempUsers.Add(message.Ip, sharedSecret); MessageToIp(message.Ip, ChatTwo_Protocol.MessageType.LoginReply, new byte[] { 0x02 }); return; } user.Secret = sharedSecret; user.Socket = message.Ip; user.Online = true; _users.Add(user); MessageToUser(user.ID, ChatTwo_Protocol.MessageType.LoginReply, ByteHelper.ConcatinateArray(new byte[] { 0x00 }, BitConverter.GetBytes(user.ID)), user.Name); UserConnect(user); break; } case ChatTwo_Protocol.MessageType.Status: { UserObj user = _users.Find(x => x.ID == message.From); if (user != null) // If the user is not found, don't do anything. (Can this happen?) { if (!IPEndPoint.Equals(user.Socket, message.Ip)) { user.Socket = message.Ip; // Message all contacts of the user with the new IP change. TellMutualContactsAboutUserStatusChange(user.ID); } DatabaseCommunication.UpdateUser(user.ID, user.Socket); } break; } case ChatTwo_Protocol.MessageType.ContactRequest: { string username = Encoding.Unicode.GetString(message.Data); UserObj user = DatabaseCommunication.LookupUser(username); if (user == null) { // Have to send back a ContactRequestReply message here with a "No user with that name" error. MessageToUser(message.From, ChatTwo_Protocol.MessageType.ContactRequestReply, new byte[] { 0x01 }); return; } if (user.ID == message.From) { // Have to send back a ContactRequestReply message here with a "You can't add your self" error. MessageToUser(message.From, ChatTwo_Protocol.MessageType.ContactRequestReply, new byte[] { 0x02 }); return; } bool added = DatabaseCommunication.AddContact(message.From, user.ID); if (!added) { // Have to send back a ContactRequestReply message here with a "User is already a contact" error. MessageToUser(message.From, ChatTwo_Protocol.MessageType.ContactRequestReply, new byte[] { 0x03 }); return; } MessageToUser(message.From, ChatTwo_Protocol.MessageType.ContactRequestReply, new byte[] { 0x00 }); //if (_users.Any(x => x.ID == user.ID)) // TellContactsAboutUserStatusChange(message.From, true); // Need to figure this out. break; } } } #if DEBUG else { throw new NotImplementedException("Could not validate the MAC of the received message."); } // Need to add a simple debug message here, but this works as a great breakpoint until then. #endif } #if DEBUG else { throw new NotImplementedException("Could not validate the signature of the received message. The signature was \"0x" + args.Data[0] + "\" but only \"0x92\" is allowed."); } // Need to add a simple debug message here, but this works as a great breakpoint until then. #endif }