public RemoteCitpTcpClient(ICitpLogService log, ITcpSocketClient client, CancellationToken cancellationToken)
 {
     _log               = log;
     _client            = client;
     _cancellationToken = cancellationToken;
     RemoteEndPoint     = new IpEndpoint(IpAddress.Parse(client.RemoteAddress), client.RemotePort);
 }
예제 #2
0
 /// <summary>
 /// Receives incoming data in a loop running in its own thread.
 /// </summary>
 /// <param name="ipEndPoint"></param>
 /// <param name="trace"></param>
 /// <exception cref="UdpSocketException">Thrown when socket cannot be bound to endpoint</exception>
 public ListenerBase(IpEndpoint ipEndPoint, ITrace trace)
 {
     _ipEndPoint  = ipEndPoint;
     _trace       = trace;
     _listener    = new UdpListener(ipEndPoint);
     _messageLoop = new MessageLoop <UdpListener>(_listener, trace, Operation, StopOperation);
 }
예제 #3
0
 public Client(IpEndpoint serverEndpoint, ITrace trace)
 {
     _trace         = trace;
     ServerEndpoint = serverEndpoint;
     _udpClient     = new UdpClient();
     _udpClient.Connect(serverEndpoint);
     _messageLoop = new MessageLoop <UdpClient>(_udpClient, _trace, Operation, StopOperation);
 }
예제 #4
0
        public BroadcastClient(IpEndpoint localEndpoint, int targetPort, byte connectionId, ITrace trace)
        {
            _listenerBase = new ListenerBase(localEndpoint, trace);
            _listenerBase.MessageReceived += MessageReceived;
            var broadcastClient = _listenerBase.Listener.ForkSendTo(new IpEndpoint(new IpAddress("255.255.255.255"), targetPort));

            Connection = new UnreliableUnorderedConnection(broadcastClient, connectionId, trace);
        }
예제 #5
0
        private Task <bool> sendDataToPeerAsync(CitpPeer peer, byte[] data, int?remoteTcpPort = null)
        {
            IRemoteCitpTcpClient client;

            Debug.Assert(peer.IsConnected, "Can't send data to an unconnected peer");

            var endpoint = new IpEndpoint(peer.Ip, remoteTcpPort ?? peer.RemoteTcpPorts.First());

            return(_tcpListenService.Clients.TryGetValue(endpoint, out client)
                                ? client.SendAsync(data)
                                : Task.FromResult(false));
        }
예제 #6
0
        private async Task Stage1()
        {
#if !NETSTANDARD1_1
            // IP Discovery
            UdpClient.Setup(ConnectionEndpoint);
            var pck = new byte[70];
            Array.Copy(BitConverter.GetBytes(SSRC), 0, pck, pck.Length - 4, 4);
            await UdpClient.SendAsync(pck, pck.Length).ConfigureAwait(false);

            var ipd = await UdpClient.ReceiveAsync().ConfigureAwait(false);

            var ipe  = Array.IndexOf <byte>(ipd, 0, 4);
            var ip   = new UTF8Encoding(false).GetString(ipd, 4, ipe - 4);
            var port = BitConverter.ToUInt16(ipd, ipd.Length - 2);
            DiscoveredEndpoint = new IpEndpoint {
                Address = System.Net.IPAddress.Parse(ip), Port = port
            };
#endif

            // Ready
            var vsp = new VoiceDispatch
            {
                OpCode  = 1,
                Payload = new VoiceSelectProtocolPayload
                {
                    Protocol = "udp",
                    Data     = new VoiceSelectProtocolPayloadData
                    {
#if !NETSTANDARD1_1
                        Address = DiscoveredEndpoint.Address.ToString(),
                        Port    = (ushort)DiscoveredEndpoint.Port,
#else
                        Address = "0.0.0.0",
                        Port    = 0,
#endif
                        Mode = VOICE_MODE
                    }
                }
            };
            var vsj = JsonConvert.SerializeObject(vsp, Formatting.None);
            VoiceWs.SendMessage(vsj);

#if !NETSTANDARD1_1
            if (Configuration.EnableIncoming)
            {
                ReceiverTokenSource = new CancellationTokenSource();
                ReceiverTask        = Task.Run(VoiceReceiverTask, ReceiverToken);
            }
#endif
        }
