Beispiel #1
0
 ToDynamicFrameSubject(this Socket socket, ISimpleFrameEncoder encoder, IDynamicFrameDecoder decoder,
                       SyncBufManager bufferManager, CancellationToken token)
 {
     return(Subject.Create <DisposableValue <ArraySegment <byte> >, DisposableValue <ArraySegment <byte> > >(
                socket.ToFrameClientObserver(encoder, token, bufferManager),
                socket.ToDynamicFrameObservable(bufferManager, decoder)));
 }
Beispiel #2
0
        public static IObservable <DisposableValue <ArraySegment <byte> > > ToDynamicFrameObservable(this Socket socket,
                                                                                                     SyncBufManager bufferManager, IDynamicFrameDecoder decoder)
        {
            return(Observable.Create <DisposableValue <ArraySegment <byte> > >(async(observer, token) =>
            {
                try
                {
                    var state = decoder.InitState();
                    byte[] leftoverBuf = null;
                    //rider suggestion is buggy: this variable must declare outside the loop in the case when receive length is zero
                    int leftoverCount = 0;
                    while (!token.IsCancellationRequested)
                    {
                        byte[] bufferArray;
                        int startIdx;
                        if (leftoverBuf != null)
                        {
                            bufferArray = leftoverBuf;
                            startIdx = leftoverCount;
                            leftoverBuf = null;
                        }
                        else
                        {
                            bufferArray = bufferManager.TakeBuffer(decoder.BufferSize);
                            startIdx = 0;
                        }
                        var pair = await socket.ReceiveDynamicFrame(state, bufferArray, startIdx, decoder, token);
                        var receiveLen = pair.Item1;
                        leftoverCount = pair.Item2;
                        if (receiveLen == 0) //no data received, and leftoverCount should be zero
                        {
                            var dropFrameStrategy = decoder.CheckDropFrame(state, bufferArray, startIdx);
                            switch (dropFrameStrategy)
                            {
                            case DropFrameStrategyEnum.DropAndClose:
                                //reclaim buffer array
                                bufferManager.ReturnBuffer(bufferArray);
                                break;

                            case DropFrameStrategyEnum.DropAndRestart:
                                //reclaim buffer array
                                bufferManager.ReturnBuffer(bufferArray);
                                continue;

                            case DropFrameStrategyEnum.KeepAndContinue:
                                //keep last received data
                                leftoverBuf = bufferArray;
                                leftoverCount = startIdx;
                                continue;
                            }
                            if (dropFrameStrategy == DropFrameStrategyEnum.DropAndClose)
                            {
                                break;
                            }
                        }
                        if (receiveLen == -1) //overflow,TODO support extensible frame in future
                        {
                            //reclaim buffer array
                            bufferManager.ReturnBuffer(bufferArray);
                            break;
                        }
                        //copy leftover
                        if (leftoverCount > 0)
                        {
                            leftoverBuf = bufferManager.TakeBuffer(decoder.BufferSize);
                            Buffer.BlockCopy(bufferArray, receiveLen - leftoverCount, leftoverBuf, 0, leftoverCount);
                        }

                        var arraySegment = decoder.BuildFrame(state, bufferArray, receiveLen, leftoverCount);
                        observer.OnNext(
                            new DisposableValue <ArraySegment <byte> >(arraySegment,
                                                                       Disposable.Create(() => bufferManager.ReturnBuffer(bufferArray))));
                    }

                    observer.OnCompleted();

                    socket.Close();
                }
                catch (Exception error)
                {
                    observer.OnError(error);
                }
            }));
        }