chrysn / aiocoap

The Python CoAP library
Other
261 stars 119 forks source link

aiocoap-rd: An exception occurred while rendering a resource: KeyError(None) #221

Open 2bdkid opened 3 years ago

2bdkid commented 3 years ago

I'm running into an issue registering some resources with aiocoap-rd. In the first instance of my server program, I create a context and bind to a specified port, and then do the registration:

# set up root
protocol = await Context.create_server_context(root, bind=('::', args.port))  # args.port == 5648
registration = Registerer(protocol, rd=args.rd)  # args.rd == "coap://<myip>"

This registration goes through just fine:

aiocoap-client coap://localhost/resource-lookup/?rt=weight
<coap://<my-ip>:5648/weight>; ct=60; rt="load weight"; obs; title=brady-rpi; anchor="coap://<my-ip>:5648"

Then, I start another instance of my server on the same host (I think this may be the problem), but bind to a different port:

# set up root
protocol = await Context.create_server_context(root, bind=('::', args.port))  # args.port == 5649
registration = Registerer(protocol, rd=args.rd)  # args.rd == "coap://<myip>"

After a second, aiocoap-rd spits this out:

ERROR:coap-server:An exception occurred while rendering a resource: KeyError(None)
Traceback (most recent call last):
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/protocol.py", line 383, in _render_to_plumbing_request
    await self._render_to_plumbing_request_inner(plumbing_request,
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/protocol.py", line 512, in _render_to_plumbing_request_inner
    response = await self.serversite.render(request)
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/cli/rd.py", line 620, in render
    return await Site.render(self, request)
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/resource.py", line 366, in render
    return await child.render(subrequest)
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/resource.py", line 114, in render
    response = await m(request)
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/cli/rd.py", line 376, in render_post
    regresource = self.common_rd.initialize_endpoint(request.remote, registration_parameters)
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/cli/rd.py", line 312, in initialize_endpoint
    oldreg.delete()
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/cli/rd.py", line 198, in delete
    self._delete_cb()
  File "/home/brady/.local/lib/python3.8/site-packages/aiocoap/cli/rd.py", line 323, in delete
    self.proxy_active.pop(proxy_host)
KeyError: None

Then, the second server instance receives an error 500 from rd.

Interestingly, if I start the second instance again, its registration goes through, but the first server instance's registration is lost. Lost as in it's no longer sent back when queried from coap://localhost/resource-lookup/.

aiocoap-client coap://localhost/resource-lookup/?rt=weight
<coap://<my-ip>:5649/weight>; ct=60; rt="load weight"; obs; title=brady-rpi-2; anchor="coap://<my-ip>:5649"

It seems like aiocoap-rd is getting confused by having a registration from the same ip, but with different ports.

2bdkid commented 3 years ago

Ok I figured it out. The rd keeps track based on (ep, d) and the ip:port has nothing to do with the issue. I added an ep in the registration_parameters of each Registerer and that fixed the issue. Reading through the code, the ep was being set through fqdn and that would have been the same because I'm running 2 instances on the same host. That's why the rd thought it was a re-register.

chrysn commented 3 years ago

Thanks for reporting this; reopening as just because clients behave oddly, the RD server should still not spitting out KeyError messages.

(What really should have happened would be the clients flip-flopping the address of the registered item back and forth between their ports -- although on a more to-the-spec level, really the RD should ask at least some level of security from the endpoint).