1# Copyright 2016 - The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import socket 16 17 18def get_available_host_port(): 19 """Finds a semi-random available port. 20 21 A race condition is still possible after the port number is returned, if 22 another process happens to bind it. 23 24 Returns: 25 A port number that is unused on both TCP and UDP. 26 """ 27 # On the 2.6 kernel, calling _try_bind() on UDP socket returns the 28 # same port over and over. So always try TCP first. 29 while True: 30 # Ask the OS for an unused port. 31 port = _try_bind(0, socket.SOCK_STREAM, socket.IPPROTO_TCP) 32 # Check if this port is unused on the other protocol. 33 if port and _try_bind(port, socket.SOCK_DGRAM, socket.IPPROTO_UDP): 34 return port 35 36 37def is_port_available(port): 38 """Checks if a given port number is available on the system. 39 40 Args: 41 port: An integer which is the port number to check. 42 43 Returns: 44 True if the port is available; False otherwise. 45 """ 46 return (_try_bind(port, socket.SOCK_STREAM, socket.IPPROTO_TCP) and 47 _try_bind(port, socket.SOCK_DGRAM, socket.IPPROTO_UDP)) 48 49 50def _try_bind(port, socket_type, socket_proto): 51 s = socket.socket(socket.AF_INET, socket_type, socket_proto) 52 try: 53 try: 54 s.bind(('', port)) 55 # The result of getsockname() is protocol dependent, but for both 56 # IPv4 and IPv6 the second field is a port number. 57 return s.getsockname()[1] 58 except socket.error: 59 return None 60 finally: 61 s.close() 62