Example #1
0
        internal PeerConnection(
            Metainfo meta,
            PeerId peerId,
            IReadOnlyList <byte> reservedBytes,
            ProtocolExtension supportedExtensions,
            IPeerMessageHandler messageHandler,
            ITransportStream transportStream)
        {
            this.messageHandler  = messageHandler;
            this.transportStream = transportStream;
            customValues         = new Dictionary <IModule, Dictionary <string, object> >();
            PeerId                = peerId;
            ReservedBytes         = reservedBytes;
            SupportedExtensions   = supportedExtensions;
            InfoHash              = meta.InfoHash;
            reader                = new BigEndianBinaryReader(transportStream.Stream);
            writer                = new BigEndianBinaryWriter(transportStream.Stream);
            Available             = new Bitfield(meta.Pieces.Count);
            RequestedByRemotePeer = new HashSet <BlockRequest>();
            Requested             = new HashSet <BlockRequest>();

            IsRemotePeerInterested   = false;
            IsInterestedInRemotePeer = false;
            IsChokedByRemotePeer     = true;
            IsChokingRemotePeer      = true;
        }
        private Task ReceiveOverUdpAsync(CancellationToken token)
        {
            var waitList = new List <Task>(_udpClientsMap.Count / 2);

            foreach (KeyValuePair <int, Socket> pair in _udpClientsMap)
            {
                int    channelNumber = pair.Key;
                Socket client        = pair.Value;

                ITransportStream transportStream = _streamsMap[channelNumber];

                Task receiveTask;

                if (transportStream is RtpStream rtpStream)
                {
                    RtcpReceiverReportsProvider receiverReportsProvider = _reportProvidersMap[channelNumber];
                    receiveTask = ReceiveRtpFromUdpAsync(client, rtpStream, receiverReportsProvider, token);
                }
                else
                {
                    receiveTask = ReceiveRtcpFromUdpAsync(client, transportStream, token);
                }

                waitList.Add(receiveTask);
            }

            return(Task.WhenAll(waitList));
        }
Example #3
0
        private Task ReceiveOverUdpAsync(CancellationToken token)
        {
            var waitList = new List <Task>(_udpClientsMap.Count / 2);

            foreach (KeyValuePair <int, Socket> pair in _udpClientsMap)
            {
                int    channelNumber = pair.Key;
                Socket client        = pair.Value;

                ITransportStream transportStream = _streamsMap[channelNumber];

                Task receiveTask;

                if (transportStream is RtpStream rtpStream)
                {
                    if (!_udpClientsMap.TryGetValue(_udpRtp2RtcpMap[channelNumber], out Socket clientRtcp))
                    {
                        throw new RtspClientException("RTP connection without RTCP");
                    }
                    RtcpReceiverReportsProvider receiverReportsProvider = _reportProvidersMap[channelNumber];
                    receiveTask = ReceiveRtpFromUdpAsync(client, clientRtcp, rtpStream, receiverReportsProvider, token);
                }
                else
                {
                    receiveTask = ReceiveRtcpFromUdpAsync(client, transportStream, token);
                }

                waitList.Add(receiveTask);
            }

            return(Task.WhenAll(waitList));
        }
        private static async Task ReceiveRtcpFromUdpAsync(Socket client, ITransportStream stream,
                                                          CancellationToken token)
        {
            var readBuffer    = new byte[Constants.UdpReceiveBufferSize];
            var bufferSegment = new ArraySegment <byte>(readBuffer);

            while (!token.IsCancellationRequested)
            {
                int read = await client.ReceiveAsync(bufferSegment, SocketFlags.None);

                var payloadSegment = new ArraySegment <byte>(readBuffer, 0, read);
                stream.Process(payloadSegment);
            }
        }
Example #5
0
        public void ConnectToPeer(ITransportStream peerTransport)
        {
            try
            {
                lock (peersLock)
                {
                    availablePeers.Remove(peerTransport);
                    connectingPeers.Add(peerTransport);
                }

                peerTransport.Connect().ContinueWith(antecedent =>
                {
                    // TODO: run on main loop thread
                    if (antecedent.Status != TaskStatus.RanToCompletion ||
                        !peerTransport.IsConnected)
                    {
                        Log.LogInformation($"Failed to connect to peer at {peerTransport.DisplayAddress}");

                        // Connection failed
                        lock (peersLock)
                            connectingPeers.Remove(peerTransport);

                        // TODO: keep a record of failed connection peers
                        return;
                    }

                    var connectionSettings = new PeerConnectionArgs(
                        localPeerId,
                        Metainfo,
                        messageHandlerFactory(this));

                    var peer = peerInitiator.InitiateOutgoingConnection(peerTransport, connectionSettings);
                    lock (peersLock)
                        connectingPeers.Remove(peerTransport);
                    PeerConnected(peer);
                });
            }
            catch
            {
                lock (peersLock)
                {
                    if (connectingPeers.Contains(peerTransport))
                    {
                        connectingPeers.Remove(peerTransport);
                    }
                }
            }
        }
