public override WebSocket CreateWebSocket(Stream stream, WebSocketListenerOptions options, IPEndPoint localEndpoint, IPEndPoint remoteEndpoint, WebSocketHttpRequest httpRequest, WebSocketHttpResponse httpResponse, List<IWebSocketMessageExtensionContext> negotiatedExtensions) { var webSocket = new WebSocketRfc6455(stream, options, localEndpoint, remoteEndpoint, httpRequest, httpResponse, negotiatedExtensions); if (OnPingReceived != null) webSocket.OnPingReceived = OnPingReceived; return webSocket; }
internal WebSocketConnectionRfc6455(Stream clientStream, WebSocketListenerOptions options) { Guard.ParameterCannotBeNull(clientStream, "clientStream"); Guard.ParameterCannotBeNull(options, "options"); _writeSemaphore = new SemaphoreSlim(1); _options = options; _clientStream = clientStream; if (options.BufferManager != null) _buffer = options.BufferManager.TakeBuffer(14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4 + 2); else _buffer = new Byte[14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4 + 2]; _headerBuffer = new ArraySegment<Byte>(_buffer, 0, 14); _controlBuffer = new ArraySegment<Byte>(_buffer, 14, 125); _pongBuffer = new ArraySegment<Byte>(_buffer, 14 + 125, 125); _pingBuffer = new ArraySegment<Byte>(_buffer, 14 + 125 + 125, 8); SendBuffer = new ArraySegment<Byte>(_buffer, 14 + 125 + 125 + 8 + 10, _options.SendBufferSize); _keyBuffer = new ArraySegment<Byte>(_buffer, 14 + 125 + 125 + 8 + 10 + _options.SendBufferSize, 4); _closeBuffer = new ArraySegment<Byte>(_buffer, 14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4, 2); switch (options.PingMode) { case PingModes.BandwidthSaving: _ping = new BandwidthSavingPing(this, _options.PingTimeout, _pingBuffer); break; case PingModes.LatencyControl: default: _ping = new LatencyControlPing(this, _options.PingTimeout, _pingBuffer); break; } }
public HttpNegotiationQueue(WebSocketFactoryCollection standards, WebSocketConnectionExtensionCollection extensions, WebSocketListenerOptions options) { Guard.ParameterCannotBeNull(standards, "standards"); Guard.ParameterCannotBeNull(extensions, "extensions"); Guard.ParameterCannotBeNull(options, "options"); _options = options; _extensions = extensions; _cancel = new CancellationTokenSource(); _semaphore = new SemaphoreSlim(options.ParallelNegotiations); _sockets = new BufferBlock<Socket>(new DataflowBlockOptions() { BoundedCapacity = options.NegotiationQueueCapacity, CancellationToken = _cancel.Token }); _negotiations = new BufferBlock<WebSocketNegotiationResult>(new DataflowBlockOptions() { BoundedCapacity = options.NegotiationQueueCapacity, CancellationToken = _cancel.Token, }); _cancel.Token.Register(_sockets.Complete); _cancel.Token.Register(_negotiations.Complete); _handShaker = new WebSocketHandshaker(standards, _options); Task.Run((Func<Task>)WorkAsync); }
public WebSocketRfc6455(Stream clientStream, WebSocketListenerOptions options, IPEndPoint local, IPEndPoint remote, WebSocketHttpRequest httpRequest, IReadOnlyList<IWebSocketMessageExtensionContext> extensions) { if (clientStream == null) throw new ArgumentNullException("clientStream"); if (options == null) throw new ArgumentNullException("options"); if (local == null) throw new ArgumentNullException("local"); if (remote == null) throw new ArgumentNullException("remote"); if (extensions == null) throw new ArgumentNullException("extensions"); if (httpRequest == null) throw new ArgumentNullException("httpRequest"); _remoteEndpoint = remote; _localEndpoint = local; _httpRequest = httpRequest; Connection = new WebSocketConnectionRfc6455(clientStream, options); _extensions = extensions; }
internal WebSocketConnectionRfc6455(Stream clientStream, WebSocketListenerOptions options) { if (clientStream == null) throw new ArgumentNullException("clientStream"); if (options == null) throw new ArgumentNullException("options"); _writeSemaphore = new SemaphoreSlim(1); _options = options; _clientStream = clientStream; if (options.BufferManager != null) _buffer = options.BufferManager.TakeBuffer(14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4 + 2); else _buffer = new Byte[14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4 + 2]; _headerBuffer = new ArraySegment<Byte>(_buffer, 0, 14); _controlBuffer = new ArraySegment<Byte>(_buffer, 14, 125); _pongBuffer = new ArraySegment<Byte>(_buffer, 14 + 125, 125); _pingBuffer = new ArraySegment<Byte>(_buffer, 14 + 125 + 125, 8); SendBuffer = new ArraySegment<Byte>(_buffer, 14 + 125 + 125 + 8 + 10, _options.SendBufferSize); _keyBuffer = new ArraySegment<Byte>(_buffer, 14 + 125 + 125 + 8 + 10 + _options.SendBufferSize, 4); _closeBuffer = new ArraySegment<Byte>(_buffer, 14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4, 2); _pingTimeout = _options.PingTimeout; _pingInterval = TimeSpan.FromMilliseconds(Math.Min(500, _options.PingTimeout.TotalMilliseconds / 2)); }
public WebSocketRfc6455(Stream clientStream, WebSocketListenerOptions options, IPEndPoint local, IPEndPoint remote, WebSocketHttpRequest httpRequest, WebSocketHttpResponse httpResponse, IReadOnlyList<IWebSocketMessageExtensionContext> extensions) :base(httpRequest, httpResponse) { Guard.ParameterCannotBeNull(clientStream, "clientStream"); Guard.ParameterCannotBeNull(options, "options"); Guard.ParameterCannotBeNull(local, "local"); Guard.ParameterCannotBeNull(remote, "remote"); Guard.ParameterCannotBeNull(extensions, "extensions"); Guard.ParameterCannotBeNull(httpRequest, "httpRequest"); _remoteEndpoint = remote; _localEndpoint = local; Connection = new WebSocketConnectionRfc6455(clientStream, options); _extensions = extensions; }
internal WebSocketConnectionRfc6455(Stream clientStream, WebSocketListenerOptions options) { Guard.ParameterCannotBeNull(clientStream, "clientStream"); Guard.ParameterCannotBeNull(options, "options"); _writeSemaphore = new SemaphoreSlim(1); _options = options; _clientStream = clientStream; if (options.BufferManager != null) { _buffer = options.BufferManager.TakeBuffer(14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4 + 2); } else { _buffer = new Byte[14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4 + 2]; } _headerBuffer = new ArraySegment <Byte>(_buffer, 0, 14); _controlBuffer = new ArraySegment <Byte>(_buffer, 14, 125); _pongBuffer = new ArraySegment <Byte>(_buffer, 14 + 125, 125); _pingBuffer = new ArraySegment <Byte>(_buffer, 14 + 125 + 125, 8); SendBuffer = new ArraySegment <Byte>(_buffer, 14 + 125 + 125 + 8 + 10, _options.SendBufferSize); _keyBuffer = new ArraySegment <Byte>(_buffer, 14 + 125 + 125 + 8 + 10 + _options.SendBufferSize, 4); _closeBuffer = new ArraySegment <Byte>(_buffer, 14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4, 2); switch (options.PingMode) { case PingModes.BandwidthSaving: _ping = new BandwidthSavingPing(this, _options.PingTimeout, _pingBuffer); break; case PingModes.LatencyControl: default: _ping = new LatencyControlPing(this, _options.PingTimeout, _pingBuffer); break; } }
public WebSocketRfc6455(Stream clientStream, WebSocketListenerOptions options, IPEndPoint local, IPEndPoint remote, WebSocketHttpRequest httpRequest, WebSocketHttpResponse httpResponse, IReadOnlyList <IWebSocketMessageExtensionContext> extensions) : base(httpRequest, httpResponse) { if (clientStream == null) { throw new ArgumentNullException("clientStream"); } if (options == null) { throw new ArgumentNullException("options"); } if (local == null) { throw new ArgumentNullException("local"); } if (remote == null) { throw new ArgumentNullException("remote"); } if (extensions == null) { throw new ArgumentNullException("extensions"); } if (httpRequest == null) { throw new ArgumentNullException("httpRequest"); } _remoteEndpoint = remote; _localEndpoint = local; Connection = new WebSocketConnectionRfc6455(clientStream, options); _extensions = extensions; }
public HttpNegotiationQueue(WebSocketFactoryCollection standards, WebSocketConnectionExtensionCollection extensions, WebSocketListenerOptions options) { if (standards == null) { throw new ArgumentNullException(nameof(standards)); } if (extensions == null) { throw new ArgumentNullException(nameof(extensions)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } this.log = options.Logger; _options = options; _extensions = extensions; _cancel = new CancellationTokenSource(); _semaphore = new SemaphoreSlim(options.ParallelNegotiations); _connections = new AsyncQueue <NetworkConnection>(options.NegotiationQueueCapacity); _negotiations = new AsyncQueue <WebSocketNegotiationResult>(); _negotiations.ParallelTakeErrorMessage = $"Parallel call to '{nameof(WebSocketListener.AcceptWebSocketAsync)}' is not allowed."; _negotiations.ClosedErrorMessage = $"{nameof(WebSocketListener)} is closed and will not accept new connections."; //_cancel.Token.Register(() => this._connections.Close(new OperationCanceledException())); _handShaker = new WebSocketHandshaker(standards, _options); if (options.PingMode != PingMode.Manual) { this.pingQueue = new PingQueue(options.PingInterval); } WorkAsync().LogFault(this.log); }
public WebSocketEventListener(WebSocketOptions options) { options.ValidateOptions(); _options = options.Clone(); var opts = new WebSocketListenerOptions { // Must disable negotiation timeout for AOT iOS support. NegotiationTimeout = TimeSpan.Zero, PingTimeout = TimeSpan.Zero, PingMode = PingMode.Manual, CertificateValidationHandler = _options.CertificateValidationHandler }; opts.Standards.RegisterRfc6455(); opts.Transports.ConfigureTcp(tcpTransport => { tcpTransport.NoDelay = true; // Dual mode needed for IPv6 support. Does not work with Mono :( tcpTransport.DualMode = _options.DualMode; }); _client = new WebSocketClient(opts); }
public void WebSocketHandshaker_CanDoHttpFallback() { var options = new WebSocketListenerOptions(); options.HttpFallback = _fallback.Object; WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories, options); using (var ms = new MemoryStream()) { using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true)) { sw.WriteLine(@"GET /chat HTTP/1.1"); sw.WriteLine(@"Host: server.example.com"); sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;"); sw.WriteLine(@"Origin: http://example.com"); } var position = ms.Position; ms.Seek(0, SeekOrigin.Begin); var result = handshaker.HandshakeAsync(ms).Result; Assert.IsNotNull(result); Assert.IsFalse(result.IsWebSocketRequest); Assert.IsFalse(result.IsValidWebSocketRequest); Assert.IsTrue(result.IsValidHttpRequest); Assert.IsFalse(result.IsVersionSupported); Assert.AreEqual(new Uri("http://example.com"), result.Request.Headers.Origin); Assert.AreEqual("server.example.com", result.Request.Headers[HttpRequestHeader.Host]); Assert.AreEqual(@"/chat", result.Request.RequestUri.ToString()); Assert.AreEqual(1, result.Request.Cookies.Count); var cookie = result.Request.Cookies["key"]; Assert.AreEqual("key", cookie.Name); Assert.AreEqual(@"W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5", cookie.Value); Assert.IsNotNull(result.Request.LocalEndpoint); Assert.IsNotNull(result.Request.RemoteEndpoint); } }
internal WebSocketConnectionRfc6455(Stream clientStream, WebSocketListenerOptions options) { if (clientStream == null) { throw new ArgumentNullException("clientStream"); } if (options == null) { throw new ArgumentNullException("options"); } _writeSemaphore = new SemaphoreSlim(1); _options = options; _clientStream = clientStream; if (options.BufferManager != null) { _buffer = options.BufferManager.TakeBuffer(14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4 + 2); } else { _buffer = new Byte[14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4 + 2]; } _headerBuffer = new ArraySegment <Byte>(_buffer, 0, 14); _controlBuffer = new ArraySegment <Byte>(_buffer, 14, 125); _pongBuffer = new ArraySegment <Byte>(_buffer, 14 + 125, 125); _pingBuffer = new ArraySegment <Byte>(_buffer, 14 + 125 + 125, 8); SendBuffer = new ArraySegment <Byte>(_buffer, 14 + 125 + 125 + 8 + 10, _options.SendBufferSize); _keyBuffer = new ArraySegment <Byte>(_buffer, 14 + 125 + 125 + 8 + 10 + _options.SendBufferSize, 4); _closeBuffer = new ArraySegment <Byte>(_buffer, 14 + 125 + 125 + 8 + 10 + _options.SendBufferSize + 4, 2); _pingTimeout = _options.PingTimeout; _pingInterval = TimeSpan.FromMilliseconds(Math.Min(500, _options.PingTimeout.TotalMilliseconds / 2)); }
/// <summary> /// Creates the connection to the B******g Server and performs the protocol handshake. /// </summary> /// <returns>Nothing (Task used for async/await)</returns> public async Task ConnectAsync(CancellationToken aToken = default(CancellationToken)) { if (_ws != null) { throw new ButtplugHandshakeException(_logger, "Websocket connector is already connected."); } const int bufferSize = 1024 * 8; // 8KiB const int bufferPoolSize = 100 * bufferSize; // 800KiB pool var options = new WebSocketListenerOptions { // set send buffer size (optional but recommended) SendBufferSize = bufferSize, // set buffer manager for buffers re-use (optional but recommended) BufferManager = BufferManager.CreateBufferManager(bufferPoolSize, bufferSize), }; // register RFC6455 protocol implementation (required) options.Standards.RegisterRfc6455(); _wsClient = new WebSocketClient(options); try { _ws = await _wsClient.ConnectAsync(_uri, aToken).ConfigureAwait(false); } catch (Exception e) { throw new ButtplugClientConnectorException(_logger, "Websocket Connection Exception! See Inner Exception", e); } _readTask = new Task(async() => { await RunClientLoop(aToken).ConfigureAwait(false); }, aToken, TaskCreationOptions.LongRunning); _readTask.Start(); }
public MKNClient() { cancellation = new CancellationTokenSource(); var bufferSize = 1024 * 8; // 8KiB var bufferPoolSize = 100 * bufferSize; // 800KiB pool var options = new WebSocketListenerOptions { SubProtocols = new[] { "text" }, PingTimeout = TimeSpan.FromSeconds(5), NegotiationTimeout = TimeSpan.FromSeconds(5), PingMode = PingMode.Manual, ParallelNegotiations = 16, NegotiationQueueCapacity = 256, BufferManager = BufferManager.CreateBufferManager(bufferPoolSize, bufferSize) }; options.Standards.RegisterRfc6455(factory => { factory.MessageExtensions.RegisterDeflateCompression(); }); // configure tcp transport options.Transports.ConfigureTcp(tcp => { tcp.BacklogSize = 100; // max pending connections waiting to be accepted tcp.ReceiveBufferSize = bufferSize; tcp.SendBufferSize = bufferSize; }); // adding the WSS extension //var certificate = new X509Certificate2(File.ReadAllBytes("<PATH-TO-CERTIFICATE>"), "<PASSWORD>"); // options.ConnectionExtensions.RegisterSecureConnection(certificate); client = new WebSocketClient(options); }
internal abstract Task <NetworkConnection> ConnectAsync(Uri address, WebSocketListenerOptions options, CancellationToken cancellation);
public HttpNegotiationQueue(WebSocketFactoryCollection standards, WebSocketConnectionExtensionCollection extensions, WebSocketListenerOptions options) { _options = options; _extensions = extensions; _cancel = new CancellationTokenSource(); _semaphore = new SemaphoreSlim(options.ParallelNegotiations); _sockets = new BufferBlock <Socket>(new DataflowBlockOptions() { BoundedCapacity = options.NegotiationQueueCapacity, CancellationToken = _cancel.Token }); _negotiations = new BufferBlock <WebSocketNegotiationResult>(new DataflowBlockOptions() { BoundedCapacity = options.NegotiationQueueCapacity, CancellationToken = _cancel.Token, }); _cancel.Token.Register(_sockets.Complete); _cancel.Token.Register(_negotiations.Complete); _handShaker = new WebSocketHandshaker(standards, _options); Task.Run((Func <Task>)WorkAsync); }
public override WebSocket CreateWebSocket(Stream stream, WebSocketListenerOptions options, IPEndPoint localEndpoint, IPEndPoint remoteEndpoint, WebSocketHttpRequest httpRequest, WebSocketHttpResponse httpResponse, List <IWebSocketMessageExtensionContext> negotiatedExtensions) { return(new WebSocketRfc6455(stream, options, localEndpoint, remoteEndpoint, httpRequest, httpResponse, negotiatedExtensions)); }
internal abstract Task <Listener> ListenAsync(Uri address, WebSocketListenerOptions options);
//[InlineData("tcp://127.0.0.1:10102/", 30, 1000)] //[InlineData("tcp://127.0.0.1:10103/", 40, 10000)] public async Task EchoServerMassClientsAsync(string address, int timeoutSeconds, int maxClients) { var messages = new string[] { new string('a', 126), new string('a', 127), new string('a', 128), new string('a', ushort.MaxValue - 1), new string('a', ushort.MaxValue), new string('a', ushort.MaxValue + 2) }; var startTime = DateTime.UtcNow; var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds)).Token; var options = new WebSocketListenerOptions { NegotiationQueueCapacity = maxClients, PingTimeout = TimeSpan.FromSeconds(30), Logger = new TestLogger(this.logger) { IsDebugEnabled = System.Diagnostics.Debugger.IsAttached } }; options.Standards.RegisterRfc6455(); options.Transports.ConfigureTcp(tcp => { tcp.IsAsync = true; tcp.NoDelay = false; tcp.BacklogSize = maxClients; tcp.SendTimeout = TimeSpan.FromSeconds(15); tcp.ReceiveTimeout = TimeSpan.FromSeconds(15); }); options.Transports.Add(new NamedPipeTransport()); var listenEndPoints = new[] { new Uri(address) }; var server = new EchoServer(listenEndPoints, options); this.logger.Debug("[TEST] Starting echo server."); await server.StartAsync().ConfigureAwait(false); var messageSender = new MessageSender(listenEndPoints[0], options); this.logger.Debug("[TEST] Connecting clients."); await messageSender.ConnectAsync(maxClients, cancellation).ConfigureAwait(false); this.logger.Debug($"[TEST] {messageSender.ConnectedClients} Client connected."); this.logger.Debug($"[TEST] Sending {maxClients * messages.Length} messages."); var sendTask = messageSender.SendMessagesAsync(messages, cancellation); while (sendTask.IsCompleted == false && cancellation.IsCancellationRequested == false) { await Task.Delay(1000); this.logger.Debug($"[TEST] T:{timeoutSeconds - (DateTime.UtcNow - startTime).TotalSeconds:F0} " + $"Server: r={server.ReceivedMessages}, s={server.SentMessages}, e={server.Errors}. " + $"Clients: r={messageSender.MessagesReceived}, s={messageSender.MessagesSent}, e={messageSender.Errors}."); } var errorMessages = new SortedDictionary <string, int>(StringComparer.OrdinalIgnoreCase); server.PushErrorMessagesTo(errorMessages); messageSender.PushErrorMessagesTo(errorMessages); if (errorMessages.Count > 0) { this.logger.Debug("Errors:"); foreach (var kv in errorMessages) { this.logger.Debug($"[TEST] [x{kv.Value}] {kv.Key}"); } } if (cancellation.IsCancellationRequested) { throw new TimeoutException(); } await sendTask.ConfigureAwait(false); this.logger.Debug("[TEST] Stopping echo server."); await server.StopAsync().ConfigureAwait(false); this.logger.Debug("[TEST] Echo server stopped."); this.logger.Debug("[TEST] Disconnecting clients."); await messageSender.CloseAsync().ConfigureAwait(false); this.logger.Debug("[TEST] Disposing server."); server.Dispose(); this.logger.Debug("[TEST] Waiting for send/receive completion."); }
public WebSocketConnectionRfc6455([NotNull] NetworkConnection networkConnection, bool maskData, [NotNull] WebSocketListenerOptions options) { if (networkConnection == null) { throw new ArgumentNullException(nameof(networkConnection)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } const int HEADER_SEGMENT_SIZE = 16; const int PONG_SEGMENT_SIZE = 128; const int PING_HEADER_SEGMENT_SIZE = 16; const int PING_SEGMENT_SIZE = 128; const int SEND_HEADER_SEGMENT_SIZE = 16; const int CLOSE_SEGMENT_SIZE = 2; this.log = options.Logger; this.writeSemaphore = new SemaphoreSlim(1); this.options = options; this.networkConnection = networkConnection; this.maskData = maskData; var bufferSize = HEADER_SEGMENT_SIZE + PING_HEADER_SEGMENT_SIZE + PONG_SEGMENT_SIZE + PING_HEADER_SEGMENT_SIZE + PING_SEGMENT_SIZE + PING_HEADER_SEGMENT_SIZE + PONG_SEGMENT_SIZE + PING_HEADER_SEGMENT_SIZE + PING_SEGMENT_SIZE + CLOSE_SEGMENT_SIZE; var smallBuffer = this.options.BufferManager.TakeBuffer(bufferSize); this.headerBuffer = new ArraySegment <byte>(smallBuffer, 0, HEADER_SEGMENT_SIZE); this.outPongBuffer = this.headerBuffer.NextSegment(PING_HEADER_SEGMENT_SIZE).NextSegment(PONG_SEGMENT_SIZE); this.outPingBuffer = this.outPongBuffer.NextSegment(PING_HEADER_SEGMENT_SIZE).NextSegment(PING_SEGMENT_SIZE); this.inPongBuffer = this.outPingBuffer.NextSegment(PING_HEADER_SEGMENT_SIZE).NextSegment(PONG_SEGMENT_SIZE); this.inPingBuffer = this.inPongBuffer.NextSegment(PING_HEADER_SEGMENT_SIZE).NextSegment(PING_SEGMENT_SIZE); this.closeBuffer = this.inPingBuffer.NextSegment(CLOSE_SEGMENT_SIZE); var sendBuffer = this.options.BufferManager.TakeBuffer(this.options.SendBufferSize); this.SendBuffer = new ArraySegment <byte>(sendBuffer, SEND_HEADER_SEGMENT_SIZE, sendBuffer.Length - SEND_HEADER_SEGMENT_SIZE); switch (options.PingMode) { case PingMode.BandwidthSaving: this.pingHandler = new BandwidthSavingPing(this); break; case PingMode.LatencyControl: this.pingHandler = new LatencyControlPing(this); break; case PingMode.Manual: this.pingHandler = new ManualPing(this); break; default: throw new InvalidOperationException($"Unknown value '{options.PingMode}' for '{nameof(PingMode)}' enumeration."); } }
/// <summary> /// Creates a new instance of <see cref="VtortolaWebSocketTransport"/> /// given the endpoint to run at. /// </summary> /// <param name="endpoint"></param> /// <param name="perMessageDeflate">A value indicating whether to support permessage-deflate /// compression extension or not.</param> /// <param name="certificate">The <see cref="X509Certificate2"/> to use for this transport.</param> /// <param name="options">The <see cref="WebSocketListenerOptions"/> to use for the created <see cref="WebSocketListener"/>.</param> public VtortolaWebSocketTransport(IPEndPoint endpoint, bool perMessageDeflate, X509Certificate2 certificate = null, WebSocketListenerOptions options = null) : this(endpoint, perMessageDeflate, null, certificate, options) { }
public VtortolaAuthenticatedWebSocketTransport (IPEndPoint endpoint, bool perMessageDeflate, ICookieAuthenticatorFactory authenticatorFactory, WebSocketListenerOptions options) : this(endpoint, perMessageDeflate, authenticatorFactory, null, options) { }
public override WebSocket CreateWebSocket(NetworkConnection networkConnection, WebSocketListenerOptions options, WebSocketHttpRequest httpRequest, WebSocketHttpResponse httpResponse, List <IWebSocketMessageExtensionContext> negotiatedExtensions) { if (networkConnection == null) { throw new ArgumentNullException(nameof(networkConnection)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } if (httpResponse == null) { throw new ArgumentNullException(nameof(httpResponse)); } if (negotiatedExtensions == null) { throw new ArgumentNullException(nameof(negotiatedExtensions)); } return(new WebSocketRfc6455(networkConnection, options, httpRequest, httpResponse, negotiatedExtensions)); }
public WebSocketEventListener(IPEndPoint endpoint, WebSocketListenerOptions options) { _listener = new WebSocketListener(endpoint, options); _listener.Standards.RegisterStandard(new WebSocketFactoryRfc6455(_listener)); }
public VtortolaAuthenticatedWebSocketTransport (IPEndPoint endpoint, bool perMessageDeflate, ICookieAuthenticatorFactory authenticatorFactory, X509Certificate2 certificate = null, WebSocketListenerOptions options = null) : base(endpoint, perMessageDeflate, authenticatorFactory, certificate, options) { }
/// <inheritdoc /> public override Task <Listener> ListenAsync(Uri address, WebSocketListenerOptions options) { return(Task.FromResult((Listener) new NamedPipeListener(this, address, options))); }
/// <inheritdoc /> internal override async Task <NetworkConnection> ConnectAsync(Uri address, WebSocketListenerOptions options, CancellationToken cancellation) { if (address == null) { throw new ArgumentNullException(nameof(address)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } var remoteEndPoint = this.GetRemoteEndPoint(address); var protocolType = this.GetProtocolType(address, remoteEndPoint); // prepare socket var socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Stream, protocolType); this.SetupClientSocket(socket, remoteEndPoint); try { // prepare connection var socketConnectedCondition = new AsyncConditionSource { ContinueOnCapturedContext = false }; var socketAsyncEventArgs = new SocketAsyncEventArgs { RemoteEndPoint = remoteEndPoint, UserToken = socketConnectedCondition }; // connect socketAsyncEventArgs.Completed += (_, e) => ((AsyncConditionSource)e.UserToken).Set(); // interrupt connection when cancellation token is set var connectInterruptRegistration = cancellation.CanBeCanceled ? cancellation.Register(s => ((AsyncConditionSource)s).Interrupt(new OperationCanceledException()), socketConnectedCondition) : default(CancellationTokenRegistration); using (connectInterruptRegistration) { if (socket.ConnectAsync(socketAsyncEventArgs) == false) { socketConnectedCondition.Set(); } await socketConnectedCondition; } cancellation.ThrowIfCancellationRequested(); // check connection result if (socketAsyncEventArgs.ConnectByNameError != null) { throw socketAsyncEventArgs.ConnectByNameError; } if (socketAsyncEventArgs.SocketError != SocketError.Success) { throw new WebSocketException($"Failed to open socket to '{address}' due error '{socketAsyncEventArgs.SocketError}'.", new SocketException((int)socketAsyncEventArgs.SocketError)); } var localEndPoint = default(EndPoint); try { localEndPoint = socket.LocalEndPoint; } catch { if (UnixSocketTransport.IsUnixEndPoint(remoteEndPoint)) { localEndPoint = remoteEndPoint; } } var connection = new SocketConnection(socket, localEndPoint); socket = null; return(connection); } finally { if (socket != null) { SafeEnd.Dispose(socket, options.Logger); } } }
public override WebSocket CreateWebSocket(Stream stream, WebSocketListenerOptions options, IPEndPoint localEndpoint, IPEndPoint remoteEndpoint, WebSocketHttpRequest webSocketHttpRequest, List<IWebSocketMessageExtensionContext> negotiatedExtensions) { return new WebSocketRfc6455(stream, options, localEndpoint, remoteEndpoint, webSocketHttpRequest, negotiatedExtensions); }
/// <summary> /// Start the API Server /// </summary> public static void Start() { _bufferPoolSize = 100 * _bufferSize; PacketLoader.LoadPackets(); var config = Config.Load(); var clientUpdateService = new UpdateService(); clientUpdateService.Start(); FileSearchService = new FileSearchService(Path.Combine(AppEnvironment.DataPath, "fileIndex.db")); FileSearchService.Start(); CronJobService = new CronJobService(Path.Combine(AppEnvironment.DataPath, "jobs.json"), Path.Combine(AppEnvironment.DataPath, "scripts")); CronJobService.ConfigureJobs(); var apiPort = config.TaskServer.TaskServerPort; AllClients = new ConcurrentDictionary <Guid, AuthClient>(); ScreenShareService = new ScreenShareService(); var address = NetworkService.GetAddress(); var webCamPort = config.Webcams.WebcamPort; var screenSharePort = config.ScreenShareService.ScreenSharePort; var listenEndPoints = new Uri[] { new Uri($"ws://{address}:{apiPort}"), new Uri($"ws://{address}:{webCamPort}"), new Uri($"ws://{address}:{screenSharePort}") }; var options = new WebSocketListenerOptions { PingMode = PingMode.LatencyControl, NegotiationTimeout = TimeSpan.FromSeconds(30), PingTimeout = TimeSpan.FromSeconds(5), ParallelNegotiations = 16, NegotiationQueueCapacity = 256, BufferManager = BufferManager.CreateBufferManager(_bufferPoolSize, _bufferSize), Logger = NullLogger.Instance, HttpAuthenticationHandler = async(request, response) => { await Task.Delay(TimeSpan.FromMilliseconds(1)); if (request.Cookies["ConnectionId"] == null) { response.Cookies.Add(new Cookie("ConnectionId", Guid.NewGuid().ToString())); } return(true); } }; options.Transports.ConfigureTcp(tcp => { tcp.BacklogSize = 1000; // max pending connections waiting to be accepted tcp.ReceiveBufferSize = _bufferSize; tcp.SendBufferSize = _bufferSize; tcp.LingerState = new LingerOption(true, 0); tcp.NoDelay = true; tcp.IsAsync = true; tcp.ReceiveTimeout = TimeSpan.FromSeconds(1); tcp.SendTimeout = TimeSpan.FromSeconds(3); }); var server = new WebSocketEventListener(listenEndPoints, options); server.OnConnect += HandleConnect; server.OnDisconnect += HandleDisconnect; server.OnPlainTextMessage += HandlePlainTextMessage; server.OnEncryptedMessage += HandleEncryptedMessage; server.OnError += HandleError; server.Start(); Log("Api Server started at " + address); }
public WebSocketServer(IPEndPoint endpoint, WebSocketListenerOptions options) { this.listener = new WebSocketListener(endpoint, options); this.listener.Standards.RegisterStandard(new WebSocketFactoryRfc6455(this.listener)); }
private static void Main(string[] args) { // configuring logging XmlConfigurator.Configure(); var cancellationTokenSource = new CancellationTokenSource(); Console.CancelKeyPress += (_, __) => cancellationTokenSource.Cancel(); Console.WriteLine("Press CTRL+C to stop client."); Console.WriteLine("Press ESC to gracefully close connection."); var bufferSize = 1024 * 8; // 8KiB var bufferPoolSize = 100 * bufferSize; // 800KiB pool var options = new WebSocketListenerOptions { // set send buffer size (optional but recommended) SendBufferSize = bufferSize, // set buffer manager for buffers re-use (optional but recommended) BufferManager = BufferManager.CreateBufferManager(bufferPoolSize, bufferSize), // set logger, leave default NullLogger if you don't want logging Logger = Log }; // register RFC6455 protocol implementation (required) options.Standards.RegisterRfc6455(); // configure tcp transport (optional) options.Transports.ConfigureTcp(tcp => { tcp.BacklogSize = 100; // max pending connections waiting to be accepted tcp.ReceiveBufferSize = bufferSize; tcp.SendBufferSize = bufferSize; }); var message = "Hello!"; var echoServerUrl = new Uri("ws://echo.websocket.org?encoding=text"); var client = new vtortola.WebSockets.WebSocketClient(options); Log.Warning("Connecting to " + echoServerUrl + "..."); var webSocket = client.ConnectAsync(echoServerUrl, cancellationTokenSource.Token).Result; Log.Warning("Connected to " + echoServerUrl + ". "); while (cancellationTokenSource.IsCancellationRequested == false) { Log.Warning("Sending text: " + message); webSocket.WriteStringAsync(message, cancellationTokenSource.Token).Wait(); var responseText = webSocket.ReadStringAsync(cancellationTokenSource.Token).Result; Log.Warning("Received message:" + responseText); if (Console.KeyAvailable && Console.ReadKey(intercept: true).Key == ConsoleKey.Escape) { break; } Thread.Sleep(400); } Log.Warning("Disconnecting from " + echoServerUrl + "..."); webSocket.CloseAsync().Wait(); Log.Warning("Disconnected from " + echoServerUrl + "."); Log.Warning("Disposing client..."); client.CloseAsync().Wait(); Console.WriteLine("Press any key to exit."); Console.ReadKey(); }
/// <summary> /// Creates a new instance of <see cref="VtortolaWebSocketTransport"/> /// given the endpoint to run at. /// </summary> /// <param name="endpoint"></param> /// <param name="perMessageDeflate">A value indicating whether to support permessage-deflate /// compression extension or not.</param> /// <param name="options">The <see cref="WebSocketListenerOptions"/> to use for the created <see cref="WebSocketListener"/>.</param> public VtortolaWebSocketTransport(IPEndPoint endpoint, bool perMessageDeflate, WebSocketListenerOptions options) : this(endpoint, perMessageDeflate, null, options) { }
protected SocketListener(SocketTransport transport, EndPoint[] endPointsToListen, ProtocolType protocolType, WebSocketListenerOptions options) { if (endPointsToListen == null) { throw new ArgumentNullException(nameof(endPointsToListen)); } if (endPointsToListen.Any(p => p == null)) { throw new ArgumentException("Null objects passed in array.", nameof(endPointsToListen)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } this.log = options.Logger; this.sockets = EmptySockets; this.localEndPoints = EmptyEndPoints; var boundSockets = new Socket[endPointsToListen.Length]; var boundEndpoints = new EndPoint[endPointsToListen.Length]; var activeEvents = new SocketAsyncEventArgs[endPointsToListen.Length]; var availableEvents = new SocketAsyncEventArgs[endPointsToListen.Length]; try { for (var i = 0; i < boundSockets.Length; i++) { boundSockets[i] = new Socket(endPointsToListen[i].AddressFamily, SocketType.Stream, protocolType); boundSockets[i].Bind(endPointsToListen[i]); boundSockets[i].Listen(transport.BacklogSize); boundEndpoints[i] = boundSockets[i].LocalEndPoint; activeEvents[i] = CreateSocketAsyncEvent(); availableEvents[i] = CreateSocketAsyncEvent(); } this.sockets = boundSockets; this.localEndPoints = boundEndpoints; this.acceptTasks = new Task <Socket> [boundSockets.Length]; this.availableAcceptEvents = activeEvents; this.activeAcceptEvents = availableEvents; boundSockets = null; } finally { if (boundSockets != null) { foreach (var socket in boundSockets) { SafeEnd.Dispose(socket); } } } }
/// <summary> /// Creates a new instance of <see cref="VtortolaWebSocketTransport"/> /// given the endpoint to run at. /// </summary> /// <param name="endpoint"></param> /// <param name="perMessageDeflate">A value indicating whether to support permessage-deflate /// compression extension or not.</param> /// <param name="authenticatorFactory"></param> /// <param name="certificate"></param> /// <param name="options"></param> protected VtortolaWebSocketTransport (IPEndPoint endpoint, bool perMessageDeflate, ICookieAuthenticatorFactory authenticatorFactory = null, X509Certificate2 certificate = null, WebSocketListenerOptions options = null) : base(authenticatorFactory) { mEndpoint = endpoint; mPerMessageDeflate = perMessageDeflate; mCertificate = certificate; mOptions = options; }
private static void Main(string[] args) { // configuring logging XmlConfigurator.Configure(); Log.Warning("Starting Echo Server"); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; // opening TLS certificate //X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); //store.Open(OpenFlags.ReadOnly); //store.Certificates.Count.ToString(); //var certificate = store.Certificates[1]; //store.Close(); var cancellation = new CancellationTokenSource(); Console.CancelKeyPress += (_, __) => cancellation.Cancel(); var bufferSize = 1024 * 8; // 8KiB var bufferPoolSize = 100 * bufferSize; // 800KiB pool var options = new WebSocketListenerOptions { SubProtocols = new[] { "text" }, PingTimeout = TimeSpan.FromSeconds(5), NegotiationTimeout = TimeSpan.FromSeconds(5), ParallelNegotiations = 16, NegotiationQueueCapacity = 256, BufferManager = BufferManager.CreateBufferManager(bufferPoolSize, bufferSize), Logger = Log }; options.Standards.RegisterRfc6455(factory => { factory.MessageExtensions.RegisterDeflateCompression(); }); // configure tcp transport options.Transports.ConfigureTcp(tcp => { tcp.BacklogSize = 100; // max pending connections waiting to be accepted tcp.ReceiveBufferSize = bufferSize; tcp.SendBufferSize = bufferSize; }); // register unix socket transport options.Transports.RegisterUnixSockets(unix => { unix.ReceiveBufferSize = bufferSize; unix.SendBufferSize = bufferSize; }); // adding the WSS extension //options.ConnectionExtensions.RegisterSecureConnection(certificate); var listenEndPoints = new Uri[] { new Uri("unix:/tmp/wsocket"), new Uri("ws://localhost") // will listen both IPv4 and IPv6 }; // starting the server var server = new WebSocketListener(listenEndPoints, options); server.StartAsync().Wait(); Log.Warning("Echo Server listening: " + string.Join(", ", Array.ConvertAll(listenEndPoints, e => e.ToString())) + "."); Log.Warning("You can test echo server at http://www.websocket.org/echo.html."); var acceptingTask = AcceptWebSocketsAsync(server, cancellation.Token); Log.Warning("Press any key to stop."); Console.ReadKey(true); Log.Warning("Server stopping."); cancellation.Cancel(); server.StopAsync().Wait(); acceptingTask.Wait(); }
public void Benchmark() { var serializer = new JsonCommonSerializer(); var port = new Random().Next(30000, 60000); var options = new WebSocketListenerOptions(); options.SubProtocols = new[] { "SignalR" }; var listener = new WebSocketListener(new IPEndPoint(IPAddress.Loopback, port), options); var rfc6455 = new vtortola.WebSockets.Rfc6455.WebSocketFactoryRfc6455(listener); listener.Standards.RegisterStandard(rfc6455); var serverTransport = listener.GenerateTransportSource(); var serverRouter = new DefaultMessageRouter(serverTransport, serializer); serverRouter.AddService <ISumService>(new SumService()); listener.Start(); var client = new ClientWebSocket(); client.Options.AddSubProtocol("SignalR"); var clientTransport = client.GenerateTransportSource(); var clientRouter = new DefaultMessageRouter(clientTransport, serializer); var proxy = clientRouter.AddInterface <ISumService>(); client.ConnectAsync(new Uri("ws://localhost:" + port + "/"), CancellationToken.None).Wait(); const int randCnt = 100; var rand = new Random(42); var randoms = new int[randCnt]; for (int i = 0; i < randCnt; i++) { randoms[i] = rand.Next(10000000, 20000000); } var sw = new Stopwatch(); long timeFromClient = 0, timeToClient = 0; const int cnt = 1000; for (int j = 0; j < cnt; j++) { sw.Start(); var sum = proxy.Sum(randoms).Result; sw.Stop(); Assert.Equal(randoms.Sum(), sum); for (int i = 0; i < randCnt; i++) { randoms[i] = rand.Next(10000000, 20000000); } var times = proxy.TimeDiff(Stopwatch.GetTimestamp()).Result; timeFromClient += times.Item1; timeToClient += Stopwatch.GetTimestamp() - times.Item2; } _testOutputHelper.WriteLine("Completed {0} sum passes in {1}ms", cnt, sw.ElapsedMilliseconds); _testOutputHelper.WriteLine("Client to server latency: {0}us", timeFromClient / cnt / 10); _testOutputHelper.WriteLine("Server to client latency: {0}us", timeToClient / cnt / 10); sw.Reset(); var tree = new SumServiceTree(); SumServiceTree.FillTree(tree, rand, 2); _testOutputHelper.WriteLine("Starting large message transfer."); sw.Start(); var result = proxy.Increment(tree).Result; sw.Stop(); Assert.Equal(tree.Leaf + 1, result.Leaf); _testOutputHelper.WriteLine("Completed large transfer in {0}ms", sw.Elapsed.TotalMilliseconds); clientRouter.Dispose(); clientTransport.Dispose(); client.Dispose(); serverRouter.Dispose(); serverTransport.Dispose(); listener.Dispose(); }
/// <inheritdoc /> public UnixSocketListener(UnixSocketTransport transport, EndPoint[] endPointsToListen, WebSocketListenerOptions options) : base(transport, endPointsToListen, ProtocolType.Unspecified, options) { this.transport = transport; }