ToxicBuild Poor’s Protocol

The ToxicBuild Poor’s Protocol is a simple protocol used to exchange messages, using tcp sockets, between the components of ToxicBuild. It is as follows:

The first n bytes, until the first \n indicate the length of the message, the rest of the message is a utf-8 encoded json. This json must contain 3 keys: token, action and body.

The token is obviously for authentication. The action key says what you want to do and the body are params specific for each action.

Toxiccore provides base classes for implementing client/server comunication using the tpp.

Example

Server

For the server you just to implement a client_connected method in your subclass of BaseToxicProtocol. When the request reaches this point the client is already authenticated, you just need to take care of executing the desired action.

The requested action is available in the self.action attribute and the body (with the params for action) are in the self.data['body'] attribute.

To send a response to the client call the send_response method. It get two params: code and body

from toxiccore.protocol import BaseToxicProtocol

class MyProtocol(BaseToxicProtocol):

    async def client_connected(self):
        if self.action != "my-action":
            # code > 0 means something went wrong.
            await self.send_response(code=1, body={'error': 'invalid action'})
            return

        params = self.data['body']
        # do something
        await fn(**params)
        # code 0 means everthing ok.
        await self.send_response(code=0, body={'my-action': 'ok! :)'})

Now you create a server that uses your protocol

from toxiccore.server import ToxicServer

class MyServer(ToxicServer):

    PROTOCOL_CLS = MyProtocol

if __name__ == '__main__':

    host = '0.0.0.0'
    port = 9876
    server = MyServer(host, port)
    server.start()

Note

To use ssl connections you must instantiate your server passing use_ssl=True and the path for your cert and key files.

certfile = '/path/to/file.cert'
keyfile = '/path/to/file.key'
server = MyServer(host, port, use_ssl=True, certfile=certfile, keyfile=keyfile)

Client

To have a client to your server, create a subclass of BaseToxicClient and call the request2server() method.

from toxiccore.client import BaseToxicClient

class MyClient(BaseToxicClient):

    async def my_action(self):

        action = 'my-action'
        body = {'a': 'value'}
        # this token is used to authenticate in the server.
        token = 'this is secret'
        # timeout for unresponsive servers, in seconds
        timeout = 600

        r = await self.request2server(action, body, token, timeout=timeout)
        return r

To use the client, use it in an async context manager:

host = '127.0.0.1'
port = 9876
# indicates if the server uses ssl connections
use_ssl = True
# indicates if the client should validate the certificate.
# should be false for self-signed certificates
validate_cert = False

async with MyClient(host, port, use_ssl, validate_cert) as client:
    try:
        r = await client.my_action()
    except ToxicClientException as err:
        # this happens when the server returns code > 0
        print(err)