private byte[] GetConnectionID(UdpClient udpClient, SocksUdpAssociateRequestHandler proxyRequestHandler, byte[] transactionID) { //Connection_id 64bit 0x41727101980 + action 32bit + transaction_id 32bit (random) byte[] requestPacket = new byte[] { 0x0, 0x0, 0x4, 0x17, 0x27, 0x10, 0x19, 0x80, 0x0, 0x0, 0x0, 0x0, transactionID[0], transactionID[1], transactionID[2], transactionID[3] }; for (int n = 0; n < 2; n++) { if (_proxy == null) { udpClient.Client.ReceiveTimeout = 15 * (2 ^ n) * 1000; } else { proxyRequestHandler.ReceiveTimeout = 15 * (2 ^ n) * 1000; } try { //SEND CONNECT REQUEST if (_proxy == null) { udpClient.Send(requestPacket, requestPacket.Length); } else { proxyRequestHandler.SendTo(requestPacket, 0, requestPacket.Length, new SocksEndPoint(_trackerURI.Host, _trackerURI.Port)); } //RECV CONNECT RESPONSE byte[] response; int responseLength; if (_proxy == null) { IPEndPoint remoteEP = null; response = udpClient.Receive(ref remoteEP); responseLength = response.Length; } else { response = new byte[128]; SocksEndPoint remoteEP; responseLength = proxyRequestHandler.ReceiveFrom(response, 0, response.Length, out remoteEP); } //check response length if (responseLength < 16) { throw new TrackerClientException("Invalid response received for connection request."); } //check transaction id for (int j = 0; j < 4; j++) { if (response[4 + j] != transactionID[j]) { throw new TrackerClientException("Invalid transaction id received for connection request."); } } //check action for (int j = 0; j < 4; j++) { if (response[j] != 0) { throw new TrackerClientException("Invalid action received for connection request."); } } byte[] connectionID = new byte[8]; Buffer.BlockCopy(response, 8, connectionID, 0, 8); return(connectionID); } catch (SocketException ex) { if (ex.ErrorCode != (int)SocketError.TimedOut) { throw new TrackerClientException(ex.Message, ex); } } } throw new TrackerClientException("No response from tracker."); }
public DnsDatagram Resolve(DnsDatagram request) { int bytesRecv; byte[] responseBuffer = null; int nextServerIndex = 0; int retries = _retries; byte[] requestBuffer; IDnsCache dnsCache = null; //serialize request using (MemoryStream mS = new MemoryStream(32)) { if (_tcp) { mS.Position = 2; } //write dns datagram request.WriteTo(mS); requestBuffer = mS.ToArray(); if (_tcp) { byte[] length = BitConverter.GetBytes(Convert.ToUInt16(requestBuffer.Length - 2)); requestBuffer[0] = length[1]; requestBuffer[1] = length[0]; } } //init server selection parameters if (_servers.Length > 1) { retries = retries * _servers.Length; //retries on per server basis byte[] select = new byte[1]; _rnd.GetBytes(select); nextServerIndex = select[0] % _servers.Length; } int retry = 0; while (retry < retries) { //select server NameServerAddress server; if (_servers.Length > 1) { server = _servers[nextServerIndex]; nextServerIndex = (nextServerIndex + 1) % _servers.Length; } else { server = _servers[0]; } if (server.EndPoint == null) { if (dnsCache == null) { dnsCache = new SimpleDnsCache(); } server.ResolveAddress(dnsCache, _proxy, _preferIPv6, _tcp, _retries); if (server.EndPoint == null) { retry++; continue; } } //query server Socket _socket = null; SocksUdpAssociateRequestHandler proxyRequestHandler = null; try { retry++; DateTime sentAt = DateTime.UtcNow; bool dnsTcp; if (_proxy == null) { if (_tcp) { _socket = new Socket(server.EndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); _socket.NoDelay = true; _socket.SendTimeout = _sendTimeout; _socket.ReceiveTimeout = _recvTimeout; IAsyncResult result = _socket.BeginConnect(server.EndPoint, null, null); if (!result.AsyncWaitHandle.WaitOne(_connectionTimeout)) { throw new SocketException((int)SocketError.TimedOut); } if (!_socket.Connected) { throw new SocketException((int)SocketError.ConnectionRefused); } } else { _socket = new Socket(server.EndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); _socket.SendTimeout = _sendTimeout; _socket.ReceiveTimeout = _recvTimeout; } dnsTcp = _tcp; } else { switch (_proxy.Type) { case NetProxyType.Http: _socket = _proxy.HttpProxy.Connect(server.EndPoint, _connectionTimeout); _socket.NoDelay = true; _socket.SendTimeout = _sendTimeout; _socket.ReceiveTimeout = _recvTimeout; dnsTcp = true; break; case NetProxyType.Socks5: if (!_tcp) { try { proxyRequestHandler = _proxy.SocksProxy.UdpAssociate(_connectionTimeout); proxyRequestHandler.ReceiveTimeout = _recvTimeout; dnsTcp = false; break; } catch (SocksClientException) { } } using (SocksConnectRequestHandler requestHandler = _proxy.SocksProxy.Connect(server.EndPoint, _connectionTimeout)) { _socket = requestHandler.GetSocket(); _socket.NoDelay = true; _socket.SendTimeout = _sendTimeout; _socket.ReceiveTimeout = _recvTimeout; dnsTcp = true; } break; default: throw new NotSupportedException("Proxy type not supported by DnsClient."); } } if (dnsTcp) { _socket.Send(requestBuffer); if ((responseBuffer == null) || (responseBuffer.Length == 512)) { responseBuffer = new byte[64 * 1024]; } bytesRecv = _socket.Receive(responseBuffer, 0, 2, SocketFlags.None); if (bytesRecv < 1) { throw new SocketException((int)SocketError.ConnectionReset); } Array.Reverse(responseBuffer, 0, 2); ushort length = BitConverter.ToUInt16(responseBuffer, 0); int offset = 0; while (offset < length) { bytesRecv = _socket.Receive(responseBuffer, offset, length, SocketFlags.None); if (bytesRecv < 1) { throw new SocketException((int)SocketError.ConnectionReset); } offset += bytesRecv; } bytesRecv = length; } else { if (responseBuffer == null) { responseBuffer = new byte[512]; } if (proxyRequestHandler == null) { _socket.SendTo(requestBuffer, server.EndPoint); EndPoint remoteEP; if (server.EndPoint.AddressFamily == AddressFamily.InterNetworkV6) { remoteEP = new IPEndPoint(IPAddress.IPv6Any, 0); } else { remoteEP = new IPEndPoint(IPAddress.Any, 0); } bytesRecv = _socket.ReceiveFrom(responseBuffer, ref remoteEP); } else { proxyRequestHandler.SendTo(requestBuffer, 0, requestBuffer.Length, new SocksEndPoint(server.EndPoint)); bytesRecv = proxyRequestHandler.ReceiveFrom(responseBuffer, 0, responseBuffer.Length, out SocksEndPoint socksRemoteEP); } } //parse response using (MemoryStream mS = new MemoryStream(responseBuffer, 0, bytesRecv, false)) { double rtt = (DateTime.UtcNow - sentAt).TotalMilliseconds; DnsDatagram response = new DnsDatagram(mS, server, (_tcp ? ProtocolType.Tcp : ProtocolType.Udp), rtt); if (response.Header.Identifier == request.Header.Identifier) { return(response); } } } catch (SocketException) { } finally { if (_socket != null) { _socket.Dispose(); } if (proxyRequestHandler != null) { proxyRequestHandler.Dispose(); } } } throw new DnsClientException("DnsClient failed to resolve the request: no response from name servers."); }
private int GetAnnounceResponse(UdpClient udpClient, SocksUdpAssociateRequestHandler proxyRequestHandler, byte[] transactionID, byte[] connectionID, TrackerClientEvent @event, IPEndPoint clientEP, out byte[] response) { byte[] request = new byte[98]; //connection_id 64bit Buffer.BlockCopy(connectionID, 0, request, 0, 8); //action 32bit request[11] = 1; //transaction_id 32bit Buffer.BlockCopy(transactionID, 0, request, 12, 4); //info_hash 20 bytes Buffer.BlockCopy(_infoHash, 0, request, 16, 20); //peer_id 20 bytes Buffer.BlockCopy(_clientID.PeerID, 0, request, 36, 20); //downloaded 64bit //left 64bit //uploaded 64bit //event 32bit request[83] = Convert.ToByte(@event); //ip address 32bit if (clientEP.Address.AddressFamily == AddressFamily.InterNetwork) { switch (clientEP.Address.ToString()) { case "0.0.0.0": case "127.0.0.1": break; default: Buffer.BlockCopy(clientEP.Address.GetAddressBytes(), 0, request, 84, 4); break; } } //key 32bit Buffer.BlockCopy(_clientID.ClientKey, 0, request, 88, 4); //num_want Buffer.BlockCopy(BitConverter.GetBytes(_clientID.NumWant), 0, request, 92, 4); //port 16bit byte[] portBuffer = BitConverter.GetBytes(clientEP.Port); Array.Reverse(portBuffer); Buffer.BlockCopy(portBuffer, 2, request, 96, 2); int responseLength; if (_proxy == null) { //SEND ANNOUNCE REQUEST udpClient.Send(request, request.Length); //RECV ANNOUNCE RESPONSE IPEndPoint remoteEP = null; response = udpClient.Receive(ref remoteEP); responseLength = response.Length; } else { //SEND ANNOUNCE REQUEST proxyRequestHandler.SendTo(request, 0, request.Length, new SocksEndPoint(_trackerURI.Host, _trackerURI.Port)); //RECV ANNOUNCE RESPONSE response = new byte[1024]; SocksEndPoint remoteEP; responseLength = proxyRequestHandler.ReceiveFrom(response, 0, response.Length, out remoteEP); } //check response length if (responseLength < 20) { throw new TrackerClientException("Invalid response received for announce request."); } //check response transaction id for (int j = 0; j < 4; j++) { if (response[4 + j] != transactionID[j]) { throw new TrackerClientException("Invalid transaction id received for announce request."); } } //check response action if (response[3] != 1) { throw new TrackerClientException("Invalid action received for announce request."); } return(responseLength); }