diff --git a/README.md b/README.md index e5273b8..74fa3b9 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,8 @@ that every call in ```tox.py``` has the right signature, but it runs It has been tested with UDP and TCP proxy (Tor). It has ***not*** been tested on Windows, and there may be some minor breakage, which should be easy to fix. There is a good coverage integration testsuite in ```wrapper_tests```. -Change to that directory and run ```tests_wrapper.py --help```. +Change to that directory and run ```tests_wrapper.py --help```; the test +suite gives a good set of examples of usage. ## Install @@ -78,3 +79,6 @@ Others include: Hardcore C wrapping which is not easy to keep up to date. No support for NGC or toxencryptsave. Abandonned. This was the basis for the TokTok/py-toxcore-c code until recently. + +To our point of view, the ability of CTYPEs to follow code in the +debugger is crucial. diff --git a/wrapper/libtox.py b/wrapper/libtox.py index 32e7335..36763e3 100644 --- a/wrapper/libtox.py +++ b/wrapper/libtox.py @@ -3,7 +3,7 @@ import os import sys from ctypes import CDLL -# You need a libs directory beside this directory +# You need a libs directory beside this directory # and you need to link your libtoxcore.so and libtoxav.so # and libtoxencryptsave.so into ../libs/ # Link all 3 to libtoxcore.so if you have only libtoxcore.so @@ -13,7 +13,7 @@ try: except ImportError: sLIBS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'libs') - + class LibToxCore: def __init__(self): @@ -40,11 +40,11 @@ class LibToxCore: class LibToxAV: def __init__(self): - platform = util.get_platform() - if platform == 'Windows': + platform = sys.platform + if platform == 'win32': # on Windows av api is in libtox.dll self._libtoxav = CDLL(os.path.join(sLIBS_DIR, 'libtox.dll')) - elif platform == 'Darwin': + elif platform == 'darwin': self._libtoxav = CDLL('libtoxcore.dylib') else: libFile = os.path.join(sLIBS_DIR, 'libtoxav.so') diff --git a/wrapper/tox.py b/wrapper/tox.py index e7207c1..ece67fb 100644 --- a/wrapper/tox.py +++ b/wrapper/tox.py @@ -172,7 +172,7 @@ class Tox: LOG_ERROR(f"tox_kill {e!s}") else: LOG_DEBUG(f"tox_kill") - + # ----------------------------------------------------------------------------------------------------------------- # Startup options # ----------------------------------------------------------------------------------------------------------------- @@ -287,7 +287,7 @@ class Tox: LOG_ERROR(f"libtoxcore.tox_bootstrap {e}") # dunno raise - + tox_err_bootstrap = tox_err_bootstrap.value if tox_err_bootstrap == TOX_ERR_BOOTSTRAP['OK']: return bool(result) @@ -1341,7 +1341,7 @@ class Tox: POINTER(None)()) self.file_recv_control_cb = None return - + LOG_DEBUG(f"tox_callback_file_recv_control") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_int, c_void_p) self.file_recv_control_cb = c_callback(callback) @@ -1607,7 +1607,7 @@ class Tox: POINTER(None)()) self.file_recv_cb = None return - + LOG_DEBUG(f"tox_callback_file_recv") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_uint32, c_uint64, c_char_p, c_size_t, c_void_p) self.file_recv_cb = c_callback(callback) @@ -1640,7 +1640,7 @@ class Tox: POINTER(None)()) self.file_recv_chunk_cb = None return - + LOG_DEBUG(f"tox_callback_file_recv_chunk") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint32, c_uint64, POINTER(c_uint8), c_size_t, c_void_p) self.file_recv_chunk_cb = c_callback(callback) @@ -1764,7 +1764,7 @@ class Tox: self.friend_lossless_packet_cb = None self.libtoxcore.tox_callback_friend_lossless_packet(self._tox_pointer, POINTER(None)()) return - + LOG_DEBUG(f"callback_friend_lossless_packet") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, POINTER(c_uint8), c_size_t, c_void_p) self.friend_lossless_packet_cb = c_callback(callback) @@ -2387,7 +2387,6 @@ class Tox: error = c_int() buff = create_string_buffer(TOX_GROUP_CHAT_ID_SIZE) - LOG_DEBUG(f"tox_group_get_chat_id") result = Tox.libtoxcore.tox_group_get_chat_id(self._tox_pointer, group_number, buff, byref(error)) @@ -2575,23 +2574,27 @@ class Tox: # ----------------------------------------------------------------------------------------------------------------- def group_send_custom_packet(self, group_number, lossless, data): - """ - Send a custom packet to the group. + """Send a custom packet to the group. - If lossless is true the packet will be lossless. Lossless packet behaviour is comparable - to TCP (reliability, arrive in order) but with packets instead of a stream. + If lossless is true the packet will be lossless. Lossless + packet behaviour is comparable to TCP (reliability, arrive in + order) but with packets instead of a stream. - If lossless is false, the packet will be lossy. Lossy packets behave like UDP packets, - meaning they might never reach the other side or might arrive more than once (if someone - is messing with the connection) or might arrive in the wrong order. + If lossless is false, the packet will be lossy. Lossy packets + behave like UDP packets, meaning they might never reach the + other side or might arrive more than once (if someone is + messing with the connection) or might arrive in the wrong + order. - Unless latency is an issue or message reliability is not important, it is recommended that you use - lossless custom packets. + Unless latency is an issue or message reliability is not + important, it is recommended that you use lossless custom + packets. :param group_number: The group number of the group the message is intended for. :param lossless: True if the packet should be lossless. :param data A byte array containing the packet data. :return True on success. + """ error = c_int() diff --git a/wrapper/toxav.py b/wrapper/toxav.py index 9fbe96c..1ae8632 100644 --- a/wrapper/toxav.py +++ b/wrapper/toxav.py @@ -391,7 +391,7 @@ class ToxAV: self.libtoxav.toxav_callback_video_receive_frame(self._toxav_pointer, POINTER(None)(), user_data) self.video_receive_frame_cb = None return - + LOG_DEBUG(f"toxav_callback_video_receive_frame") c_callback = CFUNCTYPE(None, c_void_p, c_uint32, c_uint16, c_uint16, POINTER(c_uint8), POINTER(c_uint8), POINTER(c_uint8), diff --git a/wrapper_tests/support_testing.py b/wrapper_tests/support_testing.py index 8fbc14d..6edc7a7 100644 --- a/wrapper_tests/support_testing.py +++ b/wrapper_tests/support_testing.py @@ -518,23 +518,60 @@ def _get_nodes_path(oArgs=None): DEFAULT_NODES_COUNT = 4 -def generate_nodes(nodes_count=DEFAULT_NODES_COUNT, oArgs=None): - sFile = _get_nodes_path(oArgs=oArgs) - return generate_nodes_from_file(sFile, nodes_count) +def generate_nodes( + oArgs=None, + nodes_count=DEFAULT_NODES_COUNT, + ipv='ipv4', + udp_not_tcp=True): + if oArgs is None: + # Windwoes + sFile = os.path.join(os.getenv('HOME'), '.config', 'tox', 'DHTnodes.json') + else: + sFile = _get_nodes_path(oArgs=oArgs) + return generate_nodes_from_file(sFile, + nodes_count=nodes_count, + ipv=ipv, udp_not_tcp=udp_not_tcp) -def generate_nodes_from_file(sFile, nodes_count=DEFAULT_NODES_COUNT): +def generate_nodes_from_file(sFile, + nodes_count=DEFAULT_NODES_COUNT, + ipv='ipv4', + udp_not_tcp=True, + ): + """https://github.com/TokTok/c-toxcore/issues/469 +I had a conversation with @irungentoo on IRC about whether we really need to call tox_bootstrap() when having UDP disabled and why. The answer is yes, because in addition to TCP relays (tox_add_tcp_relay()), toxcore also needs to know addresses of UDP onion nodes in order to work correctly. The DHT, however, is not used when UDP is disabled. tox_bootstrap() function resolves the address passed to it as argument and calls onion_add_bs_node_path() and DHT_bootstrap() functions. Although calling DHT_bootstrap() is not really necessary as DHT is not used, we still need to resolve the address of the DHT node in order to populate the onion routes with onion_add_bs_node_path() call. +""" if not os.path.exists(sFile): LOG.error("generate_nodes_from_file file not found " +sFile) return [] - LOG.info("generate_nodes_from_file " +sFile) - with open(sFile, 'rt') as fl: - json_nodes = json.loads(fl.read())['nodes'] - nodes = [(node['ipv4'], node['port'], node['public_key'],) for - node in json_nodes if node['ipv4'] != 'NONE'] - sorted_nodes = nodes + try: + with open(sFile, 'rt') as fl: + json_nodes = json.loads(fl.read())['nodes'] + except Exception as e: + LOG.error(f"generate_nodes_from_file error {sFile}\n{e}") + return [] + else: + LOG.info("generate_nodes_from_file " +sFile) + + if udp_not_tcp: + nodes = [(node[ipv], node['port'], node['public_key'],) for + node in json_nodes if node[ipv] != 'NONE' \ + and node["status_udp"] in [True, "true"] + ] + else: + nodes = [] + elts = [(node[ipv], node['tcp_ports'], node['public_key'],) \ + for node in json_nodes if node[ipv] != 'NONE' \ + and node['last_ping'] > 0 + and node["status_tcp"] in [True, "true"] + ] + for (ipv4, ports, public_key,) in elts: + for port in ports: + nodes += [(ipv4, port, public_key)] + sorted_nodes = sorted(nodes) random.shuffle(sorted_nodes) if nodes_count is not None and len(sorted_nodes) > nodes_count: sorted_nodes = sorted_nodes[-nodes_count:] + LOG.debug(f"generate_nodes_from_file {sFile} len={len(sorted_nodes)}") return sorted_nodes def tox_bootstrapd_port():