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 time +import sys 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 - -remoteIP = None - -# A port your app logic may use -serverPort = 8080 - -# Flags to keep state -is_joined = False -is_online = False -mode = None - def print_usage(): - print("\nUsage: \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: \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 +# Main # -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') +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 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 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((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()) + # + # 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)