Example #6
0
        public PeerConnection AcceptIncomingConnection(
            ITransportStream transportStream,
            IContext context,
            PeerConnectionArgs c)
        {
            var writer = new BigEndianBinaryWriter(transportStream.Stream);

            WriteConnectionHeader(writer, c.Metainfo.InfoHash, c.LocalPeerId);

            return(new PeerConnection(
                       c.Metainfo,
                       context.PeerId,
                       context.ReservedBytes,
                       context.SupportedExtensions,
                       c.MessageHandler,
                       transportStream));
        }
        public void ConnectToPeer(ITransportStream peerTransport)
        {
            try
            {
                lock (_peersLock)
                {
                    _availablePeers.Remove(peerTransport);
                    _connectingPeers.Add(peerTransport);
                }

                peerTransport.Connect().ContinueWith(antecedent =>
                {
                    // TODO: run on main loop thread
                    if (antecedent.Status != TaskStatus.RanToCompletion ||
                        !peerTransport.IsConnected)
                    {
                        _logger.LogInformation($"Failed to connect to peer at {peerTransport.DisplayAddress}");

                        // Connection failed
                        lock (_peersLock)
                            _connectingPeers.Remove(peerTransport);

                        // TODO: keep a record of failed connection peers
                        return;
                    }

                    var peer = _peerInitiator.InitiateOutgoingConnection(peerTransport, this);
                    lock (_peersLock)
                        _connectingPeers.Remove(peerTransport);
                    PeerConnected(peer);
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error connecting to peer");

                lock (_peersLock)
                {
                    if (_connectingPeers.Contains(peerTransport))
                    {
                        _connectingPeers.Remove(peerTransport);
                    }
                }
            }
        }
        public IPeer InitiateOutgoingConnection(ITransportStream transportStream, IApplicationProtocol applicationProtocol)
        {
            var writer = new BigEndianBinaryWriter(transportStream.Stream);
            var reader = new BigEndianBinaryReader(transportStream.Stream);

            WriteConnectionHeader(writer, applicationProtocol.Metainfo.InfoHash, _localPeerId);
            var header = ReadConnectionHeader(reader);

            if (header.InfoHash != applicationProtocol.Metainfo.InfoHash)
            {
                // Infohash mismatch
                throw new NotImplementedException();
            }

            return(new BitTorrentPeer(
                       applicationProtocol.Metainfo,
                       header.PeerId,
                       header.ReservedBytes,
                       header.SupportedExtensions,
                       new QueueingMessageHandler(_mainLoop, (BitTorrentApplicationProtocol)applicationProtocol),
                       transportStream));
        }
Example #9
0
        public PeerConnection InitiateOutgoingConnection(
            ITransportStream transportStream,
            PeerConnectionArgs c)
        {
            var writer = new BigEndianBinaryWriter(transportStream.Stream);
            var reader = new BigEndianBinaryReader(transportStream.Stream);

            WriteConnectionHeader(writer, c.Metainfo.InfoHash, c.LocalPeerId);
            var header = ReadConnectionHeader(reader);

            if (header.InfoHash != c.Metainfo.InfoHash)
            {
                // Infohash mismatch
                throw new NotImplementedException();
            }

            return(new PeerConnection(
                       c.Metainfo,
                       header.PeerId,
                       header.ReservedBytes,
                       header.SupportedExtensions,
                       c.MessageHandler,
                       transportStream));
        }
Example #10
0
 IApplicationProtocol <PeerConnection> IApplicationProtocolPeerInitiator <PeerConnection, IContext, PeerConnectionArgs> .PrepareAcceptIncomingConnection(
     ITransportStream transportStream,
     out IContext context)
 {
     return(PrepareAcceptIncomingConnection(transportStream, out context));
 }
Example #11
0
        public BitTorrentApplicationProtocol <IContext> PrepareAcceptIncomingConnection(ITransportStream transportStream, out IContext context)
        {
            var reader = new BigEndianBinaryReader(transportStream.Stream);
            var header = ReadConnectionHeader(reader);

            context = new PeerConnectionPreparationContext(header.PeerId, header.ReservedBytes, header.SupportedExtensions);
            return(applicationProtocolLookup(header.InfoHash));
        }
Example #12
0
 public AcceptConnectionEventArgs(ITransportStream ts, Action accept)
 {
     TransportStream = ts;
     Accept          = accept;
 }
 public AcceptPeerConnectionEventArgs(ITransportStream ts, Func <IPeer> accept)
 {
     TransportStream = ts;
     Accept          = accept;
 }