-
Notifications
You must be signed in to change notification settings - Fork 2k
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
gcoap: add lazy init mode #12529
gcoap: add lazy init mode #12529
Conversation
gcoap lazy init mode is for applications that wants to first do something before gcoap starts its server thread (e.g. loading credential into credman for (D)TLS). It can be enabled by adding `gcoap_lazy_init` to `USEMODULE`. In lazy init mode, the call to gcoap_init() only initializes relevant _coap_state but does not starts the coap server thread. The server will be started at the first gcoap_register_listener() call, if no server is started already. As long as there is no server running, NON requests can be sent as usual but the responses will be ignored. Sending a CON request on the other hand will fail because a CON request expects to receive a response.
@kb2ma this is based on your idea at the last summit. I hope to get feedback on this and if I could proceed with it :) |
f6967fc
to
49d1b9e
Compare
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.
Some initial comments
@@ -633,6 +651,15 @@ kernel_pid_t gcoap_init(void) | |||
|
|||
void gcoap_register_listener(gcoap_listener_t *listener) | |||
{ | |||
#ifdef MODULE_GCOAP_LAZY_INIT |
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.
If a node is not registering additional resources (I know, maybe not the most common of cases), and acts only as a client, then it won't be able to perform CON requests right?
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.
Yup. This is checked in gcoap_req_send()
, if a CON request is made, it will fail to send:
RIOT/sys/net/application_layer/gcoap/gcoap.c
Lines 760 to 765 in 49d1b9e
#ifdef MODULE_GCOAP_LAZY_INIT | |
if (msg_type == COAP_TYPE_CON && _pid == KERNEL_PID_UNDEF) { | |
DEBUG("gcoap: cannot send CON request in lazy init mode\n"); | |
return 0; | |
} | |
#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.
Yes, I saw that. Is that a wanted behaviour?: Every node must register at least one listener to be able to send CON requests.
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.
Maybe we could find another way to trigger the server to start
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.
Alternatively, instead of returning an error, the server can be started from gcoap_req_send()
when the client wants to send a CON request. The main goal of lazy init is the delayed start of the server until it is really needed. So starting the server from gcoap_req_send()
still fits in the requirement.
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.
O.k. @leandrolanzieri ?
Thanks @pokgak for taking a stab at implementation. It's pretty clear this idea was not my best. :-/ The amount of code and the issues raised show it would be simpler to be more explicit about startup. I just published an alternative PR, #12798 to accomplish this goal. An application can explicitly start gcoap, but by default it still starts at auto-init time. |
Closed in favor of #12798. |
Contribution description
This PR introduces lazy init mode for gcoap. lazy init mode is for applications that want to first do something before gcoap starts its server thread (e.g. loading credential into credman for (D)TLS). It can be enabled by adding
USEMODULE += gcoap_lazy_init
to the application MakefileAn alternative to this approach would be to just take
gcoap_init()
out of autoinit and calls it manually from the application but this may break existing applications, so I prefer not to do that if there is an alternative.How it works
In lazy init mode, the call to
gcoap_init()
only initializes the_coap_state
but does not start the coap server thread. It will be started at the firstgcoap_register_listener()
call if there is no server that is started already.As long as there is no server running, NON requests can be sent as usual but the responses will be ignored. Sending a CON request, on the other hand, will fail because a CON request expects to receive a response. After the server is started (
gcoap_register_listener()
is called), the application should behave like a normal gcoap application.Testing procedure
For now, I only tested sending NON and CON requests from a lazy init client to a gcoap normal server.
Set
BUILD_IN_DOCKER=0
if you are using Docker to build because the env values are not carried into the container for building.cd examples/gcoap
PORT=tap0 make all term
PORT=tap1 USEMODULE=gcoap_lazy_init make all term
coap put <server ip> 5683 /cli/stats 100
coap info
on the server, cli stats must be 100 nowcoap put -c <server ip> 5683 /cli/stats 200
Issues/PRs references
This is part of the work needed to add DTLS support to gcoap. See #12104 (comment).