Example #1
0
        public override void Bind(EndPoint localEP)
        {
            if (this.ActsAsServer)
            {
                throw new Exception("Cannot call {nameof(Bind)} multiple times.");
            }

            UnderlyingSocket.Bind(localEP);

            this.ActsAsServer = true;
            this.Clients      = new ConcurrentDictionary <IPEndPoint, UdpSocket>();
            this.ServerTaskCancellationTokenSource = new CancellationTokenSource();

            // All "receives" should be handled by this "server" instance.  For now, let's try one background thread.
            ServerTask = Task.Run(async() =>
            {
                try
                {
                    var buffer = new byte[4096];

                    while (true)
                    {
                        // TODO: There should be a TTL on "acting as server" sockets that are "connected" to remote endpoints, since
                        // UDP clients won't ever request a "close".
                        var receive        = await UnderlyingSocket.ReceiveFromAsync(buffer, SocketFlags.None, new IPEndPoint(IPAddress.Any, 0 /* any */));
                        var read           = receive.ReceivedBytes;
                        var remoteEndpoint = (IPEndPoint)receive.RemoteEndPoint;

                        var memory = new byte[read].AsMemory();
                        buffer.AsMemory().Slice(0, read).CopyTo(memory);

                        // See if this is for a "client" socket; if so, queue up for that socket's receive.

                        if (Clients.TryGetValue(remoteEndpoint, out UdpSocket? actualReceiver))
                        {
                            await actualReceiver.AwaitingReceives.Writer.WriteAsync(memory, ServerTaskCancellationTokenSource.Token);
                            continue;
                        }

                        // Otherwise, queue up for "self" in awaiting accepts.

                        var acceptingSocket = new UdpSocket(UnderlyingSocket)
                        {
                            TrackedRemote = remoteEndpoint
                        };
                        await acceptingSocket.AwaitingReceives.Writer.WriteAsync(memory);

                        await this.AwaitingAccepts.Writer.WriteAsync(acceptingSocket, ServerTaskCancellationTokenSource.Token);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    throw e;
                }
            }, ServerTaskCancellationTokenSource.Token);
        }
Example #2
0
 public override void Bind(EndPoint localEP) =>
 UnderlyingSocket.Bind(localEP);