Package: tsl294
Based onDCNSetup guideUsing PyPiLinux and MacOSpip3 install tsl294Windowspip install tsl294Using githubLinux and MacOSgit clone https://github.com/draklowell/TSL294 && cd TSL294 && python3 setup.py installWindowsDownload client and in downloaded folder runpython setup.py installDependenciesdcn (2.0.0.4.1.2)func-timeout (4.3.5)InfoPrivacyConnection between two nodes is wrapped byTLSv1.2( without certificate verification ), also packets are encrypted with RSA.High-level protocols conflictTo avoid protocol conflicts, we recommend to useprotocol sign, it is some bytes in begin of packet, that indicate what protocol is usingLicenseApache License 2.0Using guidePacket format18 BYTES - DCN Header
844 BYTES - TSL294 Header:
    294 BYTES - Source key ( Can be only RSA key )
    294 BYTES - Destination key ( Can be RSA key or zero bytes - broadcast to all clients)
    256 BYTES - Signature of encrypted content 
64676 BYTES - Encrypted ( if destination is RSA key ) contentMax size of content in packet -64676(pow(2, 16) - 16 - 844).Create clientThere are three arguments -key,friendly_hostsandlimit_queuekey- client RSA key ( only2048 bitssize )friendly_hosts- known nodes in format ( example:("1.2.3.4", 300)), also it request official nodes, from official trackerlimit_queue- max size of queue (-1- unlimited ), recommended65536importtsl294client=tsl294.client.Client(key=tsl294.crypto.key.Key.random(2048),friendly_hosts=[],limit_queue=-1)Send packetAfter generating packet, client sends it to user with known key. After that, it returns the count of successfully sent copies of the packet and packet hash ( as bytes )importbase64# Load key from filewithopen("target.pem","rb")asfile:key=tsl294.crypto.key.Key.importKey(file.read())# Send packetcount,hash=client.send(b"Hello, world!",key)print(f"Sended copies of packet:{count}")print(f"Packet hash ( base64 encoded ):{base64.b64encode(hash).decode()}")Output:Sended copies of packet: 1
Packet hash ( base64 encoded ): L/78pQALheezMsoc9BTxfheAcNIw7fPQtYHsDBjwDSU=Receive next packetWhen the client gets the new massage from the server, client adds the packet to the queue. When we callclient.accept(), we get the first element of the queue, and then remove it ( we can limit the queue, while initializing client )importbase64content,key,hash=client.accept()# or client.next() or next(client)print(f"Content of packet:{content.decode()}")print(f"Source of packet:{base64.b64encode(key.getHash()).decode()}")print(f"Packet hash ( base64 encoded ):{base64.b64encode(hash).decode()}")Output:Content of packet: Hello, world!
Source of packet: MEtdj9sSPdM0g00Hk6q1Jjvx72f53Gd4uIkMYWN4Khk=
Packet hash ( base64 encoded ): L/78pQALheezMsoc9BTxfheAcNIw7fPQtYHsDBjwDSU=Close clientYou need close client in end of workclient.close()Simple appNow, we can create a simple app usingDCN-TSLv294, which allows to convert user's message to uppercase. When server gets new packet from the user, it converts packet content to uppercase and sends it back to the client. Example:
User sendsHello, world!Server returnsHELLO, WORLD!Server sidefromtsl294.clientimportClientfromtsl294importKeywithopen("private.pem","rb")asfile:key=Key.importKey(file.read())client=Client(key)try:whileTrue:data,key,hash=client.accept()client.send(data.upper(),key)exceptKeyboardInterrupt:passclient.close()To close server, just pressCtrl + CClient sidefromtsl294.clientimportClientfromtsl294importKeywithopen("public.pem","rb")asfile:server_key=Key.importKey(file.read())message=input().encode("utf-8")client=Client()try:client.send(message,server_key)data,key,hash=client.accept()whilekey!=server_key.getPublic():data,key,hash=client.accept()print(data.decode("utf-8"))exceptKeyboardInterrupt:passclient.close()