private async Task StartListeningAsync(UdpConnection connection) { try { var transportTask = connection.StartAsync(); await transportTask; connection.Dispose(); } catch (Exception ex) { _logger.LogCritical(ex, $"Unexpected exception in {nameof(UdpTransport)}.{nameof(StartListeningAsync)}.", null); } }
public Task BindAsync() { List <UdpConnection> connections = new List <UdpConnection>(); IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, _udpConfiguration.ReceivePort); for (var schedulerIndex = 0; schedulerIndex < _numSchedulers; schedulerIndex++) { try { Socket listenSocket = new Socket(endPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); Extensions.DisableHandleInheritance(listenSocket); listenSocket.ReceiveBufferSize = _udpConfiguration.ReceiveBufferSize; //listenSocket.SendBufferSize = _udpConfiguration.SendBufferSize; listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); listenSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true); // Kestrel expects IPv6Any to bind to both IPv6 and IPv4 if (endPoint.Address == IPAddress.IPv6Any) { listenSocket.DualMode = true; } try { listenSocket.Bind(endPoint); } catch (SocketException e) when(e.SocketErrorCode == SocketError.AddressAlreadyInUse) { ThrowSocketAlreadyInUse(e); } // If requested port was "0", replace with assigned dynamic port. if (endPoint.Port == 0) { endPoint = (IPEndPoint)listenSocket.LocalEndPoint; } var connection = new UdpConnection(listenSocket, _memoryPool, _schedulers[schedulerIndex], _udpConfiguration, _logger, _handlerMapper); connections.Add(connection); // REVIEW: This task should be tracked by the server for graceful shutdown // Today it's handled specifically for http but not for arbitrary middleware _ = StartListeningAsync(connection); } catch (SocketException ex) when(!_unbinding) { _logger.LogError(ex); throw; } } _logger.LogInformation($"Started listening to {endPoint.ToString()} with {_numSchedulers.ToString()} listeners.", null); _connections = connections; return(Task.CompletedTask); }