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)); }
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); } }
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); } } } }
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)); }
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)); }
IApplicationProtocol <PeerConnection> IApplicationProtocolPeerInitiator <PeerConnection, IContext, PeerConnectionArgs> .PrepareAcceptIncomingConnection( ITransportStream transportStream, out IContext context) { return(PrepareAcceptIncomingConnection(transportStream, out context)); }
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)); }
public AcceptConnectionEventArgs(ITransportStream ts, Action accept) { TransportStream = ts; Accept = accept; }
public AcceptPeerConnectionEventArgs(ITransportStream ts, Func <IPeer> accept) { TransportStream = ts; Accept = accept; }