예제 #1
0
        public static async Task ReadFullImpl(IMyStream myStream, BytesSegment bs)
        {
            int pos = 0;

            if (myStream is IMyStreamReadR r)
            {
                while (pos < bs.Len)
                {
                    var read = await r.ReadAsyncR(bs.Sub(pos));

                    if (read == 0)
                    {
                        throw new DisconnectedException($"unexpected EOF while ReadFull() (count={bs.Len}, pos={pos})");
                    }
                    pos += read;
                }
                return;
            }
            while (pos < bs.Len)
            {
                var read = await myStream.ReadAsync(bs.Sub(pos)).CAF();

                if (read == 0)
                {
                    throw new DisconnectedException($"unexpected EOF while ReadFull() (count={bs.Len}, pos={pos})");
                }
                pos += read;
            }
        }
예제 #2
0
        public override async void OnNewConnection(TcpClient client)
        {
            try {
                using (client) {
                    var socket     = client.Client;
                    var remoteEP   = socket.RemoteEndPoint as IPEndPoint;
                    var dataStream = getEncryptionStream(GetMyStreamFromSocket(socket));
                    var buf        = new BytesSegment(new byte[3]);
                    await dataStream.ReadFullAsyncR(buf).CAF(); // read ahead

                    var    addrType   = (Socks5Server.AddrType)buf[0];
                    string addrString = null;
                    switch (addrType)
                    {
                    case Socks5Server.AddrType.IPv4Address:
                    case Socks5Server.AddrType.IPv6Address:
                        var buf2 = new byte[addrType == Socks5Server.AddrType.IPv4Address ? 4 : 16];
                        buf2[0] = buf[1];
                        buf2[1] = buf[2];
                        await dataStream.ReadFullAsyncR(new BytesSegment(buf2, 2, buf2.Length - 2)).CAF();

                        var ip = new IPAddress(buf2);
                        addrString = ip.ToString();
                        break;

                    case Socks5Server.AddrType.DomainName:
                        var length = buf[1];
                        if (length == 0)
                        {
                            Logger.warning($"zero addr length ({remoteEP})");
                            await Task.Delay(10 * 1000).CAF();

                            return;
                        }
                        var dnBuf = new byte[length];
                        dnBuf[0] = buf[2];
                        await dataStream.ReadFullAsyncR(new BytesSegment(dnBuf, 1, length - 1)).CAF();

                        addrString = Encoding.ASCII.GetString(dnBuf, 0, length);
                        break;

                    default:
                        Logger.warning($"unknown addr type {addrType} ({remoteEP})");
                        await Task.Delay(10 * 1000 + NaiveUtils.Random.Next(20 * 1000)).CAF();

                        return;
                    }
                    await dataStream.ReadFullAsyncR(buf.Sub(0, 2)).CAF();

                    int port = buf[0] << 8 | buf[1];
                    var dest = new AddrPort(addrString, port);
                    await Controller.HandleInConnection(InConnectionTcp.Create(this, dest, dataStream, $"remote={remoteEP}")).CAF();
                }
            } catch (Exception e) {
                Logger.exception(e, Logging.Level.Error, "handling connection");
            }
        }
예제 #3
0
        private async Task <int> ComplexRead(BytesSegment bs)
        {
            await WaitBeforeRead;

            WaitBeforeRead = AwaitableWrapper.GetCompleted();
            var r = await _ReadAsyncR(bs, true);

            OnRead(bs.Sub(0, r));
            return(r);
        }
예제 #4
0
        private void MoveNext()
        {
            if (step == 0)
            {
            }
            else if (step == 1)
            {
                goto STEP1;
            }
            else
            {
                throw new Exception();
            }

            //while (pos < bs.Len) {
WHILE:
            try {
                if (!(pos < bs.Len))
                {
                    goto EWHILE;
                }
                awaitable = myStream.ReadAsyncR(bs.Sub(pos));
                step      = 1;
                if (awaitable.IsCompleted)
                {
                    goto STEP1;
                }
                awaitable.UnsafeOnCompleted(_moveNext);
            } catch (Exception e) {
                ResetState();
                SetException(e);
                return;
            }
            return;

STEP1:
            try {
                var read = awaitable.GetResult();
                if (read == 0)
                {
                    throw new DisconnectedException($"unexpected EOF while ReadFull() (count={bs.Len}, pos={pos})");
                }
                pos += read;
            } catch (Exception e) {
                ResetState();
                SetException(e);
                return;
            }
            goto WHILE;
            //}
EWHILE:
            ResetState();
            SetResult(VoidType.Void);
            return;
        }
