public void AppendChatBoxListViewSeparateThread(T2SClientMessage message) { if (!string.IsNullOrEmpty(message.Message)) { T2SUser sender = null; //Find profile picture from list of users foreach (T2SUser user in ConnectedUsers) { if (user.MacAddr == message.MacAddr) { sender = user; } } ChatBox.Items.Add(new MessageTemplate { ProfilePicture = BitmapToImageSource(GetBitmapFromBytes(sender.ProfilePicture)), Message = message.Message }); } }
/// <summary> /// Sends a bytes to the server, simply containing a T2SClientMessage and header /// </summary> public void SendMessage(string text, bool firstConnect, bool updateProfile) { T2SClientMessage message = new T2SClientMessage() { MacAddr = this.MacAddr, ProfilePicture = (updateProfile) ? this.ProfilePicture : null, UpdateProfile = updateProfile, //change to be a bool that is set when we add Profile settings Username = this.Username, FirstConnect = firstConnect, //change to be a bool Message = text }; byte[] buffer = ObjectToByteArray(message), temp = ObjectToByteArray(message); string header = buffer.Length.ToString(); //If the header length is larger than the maximum length, we're gonna assume that the dude is trying to destroy someone with a fat receive. //There's no reason for something to be this large //Therefore, just let the sender know that their message is waaaay too big if (header.Length < 32) { Console.WriteLine("Generating header..."); for (int i = header.Length; i < 32; i++) { header += " "; //Append empty spaces until header is max length (32) } byte[] headerBytes = Encoding.ASCII.GetBytes(header + "|"); buffer = new byte[temp.Length + headerBytes.Length]; Array.Copy(headerBytes, buffer, headerBytes.Length); Array.Copy(temp, 0, buffer, 33, temp.Length); //Append own text ChatBox.Dispatcher.Invoke(new AppendRTBSeparateThreadCallback(this.AppendChatBoxListViewSeparateThread), new object[] { message }); ClientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None); } }
public void RemoveListViewConnecteduseresSeparateThread(T2SClientMessage message) { CollectionViewSource.GetDefaultView(ConnectedUsers).Refresh(); }
/// <summary> /// Receives byte array from server, converts to ASCII encoding to display /// Note that this is occurring on a separate thread /// /// HEADER AND BODY /// Header is defined as the zeroth index of a BAR | string split /// The header may also never be larger than 32 bytes (if it is, then this implies the message is SUPER long and we should probably just ignore it. /// The server should also recognize this failure and send an error message to the sending client that the message sent is too large (like, honestly, 32 bytes is a 32 digit integer. /// Who even would send something that big? /// RIP that person's bandwidth lol)) /// The header will represent the TOTAL LENGTH EXCLUSIVE of the header, thereby representing the buffer length of the NEXT receive, which should by protocol be a json file. /// The header will also always be length 32, append pipe separator to be 33 /// /// The first index will be a byte array that is the object T2SClientMessage /// /// </summary> private void ReceiveResponse() { if (!IsConnected(ClientSocket)) { Console.WriteLine("here"); Disconnect(); } int received = 0; var buffer = new byte[33]; try { received = ClientSocket.Receive(buffer, 33, SocketFlags.None); } catch (Exception e) { Console.WriteLine("EXCEPTION"); return; } if (received == 0) { return; //Nothing to receive } string text = Encoding.ASCII.GetString(buffer); //Hopefully the header Console.WriteLine(text); //If full header not grabbed, append the new bytes until header is grabbed while (received < 33) { byte[] tempBuffer = new byte[33 - received]; int appendableBytes = ClientSocket.Receive(tempBuffer, 33 - received, SocketFlags.None); Array.Copy(tempBuffer, 0, buffer, received, tempBuffer.Length); received += appendableBytes; } Console.WriteLine("Received"); int header; //Successfully got header if (Int32.TryParse(text.Split('|')[0], out header)) { buffer = new byte[header]; received = ClientSocket.Receive(buffer, header, SocketFlags.None); while (received < header) { byte[] tempBuffer = new byte[header - received]; int appendableBytes = ClientSocket.Receive(tempBuffer, header - received, SocketFlags.None); Array.Copy(tempBuffer, 0, buffer, received, tempBuffer.Length); received += appendableBytes; } T2SClientMessage message = (T2SClientMessage)ByteArrayToObject(buffer); //Perform logic //In order to do anything, the client must first be connected if (message.Connected) { //If this is the first connection, we're not going to display anything new in the chat if (message.FirstConnect) { ConnectedUsers.Add(new T2SUser() { MacAddr = message.MacAddr, Username = message.Username, ProfilePicture = message.ProfilePicture }); ListView_ConnectedUsers.Dispatcher.Invoke(new AppendListViewConnectedUsersSeparateThreadCallback(this.AppendListViewConnecteduseresSeparateThread), new object[] { message }); } else { if (message.UpdateProfile) { bool found = false; //Modify user if macaddr exists. If not, add foreach (T2SUser user in ConnectedUsers) { if (user.MacAddr == message.MacAddr) { //exists. So update the user user.ProfilePicture = (message.ProfilePicture == null) ? user.ProfilePicture : message.ProfilePicture; user.Username = message.Username; //Should never be null found = true; //Found, therefore look for the user in the ListView_ConnectedUsers and update the user ListView_ConnectedUsers.Dispatcher.Invoke(new UpdateUserListViewConnectedUsersSeparateThreadCallback(this.UpdateUserListViewConnecteduseresSeparateThread), new object[] { user }); break; } } //Not found, therefore add the user to ConnectedUser list and thingy if (!found) { ConnectedUsers.Add(new T2SUser() { MacAddr = message.MacAddr, Username = message.Username, ProfilePicture = message.ProfilePicture }); } } //Append to visual and do TTS speech.SpeakAsync(message.Message); ChatBox.Dispatcher.Invoke(new AppendRTBSeparateThreadCallback(this.AppendChatBoxListViewSeparateThread), new object[] { message }); } } else { T2SUser user = ConnectedUsers.Find(x => x.MacAddr == message.MacAddr); if (user != null) { ConnectedUsers.Remove(user); } ListView_ConnectedUsers.Dispatcher.Invoke(new RemoveListViewConnectedUsersSeparateThreadCallback(this.RemoveListViewConnecteduseresSeparateThread), new object[] { message }); } } }
/// <summary> /// Message callback function /// Send user data back based on first connect or message /// </summary> /// <param name="AR"></param> private static void ReceiveCallback(IAsyncResult AR) { Socket current = (Socket)AR.AsyncState; int received; if (!current.Connected) { return; } try { received = current.EndReceive(AR); } catch (SocketException) { Console.WriteLine("Client forcefully disconnected"); // Don't shutdown because the socket may be disposed and its disconnected anyway. current.Close(); SocketPair socketToRemove = null; foreach (SocketPair s in clientSockets) { if (s.socket.Equals(current)) { socketToRemove = s; break; } } if (socketToRemove != null) { clientSockets.Remove(socketToRemove); T2SClientMessage otherClient = new T2SClientMessage() { Connected = false, MacAddr = socketToRemove.MacAddr }; byte[] otherClientBuffer = MainWindow.ObjectToByteArray(otherClient); byte[] otherClientBufferMessage = new byte[otherClientBuffer.Length + 33]; //message to send; appends length of header string otherClientHeader = otherClientBuffer.Length.ToString(); for (int i = otherClientHeader.Length; i < 32; i++) { otherClientHeader += " "; //Append empty spaces until header is max length (32) } otherClientHeader += "|"; Array.Copy(Encoding.ASCII.GetBytes(otherClientHeader), otherClientBufferMessage, 33); Array.Copy(otherClientBuffer, 0, otherClientBufferMessage, 33, otherClientBuffer.Length); //Sendto everyone foreach (SocketPair s in clientSockets) { s.socket.Send(otherClientBufferMessage); } } return; } if (received == 0) { Console.WriteLine("No bytes received; closing socket"); SocketPair socketToRemove = null; foreach (SocketPair s in clientSockets) { if (s.socket.Equals(current)) { socketToRemove = s; break; } } if (socketToRemove.socket.Connected) { socketToRemove.socket.Close(); } clientSockets.Remove(socketToRemove); T2SClientMessage otherClient = new T2SClientMessage() { Connected = false, MacAddr = socketToRemove.MacAddr }; byte[] otherClientBuffer = MainWindow.ObjectToByteArray(otherClient); byte[] otherClientBufferMessage = new byte[otherClientBuffer.Length + 33]; //message to send; appends length of header string otherClientHeader = otherClientBuffer.Length.ToString(); for (int i = otherClientHeader.Length; i < 32; i++) { otherClientHeader += " "; //Append empty spaces until header is max length (32) } otherClientHeader += "|"; Array.Copy(Encoding.ASCII.GetBytes(otherClientHeader), otherClientBufferMessage, 33); Array.Copy(otherClientBuffer, 0, otherClientBufferMessage, 33, otherClientBuffer.Length); //Sendto everyone foreach (SocketPair s in clientSockets) { if (s.socket.Connected) { s.socket.Send(otherClientBufferMessage); } } return; } byte[] recBuf = new byte[received]; //Received buffer which should be the header to tell us the buffer length of the json message (should be length 33 with pipe at the end) Array.Copy(buffer, recBuf, received); //Get until header is filled while (received < 33) { byte[] tempBuffer = new byte[33 - received]; int appendableBytes = current.Receive(tempBuffer, 33 - received, SocketFlags.None); Array.Copy(tempBuffer, 0, recBuf, received, tempBuffer.Length); received += appendableBytes; } int headerReceived; if (Int32.TryParse(Encoding.ASCII.GetString(recBuf).Split('|')[0], out headerReceived)) { recBuf = new byte[headerReceived]; received = current.Receive(recBuf, headerReceived, SocketFlags.None); //Get until object is filled while (received < headerReceived) { byte[] tempBuffer = new byte[headerReceived - received]; int appendableBytes = current.Receive(tempBuffer, headerReceived - received, SocketFlags.None); Array.Copy(tempBuffer, 0, recBuf, received, tempBuffer.Length); received += appendableBytes; } } byte[] temp = new byte[recBuf.Length]; Array.Copy(recBuf, temp, temp.Length); string header = recBuf.Length.ToString(); //If the header length is larger than the maximum length, we're gonna assume that the dude is trying to destroy someone with a fat receive. //There's no reason for something to be this large //Therefore, just let the sender know that their message is waaaay too big if (header.Length < 32) { for (int i = header.Length; i < 32; i++) { header += " "; //Append empty spaces until header is max length (32) } byte[] headerBytes = Encoding.ASCII.GetBytes(header + "|"); T2SClientMessage clientMessage = (T2SClientMessage)MainWindow.ByteArrayToObject(recBuf); temp = MainWindow.ObjectToByteArray(clientMessage); recBuf = new byte[temp.Length + headerBytes.Length]; Array.Copy(headerBytes, recBuf, headerBytes.Length); Array.Copy(temp, 0, recBuf, 33, temp.Length); byte[] message = recBuf; //Append message with the header //Send to all connected sockets except self foreach (SocketPair s in clientSockets) { if (s.socket != current) { s.socket.Send(message); } } if (clientMessage.UpdateProfile) { foreach (SocketPair s in clientSockets) { if (s.MacAddr == clientMessage.MacAddr) { s.ProfilePicture = (clientMessage.ProfilePicture == null) ? s.ProfilePicture : clientMessage.ProfilePicture; s.Username = clientMessage.Username; break; } } } //If this is the first connection, we need to update our socketpair MacAddr for audit (also just send back to client) if (clientMessage.FirstConnect) { Console.WriteLine("First connect: " + clientMessage.Username); foreach (SocketPair s in clientSockets) { if (s.socket == current) { s.MacAddr = clientMessage.MacAddr; s.Username = clientMessage.Username; s.ProfilePicture = clientMessage.ProfilePicture; } else { T2SClientMessage otherClient = new T2SClientMessage() { FirstConnect = true, ProfilePicture = s.ProfilePicture, Username = s.Username, MacAddr = s.MacAddr }; byte[] otherClientBuffer = MainWindow.ObjectToByteArray(otherClient); byte[] otherClientBufferMessage = new byte[otherClientBuffer.Length + 33]; //message to send; appends length of header string otherClientHeader = otherClientBuffer.Length.ToString(); for (int i = otherClientHeader.Length; i < 32; i++) { otherClientHeader += " "; //Append empty spaces until header is max length (32) } otherClientHeader += "|"; Array.Copy(Encoding.ASCII.GetBytes(otherClientHeader), otherClientBufferMessage, 33); Array.Copy(otherClientBuffer, 0, otherClientBufferMessage, 33, otherClientBuffer.Length); current.Send(otherClientBufferMessage); } } current.Send(message); //Send the profile back to themself } } else { Console.WriteLine("HEADER TOO LARGE!!! Header length: " + header.Length); } current.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current); }