|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
import time
|
|
|
|
import psutil
|
|
|
|
import random
|
|
|
|
from Utils.Logger import logger
|
|
|
|
|
|
|
|
|
|
|
|
def getAvailablePort(rangeStart: int = 1024, rangeEnd: int = 65535, msWait: int = 10) -> int: # found a available port
|
|
|
|
if rangeStart > rangeEnd or rangeStart < 1 or rangeEnd > 65535: # port range check
|
|
|
|
raise RuntimeError('Invalid port range')
|
|
|
|
while True:
|
|
|
|
port = random.randint(rangeStart, rangeEnd) # choose randomly
|
|
|
|
if isVacantPort(port):
|
|
|
|
logger.debug('Found new available port -> %i' % port)
|
|
|
|
return port
|
|
|
|
time.sleep(msWait / 1000) # ms -> s (default 10ms)
|
|
|
|
|
|
|
|
|
|
|
|
def isVacantPort(port: int) -> bool: # whether the port is occupied
|
|
|
|
for connection in networkStatus(): # scan every connections
|
|
|
|
if connection['local']['port'] == port: # port occupied (ipv4-tcp / ipv4-udp / ipv6-tcp / ipv6-udp)
|
|
|
|
logger.debug('Check port %i -> occupied' % port)
|
|
|
|
return False
|
|
|
|
logger.debug('Check port %i -> available' % port) # vacant port
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def networkStatus() -> list: # get all network connections
|
|
|
|
result = []
|
|
|
|
for connection in psutil.net_connections():
|
|
|
|
if not connection.family.name.startswith('AF_INET'): # AF_INET / AF_INET6
|
|
|
|
continue
|
|
|
|
if connection.type.name not in ['SOCK_STREAM', 'SOCK_DGRAM']: # TCP / UDP
|
|
|
|
continue
|
|
|
|
result.append({
|
|
|
|
'fd': connection.fd,
|
|
|
|
'family': 'ipv6' if connection.family.name[-1] == '6' else 'ipv4', # ip version
|
|
|
|
'type': 'tcp' if connection.type.name == 'SOCK_STREAM' else 'udp', # tcp or udp
|
|
|
|
'local': { # local bind address
|
|
|
|
'addr': connection.laddr.ip,
|
|
|
|
'port': connection.laddr.port,
|
|
|
|
},
|
|
|
|
'remote': { # remote address
|
|
|
|
'addr': connection.raddr.ip,
|
|
|
|
'port': connection.raddr.port,
|
|
|
|
} if len(connection.raddr) != 0 else None,
|
|
|
|
'status': connection.status,
|
|
|
|
'pid': connection.pid, # process id
|
|
|
|
})
|
|
|
|
logger.debug('Network status -> found %i connections' % len(result))
|
|
|
|
return result
|