summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Henry <[email protected]>2021-03-07 21:11:21 -0800
committerJoseph Henry <[email protected]>2021-03-07 21:11:21 -0800
commitdd6cf48d611471745b3fc5b9139c0a0dda0f5a02 (patch)
tree903e5a263bc0290d4f65163ec97d7317ff0355f7
parente1d0f92d617cfe551a83ec02832246c18449a095 (diff)
Run Python language bindings and example code through a linter and formatter1.3.4
-rw-r--r--examples/python/example.py292
-rw-r--r--src/bindings/python/sockets.py717
2 files changed, 534 insertions, 475 deletions
diff --git a/examples/python/example.py b/examples/python/example.py
index e00ab35..ccecf3d 100644
--- a/examples/python/example.py
+++ b/examples/python/example.py
@@ -1,159 +1,157 @@
-import time, sys
+'''Example low-level socket usage'''
-import libzt
-
-# Where identity files are stored
-keyPath = "."
-
-# Network to join
-networkId = 0
-
-# Port used by ZeroTier to send encpryted UDP traffic
-# NOTE: Should be different from other instances of ZeroTier
-# running on the same machine
-ztServicePort = 9997
+import time
+import sys
-remoteIP = None
-
-# A port your app logic may use
-serverPort = 8080
-
-# Flags to keep state
-is_joined = False
-is_online = False
-mode = None
+import libzt
def print_usage():
- print("\nUsage: <server|client> <id_path> <nwid> <ztServicePort> <remoteIP> <serverPort>\n")
- print(" Ex: python3 example.py server . 0123456789abcdef 9994 8080")
- print(" Ex: python3 example.py client . 0123456789abcdef 9994 192.168.22.1 8080\n")
- if (len(sys.argv) < 6):
- print('Too few arguments')
- if (len(sys.argv) > 7):
- print('Too many arguments')
- exit(0)
-#
-if (len(sys.argv) < 6 or len(sys.argv) > 7):
- print_usage()
-
-if (sys.argv[1] == 'server' and len(sys.argv) == 6):
- mode = sys.argv[1]
- keyPath = sys.argv[2]
- networkId = int(sys.argv[3],16)
- ztServicePort = int(sys.argv[4])
- serverPort = int(sys.argv[5])
-
-if (sys.argv[1] == 'client' and len(sys.argv) == 7):
- mode = sys.argv[1]
- keyPath = sys.argv[2]
- networkId = int(sys.argv[3],16)
- ztServicePort = int(sys.argv[4])
- remoteIP = sys.argv[5]
- serverPort = int(sys.argv[6])
-
-if (mode is None):
- print_usage()
-
-print('mode = ', mode)
-print('path = ', keyPath)
-print('networkId = ', networkId)
-print('ztServicePort = ', ztServicePort)
-print('remoteIP = ', remoteIP)
-print('serverPort = ', serverPort)
-
-
+ '''print help'''
+ print(
+ "\nUsage: <server|client> <id_path> <nwid> <zt_service_port> <remote_ip> <remote_port>\n"
+ )
+ print("Ex: python3 demo.py server . 0123456789abcdef 9994 8080")
+ print("Ex: python3 demo.py client . 0123456789abcdef 9994 192.168.22.1 8080\n")
+ if len(sys.argv) < 6:
+ print("Too few arguments")
+ if len(sys.argv) > 7:
+ print("Too many arguments")
+ sys.exit(0)
+
+
+is_joined = False # Flags to keep state
+is_online = False # Flags to keep state
#
# Event handler
#
class MyEventCallbackClass(libzt.EventCallbackClass):
- def on_zerotier_event(self, msg):
- global is_online
- global is_joined
- print("eventCode=", msg.eventCode)
- if (msg.eventCode == libzt.ZTS_EVENT_NODE_ONLINE):
- print("ZTS_EVENT_NODE_ONLINE")
- print("nodeId="+hex(msg.node.address))
- # The node is now online, you can join/leave networks
- is_online = True
- if (msg.eventCode == libzt.ZTS_EVENT_NODE_OFFLINE):
- print("ZTS_EVENT_NODE_OFFLINE")
- if (msg.eventCode == libzt.ZTS_EVENT_NETWORK_READY_IP4):
- print("ZTS_EVENT_NETWORK_READY_IP4")
- is_joined = True
- # The node has successfully joined a network and has an address
- # you can perform network calls now
- if (msg.eventCode == libzt.ZTS_EVENT_PEER_DIRECT):
- print("ZTS_EVENT_PEER_DIRECT")
- if (msg.eventCode == libzt.ZTS_EVENT_PEER_RELAY):
- print("ZTS_EVENT_PEER_RELAY")
-
+ def on_zerotier_event(self, msg):
+ global is_online
+ global is_joined
+ print("eventCode=", msg.eventCode)
+ if msg.eventCode == libzt.ZTS_EVENT_NODE_ONLINE:
+ print("ZTS_EVENT_NODE_ONLINE")
+ print("nodeId=" + hex(msg.node.address))
+ # The node is now online, you can join/leave networks
+ is_online = True
+ if msg.eventCode == libzt.ZTS_EVENT_NODE_OFFLINE:
+ print("ZTS_EVENT_NODE_OFFLINE")
+ if msg.eventCode == libzt.ZTS_EVENT_NETWORK_READY_IP4:
+ print("ZTS_EVENT_NETWORK_READY_IP4")
+ is_joined = True
+ # The node has successfully joined a network and has an address
+ # you can perform network calls now
+ if msg.eventCode == libzt.ZTS_EVENT_PEER_DIRECT:
+ print("ZTS_EVENT_PEER_DIRECT")
+ if msg.eventCode == libzt.ZTS_EVENT_PEER_RELAY:
+ print("ZTS_EVENT_PEER_RELAY")
-
-#
-# Example start and join logic
#
-print("Starting ZeroTier...");
-eventCallback = MyEventCallbackClass()
-libzt.start(keyPath, eventCallback, ztServicePort)
-print("Waiting for node to come online...")
-while (not is_online):
- time.sleep(1)
-print("Joining network:", hex(networkId));
-libzt.join(networkId)
-while (not is_joined):
- time.sleep(1) # You can ping this app at this point
-print('Joined network')
-
-
-
+# Main
#
-# Example server
-#
-if (mode == 'server'):
- print("Starting server...")
- serv = libzt.socket(libzt.ZTS_AF_INET, libzt.ZTS_SOCK_STREAM, 0)
- try:
- #serv.setblocking(True)
- serv.bind(('::', serverPort))
- serv.listen(5)
- while True:
- conn, addr = serv.accept()
- print('Accepted connection from: ', addr)
- while True:
- print('recv:')
- data = conn.recv(4096)
- if data:
- print('data = ', data)
- #print(type(b'what'))
- #exit(0)
- if not data: break
- print('send:')
- #bytes(data, 'ascii') + b'\x00'
- n_bytes = conn.send(data) # echo back to the server
- print('sent ' + str(n_bytes) + ' byte(s)')
- conn.close()
- print('client disconnected')
- except Exception as e:
- print(e)
- print('errno=',libzt.errno()) # See include/ZeroTierSockets.h for codes
-
-
-#
-# Example client
-#
-if (mode == 'client'):
- print("Starting client...")
- client = libzt.socket(libzt.ZTS_AF_INET, libzt.ZTS_SOCK_STREAM, 0)
- try:
- print("connecting...")
- client.connect((remoteIP, serverPort))
- print("send:")
- data = 'Hello, world!'
- client.send(data)
- data = client.recv(1024)
- print('Received', repr(data))
- except Exception as e:
- print(e)
- print('errno=',libzt.errno())
-
+def main():
+ global is_online
+ global is_joined
+
+ key_file_path = "." # Where identity files are stored
+ network_id = 0 # Network to join
+ # Port used by ZeroTier to send encpryted UDP traffic
+ # NOTE: Should be different from other instances of ZeroTier
+ # running on the same machine
+ zt_service_port = 9997
+ remote_ip = None # ZeroTier IP of remote node
+ remote_port = 8080 # ZeroTier port your app logic may use
+ mode = None # client|server
+
+ if len(sys.argv) < 6 or len(sys.argv) > 7:
+ print_usage()
+ if sys.argv[1] == "server" and len(sys.argv) == 6:
+ mode = sys.argv[1]
+ key_file_path = sys.argv[2]
+ network_id = int(sys.argv[3], 16)
+ zt_service_port = int(sys.argv[4])
+ remote_port = int(sys.argv[5])
+ if sys.argv[1] == "client" and len(sys.argv) == 7:
+ mode = sys.argv[1]
+ key_file_path = sys.argv[2]
+ network_id = int(sys.argv[3], 16)
+ zt_service_port = int(sys.argv[4])
+ remote_ip = sys.argv[5]
+ remote_port = int(sys.argv[6])
+ if mode is None:
+ print_usage()
+ print("mode = ", mode)
+ print("path = ", key_file_path)
+ print("network_id = ", network_id)
+ print("zt_service_port = ", zt_service_port)
+ print("remote_ip = ", remote_ip)
+ print("remote_port = ", remote_port)
+
+ #
+ # Example start and join logic
+ #
+ print("Starting ZeroTier...")
+ event_callback = MyEventCallbackClass()
+ libzt.start(key_file_path, event_callback, zt_service_port)
+ print("Waiting for node to come online...")
+ while not is_online:
+ time.sleep(1)
+ print("Joining network:", hex(network_id))
+ libzt.join(network_id)
+ while not is_joined:
+ time.sleep(1) # You can ping this app at this point
+ print("Joined network")
+
+ #
+ # Example server
+ #
+ if mode == "server":
+ print("Starting server...")
+ serv = libzt.socket(libzt.ZTS_AF_INET, libzt.ZTS_SOCK_STREAM, 0)
+ try:
+ # serv.setblocking(True)
+ serv.bind(("0.0.0.0", remote_port))
+ serv.listen(5)
+ while True:
+ conn, addr = serv.accept()
+ print("Accepted connection from: ", addr)
+ while True:
+ print("recv:")
+ data = conn.recv(4096)
+ if data:
+ print("data = ", data)
+ # print(type(b'what'))
+ # exit(0)
+ if not data:
+ break
+ print("send:")
+ # bytes(data, 'ascii') + b'\x00'
+ n_bytes = conn.send(data) # echo back to the server
+ print("sent " + str(n_bytes) + " byte(s)")
+ conn.close()
+ print("client disconnected")
+ except Exception as ex:
+ print(ex)
+ print("errno=", libzt.errno()) # See include/ZeroTierSockets.h for codes
+
+ #
+ # Example client
+ #
+ if mode == "client":
+ print("Starting client...")
+ client = libzt.socket(libzt.ZTS_AF_INET, libzt.ZTS_SOCK_STREAM, 0)
+ try:
+ print("connecting...")
+ client.connect((remote_ip, remote_port))
+ print("send:")
+ data = "Hello, world!"
+ client.send(data)
+ data = client.recv(1024)
+ print("Received", repr(data))
+ except Exception as ex:
+ print(ex)
+ print("errno=", libzt.errno())
+
+if __name__ == "__main__":
+ main()
diff --git a/src/bindings/python/sockets.py b/src/bindings/python/sockets.py
index ac510fd..e8d3dc3 100644
--- a/src/bindings/python/sockets.py
+++ b/src/bindings/python/sockets.py
@@ -1,347 +1,408 @@
+"""ZeroTier low-level socket interface"""
+
import libzt
class EventCallbackClass(libzt.PythonDirectorCallbackClass):
- pass
+ """ZeroTier event callback class"""
+ pass
-# Convert libzt error code to exception
def handle_error(err):
- if (err == libzt.ZTS_ERR_SOCKET):
- raise Exception('ZTS_ERR_SOCKET (' + str(err) + ')')
- if (err == libzt.ZTS_ERR_SERVICE):
- raise Exception('ZTS_ERR_SERVICE (' + str(err) + ')')
- if (err == libzt.ZTS_ERR_ARG):
- raise Exception('ZTS_ERR_ARG (' + str(err) + ')')
- # ZTS_ERR_NO_RESULT isn't strictly an error
- #if (err == libzt.ZTS_ERR_NO_RESULT):
- # raise Exception('ZTS_ERR_NO_RESULT (' + err + ')')
- if (err == libzt.ZTS_ERR_GENERAL):
- raise Exception('ZTS_ERR_GENERAL (' + str(err) + ')')
+ """Convert libzt error code to exception"""
+ if err == libzt.ZTS_ERR_SOCKET:
+ raise Exception("ZTS_ERR_SOCKET (" + str(err) + ")")
+ if err == libzt.ZTS_ERR_SERVICE:
+ raise Exception("ZTS_ERR_SERVICE (" + str(err) + ")")
+ if err == libzt.ZTS_ERR_ARG:
+ raise Exception("ZTS_ERR_ARG (" + str(err) + ")")
+ # ZTS_ERR_NO_RESULT isn't strictly an error
+ # if (err == libzt.ZTS_ERR_NO_RESULT):
+ # raise Exception('ZTS_ERR_NO_RESULT (' + err + ')')
+ if err == libzt.ZTS_ERR_GENERAL:
+ raise Exception("ZTS_ERR_GENERAL (" + str(err) + ")")
# This implementation of errno is NOT thread safe
# That is, this value is shared among all lower-level socket calls
# and may change for any reason at any time if you have multiple
# threads making socket calls.
def errno():
- return libzt.cvar.zts_errno
+ """Return errno value of low-level socket layer"""
+ return libzt.cvar.zts_errno
-# Start the ZeroTier service
def start(path, callback, port):
- libzt.zts_start(path, callback, port)
+ """Start the ZeroTier service"""
+ libzt.zts_start(path, callback, port)
-# Stop the ZeroTier service
def stop():
- libzt.zts_stop()
+ """Stop the ZeroTier service"""
+ libzt.zts_stop()
-# [debug] Restarts the ZeroTier service and network stack
def restart():
- libzt.zts_restart()
+ """[debug] Restarts the ZeroTier service and network stack"""
+ libzt.zts_restart()
-# Permenantly shuts down the network stack.
def free():
- libzt.zts_free()
-
-# Join a ZeroTier network
-def join(networkId):
- libzt.zts_join(networkId)
-
-# Leave a ZeroTier network
-def leave(networkId):
- libzt.zts_leave(networkId)
-
-# Orbit a moon
-def zts_orbit(moonWorldId, moonSeed):
- return libzt.zts_orbit(moonWorldId, moonSeed)
-
-# De-orbit a moon
-def zts_deorbit(moonWorldId):
- return libzt.zts_deorbit(moonWorldId)
-
-# Pythonic class that wraps low-level sockets
-class socket():
-
- _fd = -1 # native layer file descriptor
- _family = -1
- _type = -1
- _proto = -1
- _connected = False
- _closed = True
- _bound = False
-
- def __init__(self, sock_family=-1, sock_type=-1, sock_proto=-1, sock_fd=None):
- self._fd = sock_fd
- self._family = sock_family
- self._type = sock_type
- self._family = sock_family
- # Only create native socket if no fd was provided. We may have
- # accepted a connection
- if (sock_fd == None):
- self._fd = libzt.zts_socket(sock_family, sock_type, sock_proto)
-
- def has_dualstack_ipv6():
- return True
-
- @property
- def family(self):
- return _family
-
- @property
- def type(self):
- return _type
-
- @property
- def proto(self):
- return _proto
-
- # Intentionally not supported
- def socketpair(self, family, type, proto):
- raise NotImplementedError("socketpair(): libzt does not support AF_UNIX sockets")
-
- # Convenience function to create a connection to a remote host
- def create_connection(self, remote_address):
- # TODO: implement timeout
- conn = socket(libzt.ZTS_AF_INET, libzt.ZTS_SOCK_STREAM, 0)
- conn.connect(remote_address)
- return conn
-
- # Convenience function to create a listening socket
- def create_server(self, local_address, family=libzt.ZTS_AF_INET, backlog=None):
- # TODO: implement reuse_port
- conn = socket(libzt.ZTS_AF_INET, libzt.ZTS_SOCK_STREAM, 0)
- conn.bind(local_address)
- conn.listen(backlog)
- return conn
-
- def fromfd(self, fd, family, type, proto=0):
- raise NotImplementedError("fromfd(): Not supported. OS File descriptors aren't used in libzt.")
-
- def fromshare(self, data):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def close(self, fd):
- raise NotImplementedError("close(fd): Not supported OS File descriptors aren't used in libzt.")
-
- def getaddrinfo(self, host, port, family=0, type=0, proto=0, flags=0):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getfqdn(self, name):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def gethostbyname(self, hostname):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def gethostbyname_ex(self, hostname):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def gethostname(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def gethostbyaddr(self, ip_address):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getnameinfo(self, sockaddr, flags):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getprotobyname(self, protocolname):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getservbyname(self, servicename, protocolname):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getservbyport(self, port, protocolname):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def ntohl(x):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def ntohs(x):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def htonl(x):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def htons(x):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def inet_aton(ip_string):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def inet_ntoa(packed_ip):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def inet_pton(address_family, ip_string):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def inet_ntop(address_family, packed_ip):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def CMSG_LEN(length):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def CMSG_SPACE(length):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getdefaulttimeout(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def setdefaulttimeout(self, timeout):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def sethostname(self, name):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def if_nameindex(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def if_nametoindex(self, if_name):
- raise NotImplementedError("if_nametoindex(): libzt does not name interfaces.")
-
- def if_indextoname(self, if_index):
- raise NotImplementedError("if_indextoname(): libzt does not name interfaces.")
-
- # Accept connection on the socket
- def accept(self):
- new_conn_fd, addr, port = libzt.zts_py_accept(self._fd)
- if (new_conn_fd < 0):
- handle_error(new_conn_fd)
- return None
- return ztsocket(self._family, self._type, self._proto, new_conn_fd), addr
-
- # Bind the socket to a local interface address
- def bind(self, local_address):
- err = libzt.zts_py_bind(self._fd, self._family, self._type, local_address)
- if (err < 0):
- handle_error(err)
-
- # Close the socket
- def close(self):
- err = libzt.zts_py_close(self._fd)
- if (err < 0):
- handle_error(err)
-
- # Connect the socket to a remote address
- def connect(self, remote_address):
- err = libzt.zts_py_connect(self._fd, self._family, self._type, remote_address)
- if (err < 0):
- handle_error(err)
-
- # Connect to remote host but return low-level result code, and errno on failure
- # This uses a non-thread-safe implementation of errno
- def connect_ex(self, remote_address):
- err = libzt.zts_py_connect(self._fd, self._family, self._type, remote_address)
- if (err < 0):
- return errno()
- return err
-
- def detach(self):
- raise NotImplementedError("detach(): Not supported. OS File descriptors aren't used in libzt.")
-
- def dup(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def fileno(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def get_inheritable(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getpeername(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getsockname(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def getsockopt(self, level, optname, buflen):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- # Get whether this socket is in blocking or non-blocking mode
- def getblocking(self):
- return libzt.zts_py_getblocking(self._fd)
-
- def gettimeout(self):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def ioctl(self, control, option):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- # Put the socket in a listening state (with an optional backlog argument)
- def listen(self, backlog):
- err = libzt.zts_py_listen(self._fd, backlog)
- if (err < 0):
- handle_error(err)
-
- def makefile(mode='r', buffering=None, *, encoding=None, errors=None, newline=None):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- # Read data from the socket
- def recv(self, n_bytes, flags=0):
- err, data = libzt.zts_py_recv(self._fd, n_bytes, flags)
- if (err < 0):
- handle_error(err)
- return None
- return data
-
- def recvfrom(self, bufsize, flags):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def recvmsg(self, bufsize, ancbufsize, flags):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def recvmsg_into(self, buffers, ancbufsize, flags):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def recvfrom_into(self, buffer, nbytes, flags):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def recv_into(self, buffer, nbytes, flags):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- # Write data to the socket
- def send(self, data, flags=0):
- err = libzt.zts_py_send(self._fd, data, len(data), flags)
- if (err < 0):
- handle_error(err)
- return err
-
- def sendall(self, bytes, flags):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def sendto(self, bytes, address):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def sendto(self, bytes, flags, address):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def sendmsg(self, buffers, ancdata, flags, address):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def sendmsg_afalg(self, msg, *, op, iv, assoclen, flags):
- raise NotImplementedError("sendmsg_afalg(): libzt does not support AF_ALG")
-
- def send_fds(self, sock, buffers, fds, flags, address):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def recv_fds(self, sock, bufsize, maxfds, flags):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def sendfile(self, file, offset=0, count=None):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def set_inheritable(self, inheritable):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- # Set whether this socket is in blocking or non-blocking mode
- def setblocking(self, flag):
- libzt.zts_py_setblocking(self._fd, flag)
-
- def settimeout(self, value):
- raise NotImplementedError("libzt does not support this (yet?)")
-
- def setsockopt(self, level, optname, value):
- # TODO: value: buffer
- # TODO: value: int
- # TODO: value: None -> optlen required
- raise NotImplementedError("libzt does not support this (yet?)")
-
- # Shut down one or more aspects (rx/tx) of the socket
- def shutdown(self, how):
- libzt.shutdown(self._fd, how)
+ """Permenantly shuts down the network stack"""
+ libzt.zts_free()
+
+def join(network_id):
+ """Join a ZeroTier network"""
+ libzt.zts_join(network_id)
+
+def leave(network_id):
+ """Leave a ZeroTier network"""
+ libzt.zts_leave(network_id)
+
+def zts_orbit(moon_world_id, moon_seed):
+ """Orbit a moon"""
+ return libzt.zts_orbit(moon_world_id, moon_seed)
+
+def zts_deorbit(moon_world_id):
+ """De-orbit a moon"""
+ return libzt.zts_deorbit(moon_world_id)
+
+
+class socket:
+ """Pythonic class that wraps low-level sockets"""
+ _fd = -1 # native layer file descriptor
+ _family = -1
+ _type = -1
+ _proto = -1
+ _connected = False
+ _closed = True
+ _bound = False
+
+ def __init__(self, sock_family=-1, sock_type=-1, sock_proto=-1, sock_fd=None):
+ self._fd = sock_fd
+ self._family = sock_family
+ self._type = sock_type
+ self._family = sock_family
+ # Only create native socket if no fd was provided. We may have
+ # accepted a connection
+ if sock_fd is None:
+ self._fd = libzt.zts_socket(sock_family, sock_type, sock_proto)
+
+ def has_dualstack_ipv6(self):
+ """Return whether libzt supports dual stack sockets: yes"""
+ return True
+
+ @property
+ def family(self):
+ """Return family of socket"""
+ return self._family
+
+ @property
+ def type(self):
+ """Return type of socket"""
+ return self._type
+
+ @property
+ def proto(self):
+ """Return protocol of socket"""
+ return self._proto
+
+ def socketpair(self, sock_family, sock_type, sock_proto):
+ """Intentionally not supported"""
+ raise NotImplementedError(
+ "socketpair(): libzt does not support AF_UNIX sockets"
+ )
+
+ def create_connection(self, remote_address):
+ """Convenience function to create a connection to a remote host"""
+ # TODO: implement timeout
+ conn = socket(libzt.ZTS_AF_INET, libzt.ZTS_SOCK_STREAM, 0)
+ conn.connect(remote_address)
+ return conn
+
+ def create_server(self, local_address, sock_family=libzt.ZTS_AF_INET, backlog=None):
+ """Convenience function to create a listening socket"""
+ # TODO: implement reuse_port
+ conn = socket(sock_family, libzt.ZTS_SOCK_STREAM, 0)
+ conn.bind(local_address)
+ conn.listen(backlog)
+ return conn
+
+ def fromfd(self, fd, sock_family, sock_type, sock_proto=0):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError(
+ "fromfd(): Not supported. OS File descriptors aren't used in libzt."
+ )
+
+ def fromshare(self, data):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getaddrinfo(self, host, port, sock_family=0, sock_type=0, sock_proto=0, flags=0):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getfqdn(self, name):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def gethostbyname(self, hostname):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def gethostbyname_ex(self, hostname):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def gethostname(self):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def gethostbyaddr(self, ip_address):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getnameinfo(self, sockaddr, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getprotobyname(self, protocolname):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getservbyname(self, servicename, protocolname):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getservbyport(self, port, protocolname):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def ntohl(x):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def ntohs(x):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def htonl(x):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def htons(x):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def inet_aton(ip_string):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def inet_ntoa(packed_ip):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def inet_pton(address_family, ip_string):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def inet_ntop(address_family, packed_ip):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def CMSG_LEN(length):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def CMSG_SPACE(length):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getdefaulttimeout(self):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def setdefaulttimeout(self, timeout):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def sethostname(self, name):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def if_nameindex(self):
+ """libzt does not support this"""
+ raise NotImplementedError("if_nameindex(): libzt does not name interfaces.")
+
+ def if_nametoindex(self, if_name):
+ """libzt does not support this"""
+ raise NotImplementedError("if_nametoindex(): libzt does not name interfaces.")
+
+ def if_indextoname(self, if_index):
+ """libzt does not support this"""
+ raise NotImplementedError("if_indextoname(): libzt does not name interfaces.")
+
+ def accept(self):
+ """Accept connection on the socket"""
+ new_conn_fd, addr, port = libzt.zts_py_accept(self._fd)
+ if new_conn_fd < 0:
+ handle_error(new_conn_fd)
+ return None
+ return socket(self._family, self._type, self._proto, new_conn_fd), addr
+
+ def bind(self, local_address):
+ """Bind the socket to a local interface address"""
+ err = libzt.zts_py_bind(self._fd, self._family, self._type, local_address)
+ if err < 0:
+ handle_error(err)
+
+ def close(self):
+ """Close the socket"""
+ err = libzt.zts_py_close(self._fd)
+ if err < 0:
+ handle_error(err)
+
+ def connect(self, remote_address):
+ """Connect the socket to a remote address"""
+ err = libzt.zts_py_connect(self._fd, self._family, self._type, remote_address)
+ if err < 0:
+ handle_error(err)
+
+ def connect_ex(self, remote_address):
+ """Connect to remote host but return low-level result code, and errno on failure
+ This uses a non-thread-safe implementation of errno
+ """
+ err = libzt.zts_py_connect(self._fd, self._family, self._type, remote_address)
+ if err < 0:
+ return errno()
+ return err
+
+ def detach(self):
+ """libzt does not support this"""
+ raise NotImplementedError(
+ "detach(): Not supported. OS File descriptors aren't used in libzt.")
+
+ def dup(self):
+ """libzt does not support this"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def fileno(self):
+ """libzt does not support this"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def get_inheritable(self):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getpeername(self):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getsockname(self):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getsockopt(self, level, optname, buflen):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def getblocking(self):
+ """Get whether this socket is in blocking or non-blocking mode"""
+ return libzt.zts_py_getblocking(self._fd)
+
+ def gettimeout(self):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def ioctl(self, control, option):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def listen(self, backlog):
+ """Put the socket in a listening state (with an optional backlog argument)"""
+ err = libzt.zts_py_listen(self._fd, backlog)
+ if err < 0:
+ handle_error(err)
+
+ def makefile(mode="r", buffering=None, *, encoding=None, errors=None, newline=None):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def recv(self, n_bytes, flags=0):
+ """Read data from the socket"""
+ err, data = libzt.zts_py_recv(self._fd, n_bytes, flags)
+ if err < 0:
+ handle_error(err)
+ return None
+ return data
+
+ def recvfrom(self, bufsize, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def recvmsg(self, bufsize, ancbufsize, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def recvmsg_into(self, buffers, ancbufsize, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def recvfrom_into(self, buffer, n_bytes, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def recv_into(self, buffer, n_bytes, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def send(self, data, flags=0):
+ """Write data to the socket"""
+ err = libzt.zts_py_send(self._fd, data, len(data), flags)
+ if err < 0:
+ handle_error(err)
+ return err
+
+ def sendall(self, n_bytes, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def sendto(self, n_bytes, flags, address):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def sendmsg(self, buffers, ancdata, flags, address):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def sendmsg_afalg(self, msg, *, op, iv, assoclen, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("sendmsg_afalg(): libzt does not support AF_ALG")
+
+ def send_fds(self, sock, buffers, fds, flags, address):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def recv_fds(self, sock, bufsize, maxfds, flags):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def sendfile(self, file, offset=0, count=None):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def set_inheritable(self, inheritable):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def setblocking(self, flag):
+ """Set whether this socket is in blocking or non-blocking mode"""
+ libzt.zts_py_setblocking(self._fd, flag)
+
+ def settimeout(self, value):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ # TODO: value: buffer
+ # TODO: value: int
+ # TODO: value: None -> optlen required
+ def setsockopt(self, level, optname, value):
+ """libzt does not support this (yet)"""
+ raise NotImplementedError("libzt does not support this (yet?)")
+
+ def shutdown(self, how):
+ """Shut down one or more aspects (rx/tx) of the socket"""
+ libzt.zts_shutdown(self._fd, how)