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; } }
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"); } }
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); }
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; }
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); }
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); }
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})"; } } } } }