Fixed issue that caused message to be not correctly reset even after
it is consumed after send sets errno to EAGAIN or EWOULDBLOCK
Signed-off-by: Dominik Dess <dominik.dess@grandcentrix.net>
this has a number of advantages:
- allows to only create notifications for each client if there are no
messages already waiting to be send, in practice prioritizing the
memory for messages for answers, thus staying more "responsive".
- saves a fair bit of memory by eliminationg now redundant client_ctx
pointer per observer.
- fixes a potential subtle bug: previously, an observer reset would've
stopped the first observation found with a matching token, which
might've belonged to a differen client.
Signed-off-by: Henning Fleddermann <henning.fleddermann@grandcentrix.net>
This restructures the lwm2m_engine to use a non-blocking socket access
instead of the previously used blocking style, and eliminates any
socket-access from outside of the main work loop.
The main motivation behind this is an issue within nordics
nrf_modem_lib/modem-fw on nrf9160, that leads to socket send() calls to
block indefinitely when the shared memory used for
rpc-communication with the modem is already exhausted because of
incoming data.
This lead to the lwm2m_engine locking up on send calls when there is
also a large amount of incoming data.
This works around this issue, by only issuing send calls when poll
reports the socket to be ready for sending, and (more importantly) by
always receiving all buffered incoming data before sending anything.
There might still be a (perhaps academic) possibility where this
situation might be triggered, when the scheduler interrupts the lwm2m
thread in-between receiving and sending, but for now we have not yet
observed this.
Besides working around the aforementioned issue, this also simplifies
the way resends are handled as they are no longer send from the main
system-workqueue, and limits all interaction with the sockets to a
single thread.
Signed-off-by: Henning Fleddermann <henning.fleddermann@grandcentrix.net>
Since the API already has a function to create an LwM2M object instance,
it makes sense to add a corresponding delete funtion, allowing the
application to delete created objects.
Additionally, for the remote delete set the Registration Update trigger
only when not in bootstrap mode.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
The Registration Update message should be sent whenever an object
instance is created or deleted. Currently this was only the case when an
object instance was created by the server and not by the application.
Fix this by triggerng the Registration Update from the API function
as well.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Currently the lwm2m_path_log_strdup allocates a temporary buffer on a
stack, and then passes it to the log_strdup function to create a copy
of the string for the logger. log_strdup however will not copy the
string if for instance immediate logging is used, therefore the logging
function will still use the memory address of the already invalid buffer
allocated within lwm2m_path_log_strdup.
Fix this by passing an addittional `buf` parameter to the
lwm2m_path_log_strdup function, therefore allowing the user to provide
the buffer within a valid scope.
CID: 220536
Fixes#34005
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Made the LwM2M engine checks for pmin and pmax optional to adhere to
the LwM2M specificattion. We now first check that pmin and pmax are
actually set. Also changed the default CONFIG values for the attributes
pmin and pmax to 0 to indicate that they are not active by default.
Fixes#34329.
Signed-off-by: Maik Vermeulen <maik.vermeulen@innotractor.com>
Replace all existing deprecated API with the recommended alternative.
Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
The specification states that the server can cancel observations "at any
moment, by sendinga GET request with Observe option=1, the LwM2M Server
cancancel an “Observe”operation on a specified Resource, or specified
Object Instance(s)."
It does not mention any token matching requirement, but RFC 7641 does.
The correct interpretation is not obvious. The EMQx LwM2M implementation
uses a new token for instance, which does not work with Zephyrs token
matching cancel-observe.
This commit introduces cancel-observe via path matching as a Kconfig
option. This could hypothetically introduce problems when we are
connected to multiple peers simultaneously, but since that is not likely
to be supported for a long time (if ever), this change should be fairly
uncontroversial since path matching is only used as a fallback.
Signed-off-by: Benjamin Lindqvist <benjamin.lindqvist@endian.se>
Each object now have to specify the object version it implements.
Based on this information the LwM2M engine can decide whether it's
needed to report the object version during Registration/Discovery
operations or not.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
The payload of the Register/Register Update message is also formatted as
application/link-format. Therefore it's reasonable to reuse the new
content writer instead of filling the payload manually.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit adds a new content writer, application/link-format, which
can be used during the Discovery procedure, to fill the content of the
response payload.
Introducing this new content writer, which encapsulates some of the
details like attribute handling which is different for bootstrap/regular
discovery, allows to unify the discovery handler in the lwm2m_engine,
thus it's no longer needed to have spearate handler functions for
bootstrap/regular discovery.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
`.well-known/core` resource is described by the CoAP RFC as an optional
method of resource discovery. The LwM2M specification though makes no
mentionon about this mechanism and provides an alternative method of
resource discovery instead (Device Management Discover, sec 5.4.2, and
Bootstrap Discovery, sec 5.2.7.3).
Since LwM2M does not require to implement `.well-known/core` resource
and it complicates the existing Discovery mechanism (and likely cause a
security concern) remove its handling from the LwM2M implementation.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Introduce LwM2M engine helper functions that allows to work with LwM2M
attributes outside of lwm2m_engine.c.
This is a groundwork for application/lwm2m-format content writer.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Add option to disable validation callback support by setting the
validation buffer size to 0, which allows to save some memory in case
it's not needed.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Add a data validation callback to the resource structure, which can be
registered by an application. It allows to verify the data before
actually modifying the resource data.
If the callback is registered for a resource, the data is decoded into a
temporary buffer first, and only copied into the actual resource buffer
if the validation is successfull. If no validation is required (and thus
no callback registered) the resource value is decoded directly into the
resource buffer, as it used to be.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Added 3 utility functions :
- lwm2m_engine_update_period_service() which updates the period of a
given service.
- lwm2m_engine_update_period_min_observer() which updates the
min_period_sec for a given observe node.
- lwm2m_engine_update_period_max_observer() which updates the
max_period_sec for a given observe node.
Signed-off-by: Thomas LE ROUX <thomas.leroux@smile.fr>
RFC 7252 (CoAP) specifies value of the Version (Ver) field in the
protocol header to value 1. This patch defines value of the Version
field to make packet initialization easier. All samples and tests
are updated to use the new COAP_VERSION_1 field when initializing
a CoAP packet.
Signed-off-by: Hubert Miś <hubert.mis@nordicsemi.no>
Introduce retransmission counter to the coap_pending structure. This
allows to simplify the retransmission logic and allows to keep track of
the number of remaining retranmissions.
Additionally, extend the `coap_pending_init()` function with `retries`
parameter, which allows to set the retransmission count individually for
each confirmable transaction.
Fixes#28117
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Multi-instance resources shall report its dimension (number of
resource instances) on discovery. Since it was not possible to tell
simply on the instance count whether the resource is multi-instance or
not (there could be a multi-instance resource with only one instance
avaialble) add a new parameter to the structure representing resource,
indicating whether it's multi-instance or not.
Add dimension information to the discovery result.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Remove any references of Bootstrap Discovery from Device Management
Discovery procedure and fix some of it's logic following the
specification.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Bootstrap discovery was not implemented properly in the LwM2M engine.
Although, there were some indications in the source code that it is
implemented, it was not done according to spec (and actually broken).
Given that Bootstrap Discovery procedure differs a lot from the regular
Device Management Discovery (different permissions, different
information returned), it's easier to implement it as a separate
function (`bootstrap_discovery()`) instead of making the existing
`do_discovery_op()` function even more complicated.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
A dedicated LwM2M execute callback type has been implemented which
supports execute arguments. The lwm2m engine, lwm2m_client sample and
lwm2m objects have been updated accordingly. Also the API change has
been documented, and the lwm2m engine reference has been updated.
Fixes#30551.
Signed-off-by: Maik Vermeulen <maik.vermeulen@innotractor.com>
Previously, lwm2m_engine set would check against the max_data_len
parameter of the ressource, but didn't take into consideration the
(possibly changed) max_data_len returned by the pre_write callback.
Fixes#30541
Signed-off-by: Henning Fleddermann <henning.fleddermann@grandcentrix.net>
The message should only be returned if the requested pending/reply
pointer is not NULL. Otherwise it could get an incorrect match (for
instance if specific pending pointer is searched for and reply is NULL
the function could return any message that doesn't expect a reply (and
thus has its reply pointer set to NULL).
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
LwM2M engine by default sends piggybacked responses for requests after
all callbacks are executed. This approach however isn't good enough if
the application callback executes some lenghty operations (for instance
during FW update). Delaying the ACK may result in unnecessary
retransmissions.
This commits adds an API function which allows to send an early empty
ACK from the application callback. This prevents further retransmissions
from the server side. After all callbacks are executed, the LwM2M engine
will send the response as a separate CON message.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Rework the bootstrap DELETE operation, to support deletion of multiple
resources.
Current implementation had several oversimplifications, making it not
spec-compliant:
* DELETE `/` removed only Security object instances (!= 0)
* DELETE `/x` was handled as DELETE `/x/0`, therefore not removing all
of the object instances.
Since the above is only supported during bootstrap and not regular
Device management, this functionality was implemented in the
`bootstrap_delete` function, which now will be called for all DELETE
operations initiated during bootstrap. The regular LwM2M DELETE handler
will only be called during regular Device management, as it has more
strict limitations on what can be deleted.
Additionally, handle empty URI Path option as `/`, therefore indicating
deletion of all resources.
Fixes#29964
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
If networking pre-emptive thread priorities are enabled,
then use the proper macro to enable them.
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Currently, when socket errors occur during receive, the LwM2M engine
restarts the state machine and registers again to the server. While this
works in simple use case (only RD client socket open), it's not a valid
approach when more sockets are open (FW update socket).
Fix this by introducing socket fault callback, which is registered by
the LwM2M engine users. This way, a proper socket owner is notified on
error and can pertake appropriate action.
For RD socket errors the behaviour remains the same - the state machine
is reset and the client registers again to the server. For FW update
socket, handle the error by reopening the socket and retransmitting the
last request. This allows to resume the download from the point the
error occured, w/o a need to start from scratch.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
According to LwM2M specfication v1.0.2, par. 5.3.2, the LwM2M client
MUST send an “Update” operation to the LwM2M Server whenever the
lifetime parameter of the Server object changes the server). The same
applies for the object instances created/deleted. The changes in objects
seem to already be handled, but the lifetime was not.
Additionally, the "Update" message shall only contain these parameters
which changed since the last update (including objects). As it's
straightforward to determine if the liftime changed but it's not easy
to tell if there were updates in the object instances, add an
additional parameter to the engine_trigger_update() function, indicating
that new object information shall be sent in the "Update" message.
Eventually add a proper error checking in `sm_send_registration` as the
function is reworked anyway.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Separate response handling implemented in the engine was faulty. The
separate response was not acknowledged by the client, resulting in
spurious retransmissions from the server side.
Also, the pending CON message was retransmitted by the client even after
it was acknowledged by an empty ACK, but the respnse haven't arrived
yet. Fix this by adding a new `acknowledged` flag to the `lwm2m_message`
structure. Once acknowledged, the flag is set and the confirmable
message is no longer retransmitted. We keep the message on the pending
list in order to timeout properly in case separate response does not
arrive in time.
Finally, prevent the reply callback from being called twice in case
the response is transmitted separately from ACk. The callback should
only be called on the actual reply, not the empty ACK.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
So far this function existed as a static function in LwM2M PULL FOTA
module. Since such functionality will be needed in other places, make it
an internal API function.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Some LWM2M backends/servers, such as emxq, expect the sequence numbers
to begin on 0.
This change is in line with how other lwm2m clients, such as Anjay and
Wakama, starts the notification sequence.
Signed-off-by: Viktor Sjölind <viktor.sjolind@endian.se>
Improve token handling by removing special meaning of tokenlen == 0,
which allows to handle server requests w/o a token (so far such
requests would cause the lwm2m engine to autogenerate token in the
response).
In order to autogenerate token during message initialization, use
special symbol `LWM2M_MSG_TOKEN_GENERATE_NEW`. If no token is wished to
be used, simply set the tokenlen to 0.
Additionally, fix an issue with token autogeneration, where invalid
token len was used (0 instead of 8).
Fixes#28299
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
LwM2M engine did not set response code for the Bootstrap-finish message,
hence it replied with the code copied from the request which is not
correct. Fix this by setting correct code for the Bootstrap-finish
reply.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
"Public Key or Identity" resource is of opaque data type, therefore it's
not correct to assume it will be a NULL terminated string (the existing
servers, for instance Leshan, does not include NULL terminator). Use the
actual size associated with the resource instead.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
So far, the resource instance structure kept only the information about
the buffer length provided to the resource (in the `data_len` field).
While this approach might be enough for integer resources, where the
actual data size is fixed, it did not work for opaque resources. It is
impossible to determine the actual opaque resource length after it's
been written into.
Fix this, by replacing the current `data_len` field of the
`lwm2m_engine_res_inst` with `max_data_len`, indicating the buffer
size, and making the `data_len` field to hold the actual data size of
the resource.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit fixes PUSH FOTA when opaque content-format is used.
This consists of the following fixes:
* Moved `struct block_context` to a private header, so that it can be a
part of `struct lwm2m_input_context`. This allows content decoders to
make use of the block context data.
* Removed faulty `get_length_left` function from the plain text
decoder, and replace it with coap_packet_get_payload() to obtain the
actual payload size.
* Introduce `struct lwm2m_opaque_context` as a part of block context,
which allows to keep track of opaque data download progress.
* Simplify `lwm2m_write_handler_opaque()` function. It will now only
make calls to `engine_get_opaque` - it's the decoder responsibility
to update the opaque context according to it's content format (for
instance TLV decoder should only update it with the actual opaque
data size, not the whole TLV).
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Change so that the caller of lwm2m_init_message is
responsible for generating a message id and remove message id generation
from lwm2m_init_message. Prevents generating a new id when the caller's
intent is to init a message with id 0.
Fixes#28283
Signed-off-by: Pascal Brogle <pascal.brogle@husqvarnagroup.com>
message id 0 and token 0 have special semantics in the lwm2m engine,
they are used to request generation of new id, mark them as such.
Signed-off-by: Pascal Brogle <pascal.brogle@husqvarnagroup.com>
Now that device_api attribute is unmodified at runtime, as well as all
the other attributes, it is possible to switch all device driver
instance to be constant.
A coccinelle rule is used for this:
@r_const_dev_1
disable optional_qualifier
@
@@
-struct device *
+const struct device *
@r_const_dev_2
disable optional_qualifier
@
@@
-struct device * const
+const struct device *
Fixes#27399
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
A proper way to match a Security object instance with a Server object
instance is via Short Server ID resource. Both coupled object instances
should carry the same value of this resource in order to me considered
matched.
This was not implemented in the LwM2M library and it was incorrectly
assumed that the Security object instance index corresponds to the
Server object instance index. While such apporach works is simple
scenario, it might yield incorrect results when bootstrap is used.
Fix this, by verifyng the Short Server ID resource in the Secuirty
instance used, and finding a matching Server instance. The server object
instance is stored for future use in the engine.
Additionally, remove an extra Server object instance that was created
when the bootstrap procedure was used. Since the boostrap Security
object instance does not have the corresponding Server object, it's
enough to have a single Server instance.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Currently, functions for poll sock_fds array management are buggy, in
case there is another socket open (for instance the socket for firmware
update download), it could get overwritten, if the LwM2M socket was
closed and re-opened in a meantime (e. g. on registration timeout).
Fix this, by appending new entries to the sock_fds in continuous manner.
In case of removal, the deleted entry is overwritten by the last one,
and the last one is cleared.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
During FW update, the application expects a consecutive data stream.
Therefore retransmitted blocks shall not be forwarded to the
application, but ignored. In case blocks are received out of order,
return an error and do not handle this block.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
When FW update in PUSH mode is used, the firmware is encapsulated in the
TLV as an opaque data, according to the LMWM2M satandard, and then
sliced into blocks and transferred block by block in several
transactions. Therefore, the TLV header is only present in the initial
message.
Current implementation did not handle this case well, reporting errors
on consecutive blocks, therefore making the FW update in PUSH mode
broken.
This commit fixes this issue with following changes:
* The TLV is only assumed to be present in the initial block, while
consecutive blocks will be processed directly into the appropriate
handler,
* 32-bit variables shall be used whenever dealing with the opaque data
length, since the firmware size can easily exceed the 16-bit range,
* Additional information, required for the FW block transfer to work
properly were added to the block context structure,
* The application shall only be notified of the actual data length, and
not the total block size (the total TLV size including header).
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
During the bootstrap procedure, when Boostrap Finish was received, the
response message was not initialized properly, resulting in a socket
error (NULL pointer porovided) and the response not being sent.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
`addrlen` parameter is updated on each `recvfrom` call, indicating the
actual address length returned. In case both, IPv4 and IPv6 are used on
different sockets (i. e. on regular LWM2M socket and FOTA socket), the
returned address length will differ.
In case `from_addr_len` is not reinitialized on each iteration, the
value stored in the `from_addr_len` variable will eventually indicate
the smaller IPv4 address size, therefore resulting in a failure in a
consecutive call on an IPv6 socket.
Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>