Exemple #1
0
        //
        // Loops while subsequent completions are sync.
        //
        private void StartReading()
        {
            while (true)
            {
                IAsyncResult ar = _transportAPM.BeginRead(_request.Buffer, _request.Offset + _totalRead, _request.Count - _totalRead, s_readCallback, this);
                if (!ar.CompletedSynchronously)
                {
#if DEBUG
                    _request._DebugAsyncChain = ar;
#endif
                    break;
                }

                int bytes = _transportAPM.EndRead(ar);

                if (CheckCompletionBeforeNextRead(bytes))
                {
                    break;
                }
            }
        }
Exemple #2
0
        // IO COMPLETION CALLBACK
        //
        // This callback is responsible for getting the complete protocol frame.
        // 1. it reads the header.
        // 2. it determines the frame size.
        // 3. loops while not all frame received or an error.
        //
        private void ReadFrameComplete(IAsyncResult transportResult)
        {
            do
            {
                if (!(transportResult.AsyncState is WorkerAsyncResult))
                {
                    if (GlobalLog.IsEnabled)
                    {
                        GlobalLog.AssertFormat("StreamFramer::ReadFrameComplete|The state expected to be WorkerAsyncResult, received:{0}.", transportResult.GetType().FullName);
                    }

                    Debug.Fail("StreamFramer::ReadFrameComplete|The state expected to be WorkerAsyncResult, received:" + transportResult.GetType().FullName + ".");
                }

                WorkerAsyncResult workerResult = (WorkerAsyncResult)transportResult.AsyncState;

                int bytesRead = _transportAPM.EndRead(transportResult);
                workerResult.Offset += bytesRead;

                if (!(workerResult.Offset <= workerResult.End))
                {
                    if (GlobalLog.IsEnabled)
                    {
                        GlobalLog.AssertFormat("StreamFramer::ReadFrameCallback|WRONG: offset - end = {0}", workerResult.Offset - workerResult.End);
                    }

                    Debug.Fail("StreamFramer::ReadFrameCallback|WRONG: offset - end = " + (workerResult.Offset - workerResult.End));
                }

                if (bytesRead <= 0)
                {
                    // (by design) This indicates the stream has receives EOF
                    // If we are in the middle of a Frame - fail, otherwise - produce EOF
                    object result = null;
                    if (!workerResult.HeaderDone && workerResult.Offset == 0)
                    {
                        result = (object)-1;
                    }
                    else
                    {
                        result = new System.IO.IOException(SR.net_frame_read_io);
                    }

                    workerResult.InvokeCallback(result);
                    return;
                }

                if (workerResult.Offset >= workerResult.End)
                {
                    if (!workerResult.HeaderDone)
                    {
                        workerResult.HeaderDone = true;
                        // This indicates the header has been read succesfully
                        _curReadHeader.CopyFrom(workerResult.Buffer, 0, _readVerifier);
                        int payloadSize = _curReadHeader.PayloadSize;
                        if (payloadSize < 0)
                        {
                            // Let's call user callback and he call us back and we will throw
                            workerResult.InvokeCallback(new System.IO.IOException(SR.Format(SR.net_frame_read_size)));
                        }

                        if (payloadSize == 0)
                        {
                            // report emtpy frame (NOT eof!) to the caller, he might be interested in
                            workerResult.InvokeCallback(0);
                            return;
                        }

                        if (payloadSize > _curReadHeader.MaxMessageSize)
                        {
                            throw new InvalidOperationException(SR.Format(SR.net_frame_size,
                                                                          _curReadHeader.MaxMessageSize.ToString(NumberFormatInfo.InvariantInfo),
                                                                          payloadSize.ToString(NumberFormatInfo.InvariantInfo)));
                        }

                        // Start reading the remaining frame data (note header does not count).
                        byte[] frame = new byte[payloadSize];
                        // Save the ref of the data block
                        workerResult.Buffer = frame;
                        workerResult.End    = frame.Length;
                        workerResult.Offset = 0;

                        // Transport.BeginRead below will pickup those changes.
                    }
                    else
                    {
                        workerResult.HeaderDone = false; // Reset for optional object reuse.
                        workerResult.InvokeCallback(workerResult.End);
                        return;
                    }
                }

                // This means we need more data to complete the data block.
                transportResult = _transportAPM.BeginRead(workerResult.Buffer, workerResult.Offset, workerResult.End - workerResult.Offset,
                                                          _readFrameCallback, workerResult);
            } while (transportResult.CompletedSynchronously);
        }