예제 #1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="callback"></param>
 /// <returns></returns>
 public SocketResult Error <TResult>(Fleck2Extensions.Action <TResult> callback)
 {
     if (_result is Exception)
     {
         callback((TResult)_result);
     }
     return(this);
 }
예제 #2
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="callback"></param>
 /// <returns></returns>
 public SocketResult Success(Fleck2Extensions.Action callback)
 {
     if (!(_result is Exception))
     {
         callback();
     }
     return(this);
 }
예제 #3
0
        public void Setup()
        {
            _request   = new WebSocketHttpRequest();
            _onClose   = delegate { };
            _onMessage = delegate { };
            _onBinary  = delegate { };

            _handler = Hybi13Handler.Create(_request, s => _onMessage(s), () => _onClose(), b => _onBinary(b));
        }
예제 #4
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="beginMethod"></param>
 /// <param name="endMethod"></param>
 /// <param name="resultCallback"> </param>
 /// <returns></returns>
 public void HandleAsyncVoid <T>(Fleck2Extensions.Func <AsyncCallback, object, T> beginMethod,
                                 Fleck2Extensions.Action <T> endMethod, Action <SocketResult> resultCallback)
 {
     DoAsyncTask(() => beginMethod(result => DoAsyncTask(() =>
     {
         endMethod((T)result);
         resultCallback(new SocketResult(true));
     }, resultCallback), null), resultCallback);
 }
예제 #5
0
        public void Setup()
        {
            _request = new WebSocketHttpRequest();
            _onClose = delegate { };
            _onMessage = delegate { };
            _onBinary = delegate { };

            _handler = Hybi13Handler.Create(_request, s => _onMessage(s), () => _onClose(), b => _onBinary(b));
        }
예제 #6
0
        public void Receive(byte[] buffer, Fleck2Extensions.Action <int> callback, Fleck2Extensions.Action <Exception> error, int offset = 0)
        {
            Fleck2Extensions.Func <AsyncCallback, object, IAsyncResult> begin = (cb, data) =>
                                                                                _stream.BeginRead(buffer, offset, buffer.Length, cb, data);

            _socketFactory.HandleAsync(begin, _stream.EndRead, result =>
            {
                result.Success(callback);
                result.Error(error);
            });
        }
        public void Send(byte[] buffer, Fleck2Extensions.Action callback, Fleck2Extensions.Action <Exception> error)
        {
            Fleck2Extensions.Func <AsyncCallback, object, IAsyncResult> begin =
                (cb, s) => _stream.BeginWrite(buffer, 0, buffer.Length, cb, s);

            _socketFactory.HandleAsyncVoid(begin, _stream.EndWrite, result =>
            {
                result.Success(callback);
                result.Error(error);
            });
        }
        public void Accept(Fleck2Extensions.Action <ISocket> callback, Fleck2Extensions.Action <Exception> error)
        {
            Fleck2Extensions.Func <IAsyncResult, ICancellationToken, ISocket> end = (result, token) =>
            {
                token.ThrowIfCancellationRequested();
                return(new SocketWrapper(_socket.EndAccept(result)));
            };

            _socketFactory.HandleAsync(_socket.BeginAccept, end, result =>
            {
                result.Success(callback);
                result.Error(error);
            });
        }
        public void Authenticate(X509Certificate2 certificate, Fleck2Extensions.Action callback, Fleck2Extensions.Action <Exception> error)
        {
            var ssl = new SslStream(_stream, false);

            _stream = ssl;

            Fleck2Extensions.Func <AsyncCallback, object, IAsyncResult> begin =
                (cb, s) => ssl.BeginAuthenticateAsServer(certificate, false, SslProtocols.Tls, false, cb, s);

            _socketFactory.HandleAsyncVoid(begin, ssl.EndAuthenticateAsServer, result =>
            {
                result.Success(callback);
                result.Error(error);
            });
        }
