Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code example for simple client/server communication with OSCORE #310

Open
SignorMercurio opened this issue Jun 4, 2023 · 1 comment
Open

Comments

@SignorMercurio
Copy link

Background

Thanks for the great library! I'm trying to implement a simple client/server communication demo with OSCORE, and have already read the docs here: https://aiocoap.readthedocs.io/en/latest/stateofoscore.html. However, the docs only include instructions on using the CLIs rather than code examples, which would be very helpful if added to the docs.

Attempts

So I tried to write the demo code for the client:

import asyncio
from aiocoap import *
import logging

logging.basicConfig(level=logging.INFO)

async def main():
    client = await Context.create_client_context()

    client.client_credentials.load_from_dict({
        "coap://localhost/*": {"oscore": {"contextfile": "client1/for-fileserver/"}}
    })

    request1 = Message(
        code=GET, uri='coap://localhost/sensor_data')

    print(request1.remote)
    response1 = await client.request(request1).response

    print("Response from Sensor1: %s" % response1.payload)

if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main())

As well as the server:

import asyncio
from aiocoap.resource import Resource, Site
from aiocoap import *
import logging

logging.basicConfig(level=logging.DEBUG)

class SensorResource(Resource):
    async def render_get(self, request):
        response = Message(payload=b"Sensor 1 data")
        return response

async def main():
    resource = SensorResource()

    site = Site()
    site.add_resource(('sensor_data',), resource)
    server = await Context.create_server_context(site, bind=('localhost', 5683))
    server.server_credentials.load_from_dict({
        ":client1": {"oscore": {"contextfile": "server/from-client1/"}}
    })
    print("Sensor server is running...")
    await asyncio.sleep(3600)

if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main())

The OSCORE context here is exactly the same with the docs, but I got an error No Object-Security option present. After some debugging, I believe the problem here is that the communication is using simple6 transport rather than the expected oscore transport.

I'm aware that simple6 is used for platforms like OSX so I switched to Linux, and it's still using udp6, not oscore. I've also tried setting request1.opt.object_security = b'', which resolves the above error but still using simple6 transport. In addition, I tried using the provided CLIs client and fileserver and got the same No Object-Security option present error with the same simple6 transport.

I wonder if there's anything wrong with the above code. I'll be happy to contribute a correct code example for simple client/server communication with OSCORE to the current docs.

Output of python3 -m aiocoap.cli.defaults

Python version: 3.8.9 (default, Feb 18 2022, 07:45:33)
[Clang 13.1.6 (clang-1316.0.21.2)]
aiocoap version: 0.4.7
Modules missing for subsystems:
    dtls: everything there
    oscore: everything there
    linkheader: everything there
    prettyprint: missing termcolor
Python platform: darwin
Default server transports:  oscore:tinydtls:tcpserver:tcpclient:tlsserver:tlsclient:simple6:simplesocketserver
Selected server transports: oscore:tinydtls:tcpserver:tcpclient:tlsserver:tlsclient:simple6:simplesocketserver
Default client transports:  oscore:tinydtls:tcpclient:tlsclient:simple6
Selected client transports: oscore:tinydtls:tcpclient:tlsclient:simple6
SO_REUSEPORT available (default, selected): True, True
@MariaKrm
Copy link

I don't know if this is the proper way but based on the code on contrib/oscore-plugtest I got OSCORE working using OscoreSiteWrapper. Using the following on the server in the above example.

from aiocoap.oscore_sitewrapper import OscoreSiteWrapper

...

async def main():
    resource = SensorResource()
    
    site = Site()
    site.add_resource(('sensor_data',), resource)
    credentials = aiocoap.credentials.CredentialsMap()
    credentials.load_from_dict({
        ":client1": {"oscore": {"contextfile": "server/from-client1/"}}
    })
    site = OscoreSiteWrapper(site, credentials)
    server = await Context.create_server_context(site, bind=('localhost', 5683))

    print("Sensor server is running...")
    await asyncio.sleep(3600)

Not sure how to check which transport is being used here but the network requests seem to be using OSCORE.
I'd also like to know if there is a suggested way of setting up a server 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants