// This routine with be run synchronously with UDPWii.Server public void SendDataPacket(UDPWii.DataDSU packet) { // If the server is not running, just drop the packet if (tokenSource == null) { return; } lock (clients) { // If there's no client, skip the packet processing step and drop the packet if (clients.Count == 0) { return; } List <IPEndPoint> toRemove = new List <IPEndPoint>(); DSU.DataRsp dsuPacket = packet.ToDSU(id); byte[] dsuPacketData = dsuPacket.Finish(); //Console.WriteLine("[DSU.Sender] ({0}, {1})", dsuPacket.touch1.x, dsuPacket.touch1.y); foreach (var keyValuePair in clients) { Client client = keyValuePair.Value; if (!Util.IsTimeout(client.lastSeenAll) || !Util.IsTimeout(client.lastSeenSlot[packet.client.slot])) { udpSend.Send(dsuPacketData, dsuPacketData.Length, keyValuePair.Key); } else { // Is this client completely dead? If so, mark it for removal // Reference: https://github.com/Davidobot/BetterJoy/blob/master/BetterJoyForCemu/UpdServer.cs // We're here so lastSeenAll must have timed out if (client.lastSeenSlot.All(Util.IsTimeout)) { toRemove.Add(keyValuePair.Key); } } //Console.WriteLine("[DSU.Sender] Packet sent to " + keyValuePair.Key.ToString()); } // Clear all dead clients now to prevent concurrent modification foreach (IPEndPoint key in toRemove) { Console.WriteLine("[DSU.Server] Removing dead client {0}", key.ToString()); clients.Remove(key); } } }
private void TaskMain(CancellationToken token) { broadcaster.Start(); try { Task <UdpReceiveResult> taskRecv; while (true) { token.ThrowIfCancellationRequested(); //Util.TimingStart(); taskRecv = udp.ReceiveAsync(); taskRecv.Wait(token); //Console.WriteLine(Util.TimingEnd()); // Mark this server's client as "alive" client.lastSeen = DateTime.Now; // Box data for DSU.Sender UDPWii.DataDSU packet = new UDPWii.DataDSU(taskRecv.Result.Buffer, client); if (packet.flags == UDPWii.Data.Flags.None) { Console.WriteLine("[UDPWii.Server@{0}] Dropping invalid packet from {1}", client.slot, taskRecv.Result.RemoteEndPoint.ToString()); } else { //Util.TimingStart(); DSU.Server.theInstance.SendDataPacket(packet); //Console.Error.WriteLine(Util.TimingEnd()); } } } catch (OperationCanceledException) { ; } broadcaster.Stop(); }