public async Task PublishAsync(string topic, byte[] payload, QualityOfService qos = QualityOfService.AtMostOnce, bool retain = false) { TaskCompletionSource <object> future = new TaskCompletionSource <object>(); PublishPacket packet = new PublishPacket(qos, false, retain); packet.TopicName = topic; packet.PacketId = PacketIdProvider.NewPacketId(); packet.Payload = Unpooled.WrappedBuffer(payload); packet.Retain(); WriteResult result = await sendAndFlushAsync(packet); if (!result.Success) { packet.Release();//needed? future.SetException(result.Exception); } else if (qos == QualityOfService.AtLeastOnce) { packet.Release(); //needed? future.SetResult(null); //We don't get an ACK for QOS 0 } else { PendingPublish pendingPublish = new PendingPublish(packet, future);//return after PubAct(QoS=1)/PubRel(QoS=2) received. pendingPublishes.TryAdd(packet.PacketId, pendingPublish); pendingPublish.RetransmitPublish(eventLoopGroup.GetNext(), sendAndFlushAsync); } await future.Task; }
public override void ChannelActive(IChannelHandlerContext ctx) { IEventLoop loop = _group.GetNext(); if (_sameEventLoop) { Deregister(ctx, loop); } else { loop.Execute(() => Deregister(ctx, loop)); } }
public override void ChannelRead(IChannelHandlerContext ctx, object msg) { var child = (IChannel)msg; child.Pipeline.AddLast(childHandler); if (childOptionsSetupFunc != null) { if (!childOptionsSetupFunc(child.Configuration)) { Logger.Warning("Not all configuration options could be set."); } } // todo: async/await instead? try { childGroup.GetNext() .RegisterAsync(child) .ContinueWith(future => ForceClose(child, future.Exception), TaskContinuationOptions.NotOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously); } catch (Exception ex) { ForceClose(child, ex); } }
public async Task TestReleaseAfterClosePool() { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel<LocalServerChannel>() .ChildHandler( new ActionChannelInitializer<LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var pool = new FixedChannelPool(cb, new TestChannelPoolHandler(), 2); IChannel channel = await pool.AcquireAsync(); pool.Close(); await _group.GetNext().SubmitAsync(() => TaskUtil.Completed); var e = await Assert.ThrowsAsync<InvalidOperationException>(async () => await pool.ReleaseAsync(channel)); Assert.Same(FixedChannelPool.PoolClosedOnReleaseException, e); // Since the pool is closed, the Channel should have been closed as well. await channel.CloseCompletion; Assert.False(channel.IsOpen, "Unexpected open channel"); await sc.CloseAsync(); pool.Close(); }
Func <IPAddress, int, Task <IChannel> > CreateWebSocketChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { return(async(address, port) => { IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); var websocketUri = new Uri(WebSocketConstants.Scheme + iotHubConnectionString.HostName + ":" + WebSocketConstants.SecurePort + WebSocketConstants.UriSuffix); var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); // Check if we're configured to use a proxy server IWebProxy webProxy = WebRequest.DefaultWebProxy; Uri proxyAddress = webProxy?.GetProxy(websocketUri); if (!websocketUri.Equals(proxyAddress)) { // Configure proxy server websocket.Options.Proxy = webProxy; } if (settings.ClientCertificate != null) { websocket.Options.ClientCertificates.Add(settings.ClientCertificate); } else { websocket.Options.UseDefaultCredentials = true; } using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1))) { await websocket.ConnectAsync(websocketUri, cancellationTokenSource.Token); } var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, false) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this.OnConnected, this.OnMessageReceived, this.OnError, iotHubConnectionString, settings)); await eventLoopGroup.GetNext().RegisterAsync(clientChannel); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return clientChannel; }); }
/// <summary> /// If running in a context of an existing <see cref="IEventLoop"/>, this <see cref="IEventLoop"/> is returned. /// Otherwise, <see cref="IEventLoop"/> is retrieved from underlying <see cref="IEventLoopGroup"/>. /// </summary> public override IEventExecutor GetNext() { if (ExecutionEnvironment.TryGetCurrentExecutor(out var executor)) { if (executor is IEventLoop loop && loop.Parent == _innerGroup) { return(loop); } } return(_innerGroup.GetNext()); }
public async Task TestBindDeadLock() { Bootstrap bootstrapA = new Bootstrap(); bootstrapA.Group(_groupA); bootstrapA.Channel <LocalChannel>(); bootstrapA.Handler(_dummyHandler); Bootstrap bootstrapB = new Bootstrap(); bootstrapB.Group(_groupB); bootstrapB.Channel <LocalChannel>(); bootstrapB.Handler(_dummyHandler); var bindFutures = new List <Task <int> >(); // Try to bind from each other. for (int i = 0; i < 1024; i++) { bindFutures.Add(_groupA.GetNext().SubmitAsync(() => { bootstrapB.BindAsync(LocalAddress.Any); return(i); })); bindFutures.Add(_groupB.GetNext().SubmitAsync(() => { bootstrapA.BindAsync(LocalAddress.Any); return(i); })); } for (int i = 0; i < bindFutures.Count; i++) { Task <int> result = bindFutures[i]; await result; } }
Func <IPAddress, int, Task <IChannel> > CreateWebSocketChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings) { return(async(address, port) => { string additionalQueryParams = ""; #if WINDOWS_UWP || NETSTANDARD1_3 // UWP and NETSTANDARD1_3 implementation doesn't set client certs, so we want to tell the IoT Hub to not ask for them additionalQueryParams = "?iothub-no-client-cert=true"; #endif IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); var websocketUri = new Uri(WebSocketConstants.Scheme + iotHubConnectionString.HostName + ":" + WebSocketConstants.SecurePort + WebSocketConstants.UriSuffix + additionalQueryParams); var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); #if !WINDOWS_UWP // UWP does not support proxies // Check if we're configured to use a proxy server IWebProxy webProxy = WebRequest.DefaultWebProxy; Uri proxyAddress = null; #if !NETSTANDARD1_3 proxyAddress = webProxy?.GetProxy(websocketUri); #endif if (!websocketUri.Equals(proxyAddress)) { // Configure proxy server websocket.Options.Proxy = webProxy; } #endif if (settings.ClientCertificate != null) { websocket.Options.ClientCertificates.Add(settings.ClientCertificate); } #if !WINDOWS_UWP && !NETSTANDARD1_3 // UseDefaultCredentials is not in UWP and NetStandard else { websocket.Options.UseDefaultCredentials = true; } #endif using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1))) { await websocket.ConnectAsync(websocketUri, cancellationTokenSource.Token); } #if WINDOWS_UWP PlatformProvider.Platform = new UWPPlatform(); #endif var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, false) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings)); await eventLoopGroup.GetNext().RegisterAsync(clientChannel); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return clientChannel; }); }
Func <IPAddress[], int, Task <IChannel> > CreateWebSocketChannelFactory(IotHubConnectionString iotHubConnectionString, MqttTransportSettings settings, ProductInfo productInfo) { return(async(address, port) => { string additionalQueryParams = ""; #if NETSTANDARD1_3 // NETSTANDARD1_3 implementation doesn't set client certs, so we want to tell the IoT Hub to not ask for them additionalQueryParams = "?iothub-no-client-cert=true"; #endif IEventLoopGroup eventLoopGroup = EventLoopGroupPool.TakeOrAdd(this.eventLoopGroupKey); var websocketUri = new Uri(WebSocketConstants.Scheme + iotHubConnectionString.HostName + ":" + WebSocketConstants.SecurePort + WebSocketConstants.UriSuffix + additionalQueryParams); var websocket = new ClientWebSocket(); websocket.Options.AddSubProtocol(WebSocketConstants.SubProtocols.Mqtt); // Check if we're configured to use a proxy server IWebProxy webProxy = settings.Proxy; try { if (webProxy != DefaultWebProxySettings.Instance) { // Configure proxy server websocket.Options.Proxy = webProxy; if (Logging.IsEnabled) { Logging.Info(this, $"{nameof(CreateWebSocketChannelFactory)} Setting ClientWebSocket.Options.Proxy"); } } } catch (PlatformNotSupportedException) { // .NET Core 2.0 doesn't support proxy. Ignore this setting. if (Logging.IsEnabled) { Logging.Error(this, $"{nameof(CreateWebSocketChannelFactory)} PlatformNotSupportedException thrown as .NET Core 2.0 doesn't support proxy"); } } if (settings.ClientCertificate != null) { websocket.Options.ClientCertificates.Add(settings.ClientCertificate); } using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1))) { await websocket.ConnectAsync(websocketUri, cancellationTokenSource.Token).ConfigureAwait(false); } var clientChannel = new ClientWebSocketChannel(null, websocket); clientChannel .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default) .Option(ChannelOption.AutoRead, false) .Option(ChannelOption.RcvbufAllocator, new AdaptiveRecvByteBufAllocator()) .Option(ChannelOption.MessageSizeEstimator, DefaultMessageSizeEstimator.Default) .Pipeline.AddLast( MqttEncoder.Instance, new MqttDecoder(false, MaxMessageSize), this.mqttIotHubAdapterFactory.Create(this, iotHubConnectionString, settings, productInfo)); await eventLoopGroup.GetNext().RegisterAsync(clientChannel).ConfigureAwait(false); this.ScheduleCleanup(() => { EventLoopGroupPool.Release(this.eventLoopGroupKey); return TaskConstants.Completed; }); return clientChannel; }); }