예제 #1
0
        private int TryFillAndReadInternalBuffer(BytesSegment bs)
        {
            var readBufferSize = this.ReadaheadBufferSize;

            if (EnableReadaheadBuffer && (socketAvailable > bs.Len & bs.Len < readBufferSize))
            {
                if (readaheadScore > 0)
                {
                    readaheadScore--;
                }
                if (readaheadBuffer.Bytes == null)
                {
                    if (readaheadScore > 0)
                    {
                        return(0);
                    }
                    readaheadBuffer.Bytes = new byte[readBufferSize];
                }
                else if (readaheadBuffer.Bytes.Length < readBufferSize)
                {
                    readaheadBuffer.Bytes = new byte[readBufferSize];
                }
                Interlocked.Increment(ref ctr.Rsync);
                readaheadBuffer.Offset = 0;
                readaheadBuffer.Len    = readBufferSize;
                var read = ReadSocketDirectSync(readaheadBuffer);
                readaheadBuffer.Len = read;
                if (read <= 0)
                {
                    throw new Exception($"{this} should not happen: Socket.Receive() returns {read} when Socket.Available > 0.");
                }
                read = Math.Min(read, bs.Len);
                readaheadBuffer.CopyTo(bs, read);
                readaheadBuffer.SubSelf(read);
                return(read);
            }
            else
            {
                if (readaheadScore < readaheadScoreMax)
                {
                    if (++readaheadScore == readaheadScoreMax)
                    {
                        // There are many large reading opearations, so the internal buffer can be released now.
                        readaheadBuffer.Bytes = null;
                    }
                }
                return(0);
            }
        }
예제 #2
0
 public async Task <int> ReadAsync(BytesSegment bs)
 {
     lock (_syncRoot) {
         if (tcsNewBuffer?.IsCompleted == false)
         {
             throw new Exception("another recv task is running.");
         }
         if (buffer.Len == 0 & !recvEOF)
         {
             tcsNewBuffer.Reset();
         }
     }
     if (tcsNewBuffer != null)
     {
         await tcsNewBuffer;
     }
     lock (_syncRoot) {
         if (recvEOF && buffer.Len == 0)
         {
             return(0);
         }
         int read = Math.Min(bs.Len, buffer.Len);
         buffer.CopyTo(bs, 0, read);
         buffer.SubSelf(read);
         if (buffer.Len == 0)
         {
             buffer = new BytesSegment();
             tcsBufferEmptied.SetResult(0);
         }
         return(read);
     }
 }
예제 #3
0
 private void Dequeue(BytesSegment bs, int len)
 {
     Queue.CopyTo(bs, len);
     Queue.SubSelf(len);
     if (Queue.Len == 0)
     {
         Queue.ResetSelf();
     }
 }
예제 #4
0
        public void ServerData(object sender, BytesSegment bs)
        {
            if (serverDone || bs.Len == 0)
            {
                return;
            }
            serverDone = true;
            if (sBuf != null)
            {
                bs.CopyTo(sBuf, 0, bs.Len, sProg);
                sProg += bs.Len;
                if (sProg < sBuf.Length)
                {
                    goto CONTINUE_READ;
                }
                else
                {
                    bs = new BytesSegment(sBuf, 0, sProg);
                }
            }
            if (Tls.Version != 0)
            {
                var hello = new TlsStream.ServerHello();
                try {
                    TlsStream.ParseServerHelloRecord(bs, ref hello, out var size);
                    if (size > bs.Len)
                    {
                        if (sBuf != null)
                        {
                            throw new Exception("sBuf != null");
                        }
                        sBuf = new byte[size];
                        bs.CopyTo(sBuf);
                        sProg = bs.Len;
                        goto CONTINUE_READ;
                    }
                } catch (Exception e) {
                    if (hello.Version != 0)
                    {
                        TlsError = true;
                        Logging.exception(e, Logging.Level.Warning, "parsing tls server hello from " + sender);
                    }
                }
                Tls.Version = Math.Min(Tls.Version, hello.Version);
                Tls.Alpn    = hello.Alpn;
            }
            sBuf = null;
            return;

CONTINUE_READ:
            serverDone = false;
            return;
        }
예제 #5
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);
        }