예제 #7
0
        private void tcpListenService_ClientDisconnect(object sender, IpEndpoint e)
        {
            _log.LogDebug($"TCP client disconnected from {e}");

            var peer = Peers.FirstOrDefault(p => p.RemoteTcpPorts.Contains(e.Port));

            if (peer == null)
            {
                _log.LogDebug("Failed to identify disconnecting peer");
                return;
            }

            peer.RemoveTcpConnection(e.Port);
            peer.LastUpdateReceived = DateTime.Now;

            _log.LogInfo($"CITP Peer '{peer}' disconnected on TCP Port {e.Port}");
        }
예제 #8
0
        private void receivedPeerNameMessage(PeerNameMessagePacket message, IpEndpoint remoteEndpoint)
        {
            var peer = _peers.FirstOrDefault(p => p.Ip == remoteEndpoint.Address && p.Name == message.Name);

            if (peer != null)
            {
                peer.AddTcpConnection(remoteEndpoint.Port);
                _log.LogInfo($"Known CITP Peer '{peer}' identified on TCP port {remoteEndpoint.Port}");
            }
            else
            {
                peer = new CitpPeer(remoteEndpoint.Address, message.Name);
                peer.AddTcpConnection(remoteEndpoint.Port);

                _peers.Add(peer);
                _log.LogInfo($"New CITP Peer '{peer}' identified from on TCP port {remoteEndpoint.Port}");
            }

            peer.Name = message.Name;
            peer.LastUpdateReceived = DateTime.Now;
        }
예제 #9
0
        private void MessageReceived(Paket paket, IpEndpoint ipEndpoint)
        {
            if (paket.Count < 2 || paket.Count > 1024)
            {
                _trace.Error("Received datagram with invalid count: {0}", paket.Count);
                return;
            }
            var protocolVersion = paket.Array[0] & 7;

            if (protocolVersion != Connection.ProtocolVersion)
            {
                _trace.Error("Discarding Message with different protocol version. Was: {0} Expected: {1}", protocolVersion, Connection.ProtocolVersion);
                return;
            }
            ServerPeer serverPeer;

            if (!_serverPeers.TryGetValue(ipEndpoint, out serverPeer))
            {
                serverPeer = new ServerPeer(ipEndpoint, _listenerBase.Listener.ForkSendTo(ipEndpoint), _trace);
                _serverPeers.Add(ipEndpoint, serverPeer);
                OnNewServerPeer(this, serverPeer);
            }
            serverPeer.MessageReceived(paket);
        }
예제 #10
0
 internal ServerPeer(IpEndpoint ipEndpoint, IUdpSend udpSend, ITrace trace)
 {
     _ipEndpoint = ipEndpoint;
     _udpSend    = udpSend;
     _trace      = trace;
 }
예제 #11
0
 public MessageReceivedEventArgs(IpEndpoint endpoint, byte[] data)
 {
     Endpoint = endpoint;
     Data     = data;
 }
