-
Notifications
You must be signed in to change notification settings - Fork 2.1k
net/gcoap: support DTLS #15549
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
net/gcoap: support DTLS #15549
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is still WIP, but I think you can get rid of most #ifdef
/ #if
foobar, when using IS_ACTIVE()
and relying on the optimizer.
#ifdef CONFIG_GCOAP_ENABLE_DTLS | ||
#define SOCK_DTLS_CLIENT_TAG (2) | ||
static sock_dtls_t _sock_dtls; | ||
static kernel_pid_t _main_thread; | ||
|
||
static event_timeout_t _dtls_session_free_up_tmout; | ||
static event_callback_t _dtls_session_free_up_tmout_cb; | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can even drop the preprocessor #if
around here and use if (IS_ACTIVE(CONFIG_GCOAP_ENABLE_DTLS))
through-out the code. This way we get rid of a lot of pre-processor magic, which allows you to not hide your code from the compiler in any case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see gcoap specific code in the dtls_session_management
module other than reading the max peer config option. Maybe we could move it out of gcoap and make it an optional module for sock dtls instead?
Might be a bug when translating the Kconfig option. This is done here. Have you tried setting it manually when building e.g.:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just some high-level comments
f482ca2
to
e46166c
Compare
After a long time finally a new push. This is my current WIP state.
The current state is still experimental. But most issues stem from the Known issues:
Still missing in gcoap/session management:
|
9dff2d3
to
45a064a
Compare
I've updated and rebased once again (mostly documentation). I remove the WIP state now. The issues with DTLS are not related to gcoap, nonetheless I keep the hotfix pkg/tinydtls commit for easier testing for now. Testing procedure from start post remains. I will also update the start post to the current state soon. DTLS epoch checking and session expiration is not yet addressed, however, I would consider both to address in a follow-up. Feedback and review is more than welcome. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not taking a look at this earlier.
There are two conceptual things that irk me, but that might also be due to me not being familiar with the CoAP/DTLS/async socket implementation.
- Why is DTLS sock not just an extension to UDP sock? The DTLS implementation would then be specific to the network stack (e.g. GNRC), but that would still be preferable to pushing it to the application layer IMHO
- Why is there a need for
dtls/dsm
- can't we attach the session directly to the socket?
sys/net/dsm/dsm.c
Outdated
for (uint8_t i=0; i < DTLS_PEER_MAX; i++) { | ||
_sessions[i].state = SESSION_STATE_NONE; | ||
memset(&_sessions[i], 0, sizeof(dsm_session_t)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's redundant as _sessions
is already static
and thus initialized with 0.
Like mentioned in one conversation comment, the distribution how the maximum number of sessions Additionally, I have a scenario in mind: cross-application session management. Possibly a bit too far thought, but I can definitely see problems if an application can theoretically "occupy" all sessions indefinitely or for a very long time. By this I mean that e.g. Right now dsm does not help here, but is very easy to extend to get access to sessions stored by other applications and close them to free peer resources. Provided dsm is used for storage by the respective applications. Although I have built in the mechanism in gcoap for this very reason, so that sessions are automatically freed, but I consider the basic scenario with multiple DTLS applications far from impossible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI still has some style nits so I added my own
if (timeout != SOCK_NO_TIMEOUT) { | ||
uint32_t diff = (xtimer_now_usec() - start); | ||
timeout = (diff > timeout) ? 0: timeout - diff; | ||
is_timed_out = (res < 0) || (timeout == 0); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment about this?
Future readers won't be hunting down the PR comment 😉
I've also renamed |
Please squash (& rebase) |
08ea058
to
c38bec4
Compare
Squashed and rebased. Also removed the tinyDTLS workaround commit, since it is now merged into master. Without this, it could happen that two session slots were added as available for one closed session. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is still something wrong here:
When playing around with two native RIOT nodes querying a third native RIOT node with
coap get fe80::7837:fcff:fe7d:1aaf 5684 /.well-known/core
after a while one of the nodes would no longer receive a response. (This is after the dsm: removed session
message), the server shows
CoAP server is listening on port 5684
Connection secured with DTLS
Free DTLS session slots: 1/1
CLI requests sent: 0
CoAP open requests: 0
Configured Proxy: None
The clients meanwhile display
CoAP server is listening on port 5684
Connection secured with DTLS
Free DTLS session slots: 13/1
CLI requests sent: 17
CoAP open requests: 0
Configured Proxy: None
The number of 'free sessions' increases with each request that does not receive a response.
Fixed. It was a problem with finding sessions which have been removed but stated them as "already existing", since session state was not taken into account. |
Thank you, works now! |
7f2ce6f
to
0a8eaea
Compare
Squashed. |
Thank you! |
Thanks for the help and review, everyone! |
I was trying to test #17141, and was for this using the |
This PR is still WIP. But the core mechanics work. Feedback in every way is very, very welcome!
Contribution description
This PR adds DTLS support in gcoap. It adds the following:
_sock_send
function to abstract udp/dtls away from gcoapBut it's still not complete:
sock_udp_ep_t
<->sock_dtls_session_t
, function to get epoch from session)And known bug(s) remain:
DTLS_PEER_MAX
for tinyDTLS? I've seen no file where it is set except the Kconfig file. It appears only in the build-files. Whatever I set, it is always 1 for tinyDTLS.At the end are some more in depth comments regarding session management and some unchanged parameters.
Thanks to @pokgak for his gcoap/dtls PR, that helped me.
Testing procedure
It's currently only tested between native RIOT nodes and between RIOT and coap-shell.
For testing between two RIOT nodes: flash
example/gcoap
and send a CoAP get request from the client to the server:coap get <ip> 5684 /riot/board
For testing between RIOT and coap-shell: flash
example/gcoap
on one device/native and launch the coap-shell. For native testing:Issues/PRs references
Issue #15517 needs to be resolved. For now I've included a workaround commit till it's resolved. Workaround is just for testing purposes.
Relates to #10897
Comments
Session management: Gcoap only stores memos for client requests on client-side and registered observers on server-side. This causes clients to block internal session slots in tinyDTLS if clients crash or sessions are simply not resolved by the clients - the server gets completely blocked if all session slots are occupied. And these sessions/udp endpoints are not stored in any way. Gcoap has to make sure to never lose sessions and to free up slots on its own if neccessary. This sadly costs memory - but I have not found a way around it.
Gcoap now reuses a session if it's already established. If the last session slot is occupied a configurable timeout will start and closes a session after expiration. Then the oldest, in terms of last usage, session will be closed.
Not changing sock_udp in parameters: In the long term it would be nice to support DTLS and UDP connections simultaneously if desired. Therefore I did not want to change any socket parameters. For supporting multiple transport layer we should maybe think about a more unified socket/tl type in gcoap which supports more than DTLS/UDP (if needed) and is also supported by the gcoap API. But that is out of scope of this PR I guess.