class IO::Endpoint::Wrapper

def bind(local_address, protocol: 0, reuse_address: true, reuse_port: nil, linger: nil, bound_timeout: nil, backlog: Socket::SOMAXCONN, **options, &block)

@parameter protocol [Integer] The socket protocol to use.
@parameter linger [Boolean] Wait for data to be sent before closing the socket.
@parameter reuse_address [Boolean] Allow this port to be bound in multiple processes.
@parameter reuse_port [Boolean] Allow this port to be bound in multiple processes.
@parameter local_address [Address] The local address to bind to.
socket = Async::IO::Socket.bind(Async::IO::Address.tcp("0.0.0.0", 9090))
@example
Bind to a local address.
def bind(local_address, protocol: 0, reuse_address: true, reuse_port: nil, linger: nil, bound_timeout: nil, backlog: Socket::SOMAXCONN, **options, &block)
	socket = nil
	
	begin
		socket = ServerSocket.new(local_address.afamily, local_address.socktype, protocol)
		
		if reuse_address
			socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
		end
		
		if reuse_port
			socket.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
		end
		
		if linger
			socket.setsockopt(SOL_SOCKET, SO_LINGER, 1)
		end
		
		# Set the timeout:
		if bound_timeout
			set_timeout(socket, bound_timeout)
		end
		
		socket.bind(local_address.to_sockaddr)
		
		if backlog
			begin
				# Generally speaking, bind/listen is a common pattern, but it's not applicable to all socket types. We ignore the error if it's not supported as the alternative is exposing this upstream, which seems less desirable than handling it here. In other words, `bind` in this context means "prepare it to accept connections", whatever that means for the given socket type.
				socket.listen(backlog)
			rescue Errno::EOPNOTSUPP
				# Ignore.
			end
		end
	rescue
		socket&.close
		raise
	end
	
	return socket unless block_given?
	
	async do
		begin
			yield socket
		ensure
			socket.close
		end
	end
end