예제 #12
0
        private async Task Stage1(VoiceReadyPayload voiceReady)
        {
            // IP Discovery
            this.UdpClient.Setup(this.UdpEndpoint);

            var pck = new byte[70];

            PreparePacket(pck);
            await this.UdpClient.SendAsync(pck, pck.Length).ConfigureAwait(false);

            // fetch endpoint it it wasn't done already
            IpEndpoint ownEndpoint;

            try
            {
                var ipd = await this.UdpClient.ReceiveAsync().ConfigureAwait(false);

                ReadPacket(ipd, out var ip, out var port);
                ownEndpoint = new IpEndpoint
                {
                    Address = ip,
                    Port    = port
                };
                this.DiscoveredEndpoint = ownEndpoint;
                this.Discord.DebugLogger.LogMessage(LogLevel.Debug, "VNext UDP", $"Endpoint discovery resulted in {ip}:{port}", DateTime.Now);
            } catch (Exception e)
            {
                this.Discord.DebugLogger.LogMessage(LogLevel.Error, "VNext UDP", "Endpoint discovery failed", DateTime.Now, e);

                // fallback to last value if present
                if (this.DiscoveredEndpoint.HasValue)
                {
                    ownEndpoint = this.DiscoveredEndpoint.Value;
                    this.Discord.DebugLogger.LogMessage(LogLevel.Info, "VNext UDP", "Endpoint discovery used old endpoint", DateTime.Now, e);
                }
                else
                {
                    throw e;
                }
            }


            void PreparePacket(byte[] packet)
            {
                var ssrc       = this.SSRC;
                var packetSpan = packet.AsSpan();

                MemoryMarshal.Write(packetSpan, ref ssrc);
                Helpers.ZeroFill(packetSpan);
            }

            void ReadPacket(byte[] packet, out System.Net.IPAddress decodedIp, out ushort decodedPort)
            {
                if (packet.Length != 70)
                {
                    throw new Exception($"Recieved invalid IP discovery data. Expected length 70 but got {packet.Length}");
                }

                var packetSpan = packet.AsSpan();

                var ipString = Utilities.UTF8.GetString(packet, 4, 64 /* 70 - 6 */).TrimEnd('\0');

                decodedIp = System.Net.IPAddress.Parse(ipString);

                decodedPort = BinaryPrimitives.ReadUInt16LittleEndian(packetSpan.Slice(68 /* 70 - 2 */));
            }

            // Select voice encryption mode
            var selectedEncryptionMode = Sodium.SelectMode(voiceReady.Modes);

            this.SelectedEncryptionMode = selectedEncryptionMode.Value;

            // Ready
            this.Discord.DebugLogger.LogMessage(LogLevel.Debug, "VoiceNext", $"Selected encryption mode: {selectedEncryptionMode.Key}", DateTime.Now);
            var vsp = new VoiceDispatch
            {
                OpCode  = 1,
                Payload = new VoiceSelectProtocolPayload
                {
                    Protocol = "udp",
                    Data     = new VoiceSelectProtocolPayloadData
                    {
                        Address = ownEndpoint.Address.ToString(),
                        Port    = (ushort)ownEndpoint.Port,
                        Mode    = selectedEncryptionMode.Key
                    }
                }
            };
            var vsj = JsonConvert.SerializeObject(vsp, Formatting.None);

            await this.VoiceWs.SendMessageAsync(vsj).ConfigureAwait(false);

            if (this.SenderTokenSource != null)
            {
                this.SenderTokenSource.Cancel();
            }
            this.SenderTokenSource = new CancellationTokenSource();
            this.SenderTask        = Task.Run(this.VoiceSenderTask, this.SenderToken);

            if (this.ReceiverTokenSource != null)
            {
                this.ReceiverTokenSource.Cancel();
            }
            this.ReceiverTokenSource = new CancellationTokenSource();
            this.ReceiverTask        = Task.Run(this.UdpReceiverTask, this.ReceiverToken);
        }
예제 #13
0
 private void MessageReceived(Paket paket, IpEndpoint ipEndpoint)
 {
     CurrentEndpoint = ipEndpoint;
     Connection.MessageReceived(paket);
 }
예제 #14
0
 public ServerConfiguration(IpEndpoint ipEndpoint)
 {
     IpEndpoint = ipEndpoint;
 }
예제 #15
0
 public ServerConfiguration(int port)
 {
     IpEndpoint = new IpEndpoint(IpAddress.AnyAddress, port);
 }
예제 #16
0
 protected bool Equals(IpEndpoint other)
 {
     return(Equals(IpAddress, other.IpAddress) && Port == other.Port);
 }