Files
clever-show/lib/network.py
2020-11-25 02:31:59 +03:00

89 lines
3.1 KiB
Python

import socket
import logging
import platform
def str_peername(peername):
if peername is None:
return "None"
return f"{peername[0]}:{peername[1]}"
def get_ip_address(): # dodo async
"""
Returns the IP address of current computer or `localhost` if no network connection present.
Returns:
string: IP address of current computer or `localhost` if no network connection present
"""
ip_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # TODO IPv6
try:
ip_socket.connect(("8.8.8.8", 80))
ip = ip_socket.getsockname()[0]
except OSError as e:
logging.warning(f"No network connection detected, using localhost: {e}")
ip = "localhost"
finally:
ip_socket.close()
return ip
def get_ntp_time(ntp_host, ntp_port):
"""
Gets and returns time from specified host and port of NTP server.
Args:
ntp_host (string): hostname or address of the NTP server.
ntp_port (int): port of the NTP server.
Returns:
int: Current time recieved from the NTP server
"""
NTP_DELTA = 2208988800 # 1970-01-01 00:00:00
NTP_QUERY = b'\x1b' + bytes(47)
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as ntp_socket:
ntp_socket.sendto(NTP_QUERY, (ntp_host, ntp_port))
msg, _ = ntp_socket.recvfrom(1024)
return int.from_bytes(msg[-8:], 'big') / 2 ** 32 - NTP_DELTA
def set_keepalive(sock, after_idle_sec=1, interval_sec=3, max_fails=5):
"""
Sets `keepalive` parameters of given socket.
Args:
sock (socket): Socket which parameters will be changed.
after_idle_sec (int, optional): Start sending keepalive packets after this amount of seconds. Defaults to 1.
interval_sec (int, optional): Interval of keepalive packets in seconds. Defaults to 3.
max_fails (int, optional): Count of fails leading to socket disconnect. Defaults to 5.
Raises:
NotImplementedError: for unknown platform.
"""
current_platform = platform.system() # could be empty
if current_platform == "Linux":
return _set_keepalive_linux(sock, after_idle_sec, interval_sec, max_fails)
if current_platform == "Windows":
return _set_keepalive_windows(sock, after_idle_sec, interval_sec)
if current_platform == "Darwin":
return _set_keepalive_osx(sock, interval_sec)
raise NotImplementedError
def _set_keepalive_linux(sock, after_idle_sec, interval_sec, max_fails):
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)
def _set_keepalive_windows(sock, after_idle_sec, interval_sec):
sock.ioctl(socket.SIO_KEEPALIVE_VALS, (1, after_idle_sec * 1000, interval_sec * 1000))
def _set_keepalive_osx(sock, interval_sec):
TCP_KEEPALIVE = 0x10
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.setsockopt(socket.IPPROTO_TCP, TCP_KEEPALIVE, interval_sec)