Esempio n. 1
0
            private async Task CopyToAsync(IProxyServerUdpAssociateHandler src, IProxyServerUdpAssociateHandler dst)
            {
                try
                {
                    byte[] buffer = new byte[64 * 1024];

                    while (true)
                    {
                        UdpReceiveFromResult result = await src.ReceiveFromAsync(buffer, 0, buffer.Length);

                        await dst.SendToAsync(buffer, 0, result.BytesReceived, result.RemoteEndPoint);
                    }
                }
                finally
                {
                    Dispose();
                }
            }
Esempio n. 2
0
        public async Task <int> UdpQueryAsync(byte[] request, int requestOffset, int requestCount, byte[] response, int responseOffset, int responseCount, EndPoint remoteEP, int timeout = 10000, int retries = 1, bool expBackoffTimeout = false, CancellationToken cancellationToken = default)
        {
            Task <UdpReceiveFromResult> recvTask = null;

            int timeoutValue = timeout;
            int retry        = 0;

            while (retry < retries) //retry loop
            {
                if (expBackoffTimeout)
                {
                    timeoutValue = timeout * (2 ^ retry);
                }

                retry++;

                if (cancellationToken.IsCancellationRequested)
                {
                    return(await Task.FromCanceled <int>(cancellationToken)); //task cancelled
                }
                //send request
                await SendToAsync(request, requestOffset, requestCount, remoteEP);

                while (true)
                {
                    //receive request
                    if (recvTask == null)
                    {
                        recvTask = ReceiveFromAsync(response, responseOffset, responseCount);
                    }

                    //receive with timeout
                    using (CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource())
                    {
                        using (CancellationTokenRegistration ctr = cancellationToken.Register(delegate() { timeoutCancellationTokenSource.Cancel(); }))
                        {
                            if (await Task.WhenAny(recvTask, Task.Delay(timeoutValue, timeoutCancellationTokenSource.Token)) != recvTask)
                            {
                                break; //recv timed out
                            }
                        }

                        timeoutCancellationTokenSource.Cancel(); //to stop delay task
                    }

                    UdpReceiveFromResult result = await recvTask;

                    if ((remoteEP is DomainEndPoint) || remoteEP.Equals(result.RemoteEndPoint)) //in case remoteEP is domain end point then returned response will contain the resolved IP address so cant compare it together
                    {
                        //got response
                        return(result.BytesReceived);
                    }

                    //recv task is complete; set recvTask to null so that another task is used to read next response packet
                    recvTask = null;
                }
            }

            _udpSocket.Dispose();
            throw new SocketException((int)SocketError.TimedOut);
        }
Esempio n. 3
0
        public async Task <UdpReceiveFromResult> ReceiveFromAsync(byte[] buffer, int offset, int count)
        {
            byte[] datagram = new byte[262 + count];

            UdpReceiveFromResult result = await _udpSocket.ReceiveFromAsync(datagram);

            if (result.BytesReceived < 10)
            {
                throw new SocksProxyException("Incomplete SOCKS5 datagram was received.");
            }

            EndPoint remoteEP;

            switch ((SocksAddressType)datagram[3])
            {
            case SocksAddressType.IPv4Address:
            {
                byte[] address = new byte[4];
                Buffer.BlockCopy(datagram, 3 + 1, address, 0, 4);

                byte[] port = new byte[2];
                Buffer.BlockCopy(datagram, 3 + 1 + 4, port, 0, 2);
                Array.Reverse(port);

                remoteEP = new IPEndPoint(new IPAddress(address), BitConverter.ToUInt16(port, 0));
            }
            break;

            case SocksAddressType.IPv6Address:
            {
                byte[] address = new byte[16];
                Buffer.BlockCopy(datagram, 3 + 1, address, 0, 16);

                byte[] port = new byte[2];
                Buffer.BlockCopy(datagram, 3 + 1 + 16, port, 0, 2);
                Array.Reverse(port);

                remoteEP = new IPEndPoint(new IPAddress(address), BitConverter.ToUInt16(port, 0));
            }
            break;

            case SocksAddressType.DomainName:
            {
                int length = datagram[3 + 1];

                byte[] address = new byte[length];
                Buffer.BlockCopy(datagram, 3 + 1 + 1, address, 0, length);

                byte[] port = new byte[2];
                Buffer.BlockCopy(datagram, 3 + 1 + 1 + length, port, 0, 2);
                Array.Reverse(port);

                remoteEP = new DomainEndPoint(Encoding.ASCII.GetString(address), BitConverter.ToUInt16(port, 0));
            }
            break;

            default:
                throw new NotSupportedException("SocksAddressType not supported.");
            }

            int addressSize;

            switch (remoteEP.AddressFamily)
            {
            case AddressFamily.InterNetwork:
                addressSize = 4;
                break;

            case AddressFamily.InterNetworkV6:
                addressSize = 16;
                break;

            case AddressFamily.Unspecified:
                addressSize = 1 + (remoteEP as DomainEndPoint).Address.Length;
                break;

            default:
                throw new NotSupportedException("AddressFamily not supported.");
            }

            int dataOffset = 6 + addressSize;
            int dataSize   = result.BytesReceived - dataOffset;

            if (dataSize > count)
            {
                dataSize = count;
            }

            Buffer.BlockCopy(datagram, dataOffset, buffer, offset, dataSize);

            if (_relayEP == null)
            {
                _relayEP = result.RemoteEndPoint; //set new relay ep
            }
            return(new UdpReceiveFromResult(dataSize, remoteEP));
        }