internal IObservable <string> CreateWebsocketListenerObservable( Stream tcpStream, IEnumerable <string> subProtocols = null) { ParserDelegate = new HttpParserDelegate(); var parserHandler = new HttpCombinedParser(ParserDelegate); _textDataParser.Reinitialize(); _tcpStream = tcpStream; _observerDataReceiveMode.OnNext(DataReceiveState.IsListeningForHandShake); _dataReceiveState = DataReceiveState.IsListeningForHandShake; var listenerObservable = Observable.Create <string>( obs => { var disposableReceiveState = DataReceiveStateObservable.Subscribe(s => { _dataReceiveState = s; }, obs.OnError, () => { Debug.WriteLine("DataReceiveObservable completed"); }); var disposableStreamListener = Observable.While( () => _dataReceiveState == DataReceiveState.IsListeningForHandShake || _dataReceiveState == DataReceiveState.IsListening, Observable.FromAsync(() => ReadOneByteAtTheTimeAsync(tcpStream))) .Select(b => Observable.FromAsync(() => ParseWebSocketAsync(b, ParserDelegate, parserHandler, subProtocols, obs))) .Concat() .Subscribe( _ => { if (_textDataParser.IsCloseReceived) { _observerDataReceiveMode.OnNext(DataReceiveState.Exiting); _observerDataReceiveMode.OnCompleted(); } }, obs.OnError, obs.OnCompleted); return(new CompositeDisposable(disposableReceiveState, disposableStreamListener)); }); return(listenerObservable); }
/// <summary> /// Initializes a new instance of the <see cref="TcpConnection"/> class. /// </summary> /// <param name="client">The associated socket.</param> /// <param name="littleEndianByteOrder">The expected endianness of integral value types.</param> public TcpConnection(Socket client, bool littleEndianByteOrder = true) { Assert.ParamIsNotNull(client); mClient = client; mNetworkStream = new NetworkStream(client); mReader = new BinaryReader(mNetworkStream); mWriter = new BinaryWriter(mNetworkStream); mLittleEndianByteOrder = littleEndianByteOrder; mReceiveState = DataReceiveState.MessageFraming; mPartiallyReceivedData = new byte[ReceivedDataBufferSize]; mCompletelyReceivedData = new List<byte>(); mMessageLengthData = new byte[4]; mBytesToProcessRemaining = 0; }
public EODataChunk() : base(BUFFER_SIZE) { State = DataReceiveState.ReadLen1; RawLength = new byte[2]; }
public EODataChunk() : base(BUFFER_SIZE) { State = DataReceiveState.ReadLen1; RawLength = new byte[2]; }
/// <summary> /// The callback paired with Socket.BeginReceive(). /// </summary> /// <param name="asyncResult"></param> private void DataReceivedCallback(IAsyncResult asyncResult) { if (mIsClosed) { return; } try { int bytesReceived = mClient.EndReceive(asyncResult); if (bytesReceived > 0) { mBytesToProcessRemaining = bytesReceived; mCompletelyReceivedData.AddRange(new SubArray<byte>(mPartiallyReceivedData, 0, bytesReceived)); while (mBytesToProcessRemaining > 0) { switch (mReceiveState) { case TcpConnection.DataReceiveState.MessageFraming: { // Read message length if (mCompletelyReceivedData.Count >= 4) { mCompletelyReceivedData.CopyTo(0, mMessageLengthData, 0, 4); if (BitConverter.IsLittleEndian != mLittleEndianByteOrder) { mMessageLengthData = Utility.SwapEndian(mMessageLengthData); } mMessageLength = BitConverter.ToInt32(mMessageLengthData, 0); Assert.IsTrue(mMessageLength > 0); mReceiveState = TcpConnection.DataReceiveState.Message; mCompletelyReceivedData.RemoveRange(0, 4); mBytesToProcessRemaining -= 4; } break; } case DataReceiveState.Message: { if (mCompletelyReceivedData.Count >= mMessageLength) { byte[] message = new byte[mMessageLength]; mCompletelyReceivedData.CopyTo(0, message, 0, mMessageLength); OnDataReceived(new TcpDataReceivedEventArgs(this, message)); mReceiveState = TcpConnection.DataReceiveState.MessageFraming; mCompletelyReceivedData.RemoveRange(0, mMessageLength); } mBytesToProcessRemaining = 0; break; } } } InitDataReceivedCallback(); } else { // bytesReceived == 0 when the socket gets shutdown; therefore, remove the connection. mCompletelyReceivedData.Clear(); Close(); return; } } catch { Close(); } }