/// <summary> /// Handle a client's message. /// </summary> /// <param name="clientSocket">The client socket.</param> private void HandleClient(Socket clientSocket) { if (!clientSocket.Connected) { throw new ArgumentException($"Socket is not connected."); } // Receive the full message from the client. Message message = Message.Receive(this, clientSocket); if (message.IsCarryingData) { string intentAction = message.MessageType == EMessageType.SendData ? WifiP2pMessageIntent.ActionReceivedDataProgress : WifiP2pMessageIntent.ActionReceivedFileProgress; // Broadcast completion Intent doneIntent = new WifiP2pMessageIntent <IParcelable>(intentAction, 1, true, message.Object); SendBroadcast(doneIntent); } else { switch (message.MessageType) { case EMessageType.RequestFile: // TODO send file break; case EMessageType.RequestUpdatedData: // TODO send updated data break; } } clientSocket.Close(); // Release the socket. lock (m_Lock) { m_CurrentlyActiveSockets--; } }
/// <summary> /// Set and send the object of this message. /// </summary> /// <param name="clientSocket">The socket to send the data through.</param> /// <param name="obj">The object to send.</param> /// <param name="context">The context needed to send the broadcast.</param> /// <remarks>Depending on the current message type, only one object type will be supported.</remarks> public void Send(Socket clientSocket, Context context) { var formatter = new BinaryFormatter(); string intentAction = MessageType.GetIntentAction(true); // First send the message type. byte[] buffer = new byte[1]; buffer[0] = (byte)MessageType; clientSocket.SendBufferSize = buffer.Length; clientSocket.Send(buffer); // Then send the object length (in bytes) if the message is carrying data. if (IsCarryingData) { buffer = BitConverter.GetBytes(Length); clientSocket.SendBufferSize = buffer.Length; clientSocket.Send(buffer); using (MemoryStream ms = new MemoryStream()) { formatter.Serialize(ms, Data); buffer = ms.ToArray(); for (int i = 0; i < buffer.Length;) { clientSocket.SendBufferSize = Step; i += clientSocket.Send(buffer, i, Step, SocketFlags.None); Intent progressIntent = new WifiP2pMessageIntent(intentAction, (float)i / buffer.Length, false, this); context.SendBroadcast(progressIntent); } } } // Broadcast completion. Intent doneIntent = new WifiP2pMessageIntent(intentAction, 1, true, this); context.SendBroadcast(doneIntent); }
/// <summary> /// Receive a message from a client socket. /// </summary> /// <param name="context">The context used to send broadcasts on the progress.</param> /// <param name="clientSocket">The client socket.</param> static public void Receive(Context context, Socket clientSocket) { // Fetch the message type (first byte) byte[] buffer = new byte[1]; int bytesRead = clientSocket.Receive(buffer, 1, SocketFlags.None); if (bytesRead != 1) { throw new InvalidOperationException($"The received message could not be read."); } // Read message type EMessageType messageType = (EMessageType)buffer[0]; Message msg = new Message(messageType); // Stop reading if the message is not carrying any data. if (!messageType.IsCarryingData()) { return; } // Otherwise read it // Read object size (Int64 -> 8 bytes). buffer = new byte[8]; bytesRead = clientSocket.Receive(buffer, 4, SocketFlags.None); if (bytesRead != 8) { throw new InvalidOperationException($"The size of the object could not be read."); } long objLength = BitConverter.ToInt64(buffer, 0); List <byte> objBytes = new List <byte>(); int totalBytesRead = 0; string intentAction = messageType.GetIntentAction(false); buffer = new byte[Step]; while ((bytesRead = clientSocket.Receive(buffer, Step, SocketFlags.None)) > 0) { totalBytesRead += bytesRead; objBytes.AddRange(buffer); // Broadcast progress Intent progressIntent = new WifiP2pMessageIntent(intentAction, (float)totalBytesRead / objLength, false, msg); context.SendBroadcast(progressIntent); } if (totalBytesRead != objLength) { throw new InvalidOperationException($"Error while reading the object : {bytesRead} bytes read but object should be {objLength} bytes long."); } // Deserialize the object. var formatter = new BinaryFormatter(); msg.Data = formatter.Deserialize(new MemoryStream(objBytes.ToArray())) as IParcelable; // Broadcast completion Intent doneIntent = new WifiP2pMessageIntent(intentAction, 1, true, msg); context.SendBroadcast(doneIntent); }