//every client runs on its own thread. //File send and receives also runs on its own thread. this is to keep GUI responsive. private void recvMessage(object s) { ConnectedClient client = (ConnectedClient)s; bool bRecvMessage = true; while (bRecvMessage) { try { nBuffer buffer = new nBuffer(); int ReadBytes; if ((ReadBytes = buffer.ReceiveCryptoBuffer(client.socket, client.CC.Salt)) > 0) { #region RecvClientSettings if (buffer.GetID() == MsgType.ClientSettings) { Console.WriteLine(client.socket.RemoteEndPoint.ToString() + ": Received Client settings"); ClientSettings CSettings; CSettings = buffer.GetObject <ClientSettings>(); CSettings.Ip = client.CC.Ip; bool InGroupList = false; for (int i = 0; i < ConnectedClients.Count(); i++) { if (ConnectedClients[i].CC.Ip == client.CC.Ip) { Console.WriteLine(ConnectedClients[i].Name + " Renamed to: " + CSettings.Name); ConnectedClients[i].Name = CSettings.Name; } } client.Groups = CSettings.Groups; string[] tmpGroups = CSettings.Groups.Split(';'); foreach (string group in tmpGroups) { if (group != "") { InGroupList = false; for (int i = 0; i < ChatGroupsContainer.Instance.Count; i++) { if (group == ChatGroupsContainer.Instance.at(i).GroupName) { InGroupList = true; // group is already in chatrgrouplist, } } if (!InGroupList) { ChatGroup cGroup = new ChatGroup(); cGroup.GroupName = group; ChatGroupsContainer.Instance.Add(cGroup); AddGroupToDataGridview(cGroup); Console.WriteLine("Group " + group + " Added to List"); } // check if user is in group, else add it, and check if name updated; for (int i = 0; i < ChatGroupsContainer.Instance.Count; i++) { bool UserInList = false; if (ChatGroupsContainer.Instance.at(i).GroupName == group) { for (int j = 0; j < ChatGroupsContainer.Instance.at(i).Members.Count; j++) { if (ChatGroupsContainer.Instance.at(i).Members[j].Ip == CSettings.Ip) // Member is in list { UserInList = true; ChatGroupsContainer.Instance.at(i).Members[j].Name = CSettings.Name; // update name. } } if (!UserInList) { ChatGroupsContainer.Instance.at(i).Members.Add(CSettings); Console.WriteLine(CSettings.Name + " Added to: " + ChatGroupsContainer.Instance.at(i).GroupName); } } } } } // check all groups if it has the user, if it does, check if the user has specified the group, else delete it from that group for (int j = 0; j < ChatGroupsContainer.Instance.Count; j++) { bool UserInGroup = false; bool UserSpecifiedGroup = false; int IndexOfUser = -1; for (int i = 0; i < ChatGroupsContainer.Instance.WholeList[j].Members.Count; i++) { if (ChatGroupsContainer.Instance.at(j).Members[i].Ip == CSettings.Ip) // client is in the group { UserInGroup = true; foreach (string Cgroups in tmpGroups) // check if groupname is also specified by teh client; { if (Cgroups == ChatGroupsContainer.Instance.at(j).GroupName) { UserSpecifiedGroup = true; } } if (!UserSpecifiedGroup) { IndexOfUser = i; } } } if (UserInGroup && !UserSpecifiedGroup) // user is in chatgroup but not specified in tmpgroups. { ChatGroupsContainer.Instance.at(j).Members.RemoveAt(IndexOfUser); } } UpdateClientList(); } #endregion #region RecvTextMessage if (buffer.GetID() == MsgType.TextMessage) { Console.WriteLine(client.socket.RemoteEndPoint.ToString() + ": Received TextMessage"); TextMessage TM = buffer.GetObject <TextMessage>(); PassMessage(TM); if (LogChatMessages.Checked) { MessageLogger.LOG(TM, ChatGroupsContainer.Instance.WholeList); } } #endregion #region FileRecv/Send if (buffer.GetID() == MsgType.SendFile) // Server Receives file { PrepareFileSend PFS = buffer.GetObject <PrepareFileSend>(); Console.WriteLine(client.socket.RemoteEndPoint.ToString() + ": Send File -> " + PFS.FileName + PFS.Ext); buffer.innerbuffer.Clear(); buffer.ReceiveCryptoFileBuffer(client.socket, client.CC.Salt); ServerFile SF = buffer.GetObject <ServerFile>(0); // Encrypt current password into file; byte[] Passwordbytes = Crypt.Base64Encode(BinaryFilesPassword); byte[] binaryfile = new byte[Passwordbytes.Length + SF.BinaryFile.Length]; Buffer.BlockCopy(Passwordbytes, 0, binaryfile, 0, Passwordbytes.Length); Buffer.BlockCopy(SF.BinaryFile, 0, binaryfile, Passwordbytes.Length, SF.BinaryFile.Length); // copy binary file; binaryfile = Crypt.Encrypt(binaryfile, BinaryFilesKey, BinaryFilesPassword); // encrypt file and store it. string Path = Utils.AssemblyDirectory + "\\" + PFS.FileName + PFS.Ext + ".scbd"; FileStream fs = null; if (File.Exists(Path)) { fs = new FileStream(Path, FileMode.Truncate, FileAccess.ReadWrite); // overwrite file } else { fs = new FileStream(Path, FileMode.OpenOrCreate, FileAccess.ReadWrite); // create new; } if (fs.CanWrite) { fs.Write(binaryfile, 0, binaryfile.Length); } fs.Close(); fs.Dispose(); SF.length = binaryfile.Length; SF.Ext = PFS.Ext; binaryfile = null; // now we need to notify clients that there is a file for them. TextMessage TM = new TextMessage(); TM.To = PFS.to; TM.From = PFS.from; TM.ID = ChatBufferMessageType.Link; TM.Message = PFS.FileName + PFS.Ext; PassMessage(TM); buffer.innerbuffer.Clear(); buffer.AddID(MsgType.FileSendComplete); FileSendComplete FSC = new FileSendComplete(); FSC.complete = true; buffer.AddObject(FSC); buffer.SendCryptoBuffer(client.socket, client.CC.Salt); } #endregion #region File Request Awsering if (buffer.GetID() == MsgType.RequestFile) // Client requests file from server { bool NoFile = true; RequestFile RF = buffer.GetObject <RequestFile>(); Console.WriteLine(client.socket.RemoteEndPoint.ToString() + ": Request File -> " + RF.Name); buffer.innerbuffer.Clear(); byte[] binaryfile = new byte[] { }; string Path = Utils.AssemblyDirectory + "\\" + RF.Name + ".scbd"; if (File.Exists(Path)) { binaryfile = Crypt.Decrypt(File.ReadAllBytes(Path), BinaryFilesKey, BinaryFilesPassword); byte[] passwordbytes = Crypt.Base64Encode(BinaryFilesPassword); // get bytes of password byte[] binarypasswordfromfile = new byte[passwordbytes.Length]; // allocate bytes try { // copy length of of current password from binrayfile on disk; Buffer.BlockCopy(binaryfile, 0, binarypasswordfromfile, 0, binarypasswordfromfile.Length); string DecodedBinaryPassword = Crypt.Base64Decode(binarypasswordfromfile); // decode password if (DecodedBinaryPassword == BinaryFilesPassword) // password from file is the same as current password; { Buffer.BlockCopy(binaryfile, passwordbytes.Length, binaryfile, 0, binaryfile.Length - passwordbytes.Length); } else // password was longer/smaller or same length but different chars. { Console.WriteLine("Encrypted password does not match current password, file could not be send to user : "******"Failed to Decrypt file from disk"); Console.WriteLine(ex.Message + "/n/r " + ex.StackTrace); } NoFile = false; PrepareFileSend PFS = new PrepareFileSend(); PFS.filesize = binaryfile.Length; PFS.FileName = RF.Name; PFS.ACK = 0; buffer.AddID(MsgType.SendFile); buffer.AddObject(PFS); buffer.SendCryptoBuffer(client.socket, client.CC.Salt); buffer.innerbuffer.Clear(); buffer.CryptoSize = 0; buffer.ReceiveCryptoBuffer(client.socket, client.CC.Salt); if (buffer.GetID() == MsgType.SendOK) { buffer.innerbuffer.Clear(); ServerFile serverfile = new ServerFile(); string[] splitname = RF.Name.Split('.'); serverfile.Name = splitname[0]; // name serverfile.Ext = splitname[1]; // extension serverfile.BinaryFile = binaryfile; // decrypt file to send it. binaryfile = null; buffer.AddObject(serverfile); Console.WriteLine("Server : " + buffer.SendCryptoBuffer(client.socket, client.CC.Salt) + " bytess of " + RF.Name + " send!"); buffer.innerbuffer.Clear(); } } if (NoFile) { PrepareFileSend PFS = new PrepareFileSend(); PFS.filesize = -1; PFS.FileName = RF.Name; PFS.ACK = 0; buffer.AddID(MsgType.Nofile); buffer.AddObject(PFS); buffer.SendCryptoBuffer(client.socket, client.CC.Salt); buffer.innerbuffer.Clear(); Thread.Sleep(10); } } #endregion #region Reguest Logo if (buffer.GetID() == MsgType.RequestLogo) { if (Logo == null) { buffer.innerbuffer.Clear(); buffer.AddID(MsgType.NoLogo); buffer.SendCryptoBuffer(client.socket, client.CC.Salt); } else { buffer.innerbuffer.Clear(); buffer.AddID(MsgType.Logo); buffer.AddObject(Logo); buffer.SendCryptoBuffer(client.socket, client.CC.Salt); } } #endregion } else { for (int i = 0; i < ConnectedClients.Count(); i++) { if (ConnectedClients[i].socket == client.socket) { if (client.CC.Ip == ConnectedClients[i].CC.Ip && client.CC.sockettype != ConnectionType.Client) // or delete if FileSocket. { ConnectedClients[i].socket.Shutdown(SocketShutdown.Both); ConnectedClients[i].socket.Close(1); ConnectedClients.RemoveAt(i); Console.WriteLine("Socket of Type {0} Disconnected!", client.CC.sockettype); bRecvMessage = false; return; } client.socket.Shutdown(SocketShutdown.Both); client.socket.Close(1); client.socket = null; client.Online = false; bRecvMessage = false; Console.WriteLine("Client {0} of Type {1} Disconnected!", client.CC.Ip, client.CC.sockettype); UpdateClientList(); return; } } // if (ConnectedClients[index].CC.sockettype != ConnectionType.File) // only update clientlist if socket is not a filesocket. // UpdateClientList(); } } catch (Exception e) { for (int i = 0; i < ConnectedClients.Count(); i++) { if (client.socket == ConnectedClients[i].socket) { Console.WriteLine(ConnectedClients[i].CC.Ip + " " + e.Message + "\r\n Disconnected"); if (i < ConnectedClients.Count()) { /* * ConnectedClients[i].Online = false; * ConnectedClients[i].socket = null; * ConnectedClients[i].IsRunning = false; */ client.socket.Shutdown(SocketShutdown.Both); client.socket.Close(1); client.socket = null; client.Online = false; bRecvMessage = false; } } } } } }