예제 #5
0
        private int PreReadAsync(ref BytesSegment bs, bool full)
        {
            var bufRead = TryReadInternalBuffer(bs);

            if (bufRead > 0)
            {
                if ((full || (EnableSmartSyncRead && Enable2ndBufferCheck)) && bs.Len > bufRead && socketAvailable > 0)
                {
                    int read = ReadSync_SocketHaveAvailableData(bs.Sub(bufRead));
                    return(bufRead + read);
                }
                else
                {
                    return(bufRead);
                }
            }

            if (full)
            {
                // when bufRead == 0 && socketAvailable > 0
                int read = ReadSync_SocketHaveAvailableData(bs);
                return(read);
            }

            if (EnableSmartSyncRead || (EnableReadaheadBuffer && bs.Len < ReadaheadBufferSize))
            {
                if (socketAvailable < bs.Len || socketAvailable < ReadaheadBufferSize)
                {
                    // Get the Available value from socket when needed.
                    socketAvailable = GetAvailable();
                }
                var bufRead2 = TryFillAndReadInternalBuffer(bs);
                if (bufRead2 > 0)
                {
                    return(bufRead2);
                }
                if (EnableSmartSyncRead && socketAvailable > 0)
                {
                    // If the receive buffer of OS is not empty,
                    // use sync operation to reduce async overhead.
                    // This optimization made ReadAsync 12x faster.
                    int read = ReadSync_SocketHaveAvailableData(bs);
                    return(read);
                }
            }
            return(0);
        }
예제 #6
0
        public async Task <ClientHello> ReadClientHello()
        {
            var recordHeader = new BytesSegment(new byte[5]);
            await RealBaseStream.ReadFullAsyncR(recordHeader);

            MyStreamWrapper.Queue = recordHeader;
            ushort ver = 0;
            int    recordPayloadLength = GetRecordPayloadLength(recordHeader, ref ver);

            var record = new BytesSegment(new byte[5 + recordPayloadLength]);

            recordHeader.CopyTo(record);
            var msg = record.Sub(5);
            await RealBaseStream.ReadFullAsyncR(msg);

            MyStreamWrapper.Queue = record;
            var ch = new ClientHello();

            ParseClientHello(msg, ref ch);
            return(ch);
        }
예제 #7
0
        public void ClientData(object sender, BytesSegment _bs)
        {
            if (clientDone || _bs.Len == 0)
            {
                return;
            }
            clientDone = true;
            try {
                TlsStream.ParseClientHelloRecord(_bs, ref Tls, out var size);
            } catch (Exception e) {
                if (Tls.Version != 0)
                {
                    TlsError = true;
                    Logging.exception(e, Logging.Level.Warning, "parsing tls client hello from " + sender);
                }
            }

            try {
                var bs   = _bs;
                var http = false;
                foreach (var item in httpMethods)
                {
                    if (Match(bs, item) && bs.GetOrZero(item.Length) == ' ')
                    {
                        bs.SubSelf(item.Length + 1);
                        http = true;
                        break;
                    }
                }
                if (http)
                {
                    Protocol = "HTTP?";
                    var begin = Find(bs, (byte)' ');
                    if (begin != -1)
                    {
                        begin += 1;
                        bs.SubSelf(begin);
                        if (Match(bs, "HTTP"))
                        {
                            var len = Find(bs.Sub(0, Math.Min(bs.Len, 10)), (byte)'\r');
                            if (len == -1)
                            {
                                len = Find(bs.Sub(0, Math.Min(bs.Len, 10)), (byte)'\n');
                            }
                            if (len != -1)
                            {
                                Protocol = Encoding.ASCII.GetString(bs.Bytes, bs.Offset, len);
                            }
                        }
                    }
                }
            } catch (Exception) {
            }

            if (Protocol != null)
            {
                return;
            }

            if (Match(_bs, "SSH-"))
            {
                Protocol = "SSH";
                return;
            }
            if (Match(_bs, "\x0013BitTorrent protocol"))
            {
                Protocol = "BitTorrent";
                return;
            }

            if (_bs[0] == '<')
            {
                // XML stream?
                var bs = _bs.Sub(1);
                if (Match(bs, "?xml version="))
                {
                    Protocol = "XML?";
                    // skip xml declaration
                    var end = Find(bs, (byte)'>');
                    if (end != -1)
                    {
                        bs.Sub(end + 1);
                    }
                }
                while (Match(bs, "\r") || Match(bs, "\n"))
                {
                    bs.SubSelf(1);
                }
                if (Match(bs, "<stream"))
                {
                    Protocol = "XMPP?";
                }
            }

            if (_bs.Len >= 2 && _bs[0] == 0x10)
            {
                // MQTT CONNECT?
                var remainingLength = _bs[1];
                if (2 + remainingLength <= _bs.Len)
                {
                    var payload = _bs.Sub(2, remainingLength);
                    if (Match(payload, "\x0000\x0004MQTT"))
                    {
                        Protocol = "MQTT";
                        if (payload.Len >= 7)
                        {
                            var version = payload[6];
                            Protocol += version == 5 ? "(v5.0)" :
                                        version == 4 ? "(v3.1.1)" :
                                        $"(v{version})";
                        }
                    }
                }
            }
        }