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; } }
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)) }; }
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 WebSocketConnection(ISocket socket, Action<IWebSocketConnection> initialize, Fleck2Extensions.Func<byte[], WebSocketHttpRequest> parseRequest, Fleck2Extensions.Func<WebSocketHttpRequest, IHandler> handlerFactory) { Socket = socket; OnOpen = () => { }; OnClose = () => { }; OnMessage = x => { }; OnBinary = x => { }; OnError = x => { }; _initialize = initialize; _handlerFactory = handlerFactory; _parseRequest = parseRequest; }
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); }
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); } }
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(); }); }
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); }); }
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 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); }); }