예제 #10
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="unitOfWork"></param>
 /// <param name="resultCallback"> </param>
 private static void DoAsyncTask(Fleck2Extensions.Action unitOfWork, Action <SocketResult> resultCallback)
 {
     ThreadPool.QueueUserWorkItem(delegate
     {
         try
         {
             unitOfWork();
         }
         catch (SocketCancellationTokenException)
         {
         } catch (Exception ex)
         {
             resultCallback(new SocketResult(ex));
         }
     });
 }
예제 #11
0
        public void ShouldCloseOnCloseFromValidStatusCode()
        {
            var frame = new Hybi14DataFrame
            {
                FrameType = FrameType.Close,
                IsFinal   = true,
                IsMasked  = true,
                MaskKey   = 5232,
                Payload   = 1000.ToBigEndianBytes < ushort > ()
            };

            var hit = false;

            _onClose = () => hit = true;
            _handler.Receive(frame.ToBytes());

            Assert.IsTrue(hit);
        }
예제 #12
0
        public void ShouldCloseOnCloseFromText()
        {
            var payload = Fleck2Extensions.ToArray(1000.ToBigEndianBytes < ushort > ().Concat(Encoding.UTF8.GetBytes("Reason")));
            var frame   = new Hybi14DataFrame
            {
                FrameType = FrameType.Close,
                IsFinal   = true,
                IsMasked  = true,
                MaskKey   = 5232,
                Payload   = payload
            };

            var hit = false;

            _onClose = () => hit = true;
            _handler.Receive(frame.ToBytes());

            Assert.IsTrue(hit);
        }
예제 #13
0
 private void SendBytes(byte[] bytes, Fleck2Extensions.Action callback = null)
 {
     Socket.Send(bytes, () =>
     {
         FleckLog.Debug("Sent " + bytes.Length + " bytes");
         if (callback != null)
         {
             callback();
         }
     },
                 e =>
     {
         if (e is IOException)
         {
             FleckLog.Debug("Failed to send. Disconnecting.", e);
         }
         else
         {
             FleckLog.Info("Failed to send. Disconnecting.", e);
         }
         CloseSocket();
     });
 }
예제 #14
0
        public static void ReceiveData(List <byte> data, ReadState readState, Fleck2Extensions.Action <FrameType, byte[]> processFrame)
        {
            while (data.Count >= 2)
            {
                var isFinal      = (data[0] & 128) != 0;
                var reservedBits = (data[0] & 112);
                var frameType    = (FrameType)(data[0] & 15);
                var isMasked     = (data[1] & 128) != 0;
                var length       = (data[1] & 127);


                if (!isMasked ||
                    !Enum.IsDefined(typeof(FrameType), frameType) ||
                    reservedBits != 0 || //Must be zero per spec 5.2
                    (frameType == FrameType.Continuation && !readState.FrameType.HasValue))
                {
                    throw new WebSocketException(WebSocketStatusCodes.ProtocolError);
                }

                var index = 2;
                int payloadLength;

                switch (length)
                {
                case 127:
                    if (data.Count < index + 8)
                    {
                        return;     //Not complete
                    }
                    payloadLength = data.Skip(index).Take(8).ToArray().ToLittleEndianInt();
                    index        += 8;
                    break;

                case 126:
                    if (data.Count < index + 2)
                    {
                        return;     //Not complete
                    }
                    payloadLength = data.Skip(index).Take(2).ToArray().ToLittleEndianInt();
                    index        += 2;
                    break;

                default:
                    payloadLength = length;
                    break;
                }

                if (data.Count < index + 4)
                {
                    return; //Not complete
                }
                var maskBytes = data.Skip(index).Take(4).ToList();

                index += 4;

                if (data.Count < index + payloadLength)
                {
                    return; //Not complete
                }
                var i       = 0;
                var payload = data.Skip(index)
                              .Take(payloadLength)
                              .Select(value => (byte)(value ^ maskBytes[i++ % 4]));

                readState.Data.AddRange(payload);
                data.RemoveRange(0, index + payloadLength);

                if (frameType != FrameType.Continuation)
                {
                    readState.FrameType = frameType;
                }

                if (!isFinal || !readState.FrameType.HasValue)
                {
                    continue;
                }

                var stateData      = readState.Data.ToArray();
                var stateFrameType = readState.FrameType;
                readState.Clear();

                processFrame(stateFrameType.Value, stateData);
            }
        }
예제 #15
0
        public static void ProcessFrame(FrameType frameType, byte[] data, Action <string> onMessage, Fleck2Extensions.Action onClose, Action <byte[]> onBinary)
        {
            switch (frameType)
            {
            case FrameType.Close:
                if (data.Length == 1 || data.Length > 125)
                {
                    throw new WebSocketException(WebSocketStatusCodes.ProtocolError);
                }

                if (data.Length >= 2)
                {
                    var closeCode = (ushort)(data.Take(2).ToArray().ToLittleEndianInt());
                    if (!WebSocketStatusCodes.Contains(closeCode) && (closeCode < 3000 || closeCode > 4999))
                    {
                        throw new WebSocketException(WebSocketStatusCodes.ProtocolError);
                    }
                }

                if (data.Length > 2)
                {
                    ReadUtf8PayloadData(data.Skip(2));
                }

                onClose();
                break;

            case FrameType.Binary:
                onBinary(data);
                break;

            case FrameType.Text:
                onMessage(ReadUtf8PayloadData(data));
                break;

            default:
                FleckLog.Debug("Received unhandled " + frameType);
                break;
            }
        }
예제 #16
0
        public static IHandler Create(WebSocketHttpRequest request, Action <string> onMessage, Fleck2Extensions.Action onClose, Action <byte[]> onBinary)
        {
            var readState = new ReadState();

            return(new ComposableHandler
            {
                Handshake = () => BuildHandshake(request),
                TextFrame = data => FrameData(Encoding.UTF8.GetBytes(data), FrameType.Text),
                BinaryFrame = data => FrameData(data, FrameType.Binary),
                CloseFrame = i => FrameData(i.ToBigEndianBytes <ushort>(), FrameType.Close),
                ReceiveData = bytes => ReceiveData(bytes, readState, (op, data) => ProcessFrame(op, data, onMessage, onClose, onBinary))
            });
        }
예제 #17
0
        public static IHandler BuildHandler(WebSocketHttpRequest request, Action <string> onMessage, Fleck2Extensions.Action onClose, Action <byte[]> onBinary)
        {
            var version = GetVersion(request);

            switch (version)
            {
            case "76":
                return(Draft76Handler.Create(request, onMessage));

            case "7":
            case "8":
            case "13":
                return(Hybi13Handler.Create(request, onMessage, onClose, onBinary));
            }

            throw new WebSocketException(WebSocketStatusCodes.UnsupportedDataType);
        }
예제 #18
0
        public void ShouldCloseOnCloseFromValidStatusCode()
        {
            var frame = new Hybi14DataFrame
                {
                    FrameType = FrameType.Close,
                    IsFinal = true,
                    IsMasked = true,
                    MaskKey = 5232,
                    Payload = 1000.ToBigEndianBytes<ushort>()
                };

            var hit = false;
            _onClose = () => hit = true;
            _handler.Receive(frame.ToBytes());

            Assert.IsTrue(hit);
        }
예제 #19
0
        public void ShouldCloseOnCloseFromText()
        {
            var payload = Fleck2Extensions.ToArray(1000.ToBigEndianBytes<ushort>().Concat(Encoding.UTF8.GetBytes("Reason")));
            var frame = new Hybi14DataFrame
                {
                    FrameType = FrameType.Close,
                    IsFinal = true,
                    IsMasked = true,
                    MaskKey = 5232,
                    Payload = payload
                };

            var hit = false;
            _onClose = () => hit = true;
            _handler.Receive(frame.ToBytes());

            Assert.IsTrue(hit);
        }