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

net/nanocoap: add generic handling for string-based options #8920

Merged
merged 3 commits into from
Aug 31, 2018

Conversation

haukepetersen
Copy link
Contributor

Contribution description

Many string-based options (e.g. COAP_OPT_URI, COAP_OPT_LOCATION_PATH) share a similar structure: they consist of string 'snippets', that are split using some kind of separation character, typically /. This PR adds a more generic function for setting and reading these kind of options to nanocoap.

Please let me know what you think of this approach - once consensus is reached I will spend the time to add the missing doxygen...

Issues/PRs references

Follow-up on #8772

@haukepetersen haukepetersen added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: network Area: Networking labels Apr 11, 2018
}

/**
* @brief Get the packet's request URI
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is of course copy/paste bla bla, will adjust once the code is approved...

@kaspar030
Copy link
Contributor

ACK for the idea!

@haukepetersen
Copy link
Contributor Author

Cool.

@bergzand bergzand changed the title net/nanocaop: add generic handling for string-based options net/nanocoap: add generic handling for string-based options Apr 11, 2018
@haukepetersen
Copy link
Contributor Author

alright, updated the doxygen accordingly.

@haukepetersen
Copy link
Contributor Author

should be ready for review

Copy link
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minors, feel free to squash after.

* @return -ENOSPC if the complete option does fit into @p target
* @return nr of bytes written to @p target (including '\0')
*/
int coap_get_opt_string(const coap_pkt_t *pkt, uint16_t optnum,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably change to size_t return type for consistency

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ssize_t since error codes are negative?

@@ -504,6 +512,8 @@ size_t coap_put_option_uri(uint8_t *buf, uint16_t lastonum, const char *uri, uin
return bufpos - buf;
}


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...

@kaspar030
Copy link
Contributor

@kb2ma I'm about to ACK, would you like to take a quick look?

Copy link
Member

@bergzand bergzand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as @kaspar030, nothing big, feel free to squash after these too.

@@ -434,7 +494,32 @@ unsigned coap_get_content_type(coap_pkt_t *pkt);
* @returns -ENOSPC if URI option is larger than NANOCOAP_URI_MAX
* @returns nr of bytes written to @p target (including '\0')
*/
int coap_get_uri(coap_pkt_t *pkt, uint8_t *target);
static inline int coap_get_uri(const coap_pkt_t *pkt, uint8_t *target)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If @kaspar030 comment is applied, the return type also propagates to this function.

* @returns -ENOSPC if URI option is larger than @p max_len
* @returns nr of bytes written to @p target (including '\0')
*/
static inline int coap_get_location_path(const coap_pkt_t *pkt,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And to this one

{
coap_optpos_t *optpos = pkt->options;
coap_optpos_t *optpos = (coap_optpos_t *)pkt->options;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you mark *optpos as const you don't need the cast here.

@haukepetersen
Copy link
Contributor Author

Just a remark before I forget it again: somebody would need to go through all of the nanocoap code to check/fix the usage of const for function parameters. In this PR, I only touched the occurrences that were 'in my path'...

Comments look all valid, will address them ASAP

@bergzand
Copy link
Member

There is a typo in the commit message of the second commit "LOCACTION_PATH" -> "LOCATION_PATH".

@kb2ma
Copy link
Member

kb2ma commented Apr 12, 2018

I'm about to ACK, would you like to take a quick look?

Yes, thanks. I'll post my feedback later today.

* @param[in] max_len size of @p target
* @param[in] separator character used for separating the option parts
*
* @return -ENOSPC if the complete option does fit into @p target
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be "does not fit".

@haukepetersen
Copy link
Contributor Author

rebased, squashed, and fixed comments:

  • renamed 'get' function to coap_get_option_string() -> more consistent with coap_put_option_ functions
  • changed return type for coap_get_option_string() and its users to ssize_t
  • make optpos in coap_find_option const
  • fixed some typos in doxygen

@haukepetersen
Copy link
Contributor Author

and fixed the typo in the commit message :-)

@kb2ma
Copy link
Member

kb2ma commented Apr 13, 2018

I'm going to put my review here to keep it all together, rather than put some of it in the code.

coap_put_option_location_path() -- shouldn't this be coap_put_option_location() to include Location-Path and Location-Query? This approach would be consistent with coap_put_option_uri(), which includes Uri-Path and Uri-Query.

I have a couple of higher level concerns. Why do coap_[get|put]_option_string() require the separator as an argument? Isn't this implicit in the option number argument? For example, Uri-Path always uses '/', and Uri-Query uses '&' except for the initial '?'.

What about options with an opaque data type, like ETag? WIll this require a coap_[get|put]_option_buf()? Why not roll up string and opaque options into a single function? Once again, the option number defines the behavior.

I think the fundamental API is:

  • coap_opt_get_buf(pkt, optnum, uint8_t *target, max_len)
  • coap_opt_put_buf(buf, lastonum, optnum, target, uint8_t *source, source_len)
  • coap_opt_get_uint(pkt, optnum, uint32_t *target)
  • coap_opt_put_uint(buf, lastonum, optnum, value)

Any other option-specific functions likely are inline on top of those.

gcoap then simplifies the put options by removing the requirement to specify them in order, as shown in #8831.

@kaspar030
Copy link
Contributor

Why not roll up string and opaque options into a single function?

Isn't the difficulty with string functions that one e.g, path is split into multiple occurences of the option?

@kb2ma
Copy link
Member

kb2ma commented Apr 17, 2018

I have been experimenting with the adaptation of gcoap with the API I described above. The problem with this approach is that it means nanocoap would need to maintain lookup tables for the configuration of an option. Examples -- is it repeatable, what is the separator character, how to match the option number to a position in the table.

This approach would allow nanocoap to validate options more carefully. However, I think this work is two steps away from where we are today. The next step is just to get options working based on #8772. So, I agree that the API needs functions to get/set string values. If/when we get to option definitions, the string functions can be deprecated.

So how about this for an updated API. I do think the use of 'coap_opt' for the prefix improves usability, as @kaspar030 suggested.

coap_opt_get_string(pkt, optnum, uint8_t *target, max_len, separator)
coap_opt_put_string(buf, lastonum, optnum, char *source, separator)
coap_opt_get_buf(pkt, optnum, uint8_t *target, max_len)
coap_opt_put_buf(buf, lastonum, optnum, target, uint8_t *source, source_len)
coap_opt_get_uint(pkt, optnum, uint32_t *target)
coap_opt_put_uint(buf, lastonum, optnum, value)

@haukepetersen
Copy link
Contributor Author

coap_put_option_location_path() -- shouldn't this be coap_put_option_location()

yes, that's better indeed. Will fix.

I have a couple of higher level concerns. Why do coap_[get|put]_option_string() require the separator as an argument? Isn't this implicit in the option number argument? For example, Uri-Path always uses '/', and Uri-Query uses '&' except for the initial '?'.

As you stated below, making this explicit depending on the option number implies that we need to keep some kind of a lookup table to map the behavior. This is IMHO overkill (especially considering nanocaop's scope to be as lightweight as possible). Further, the separator character in the string representation is something specific chosen by the nanocoap user, and is not really for making the string nice to read for humans, so there is IMHO no need for having e.g. a query string start with ? instead of starting it also with an &...

So how about this for an updated API.

I like it. I will adapt the functions touched by this PR and propose that we open an issue for adapting the rest of the option handling functions in separate PR(s). How does that sound?

@kaspar030
Copy link
Contributor

So how about this for an updated API.

Thinking about this:

coap_opt_get_string(pkt, optnum, uint8_t *target, max_len, separator)
coap_opt_put_string(buf, lastonum, optnum, char *source, separator)

... the get functions get a packet, the put functions a buffer.
@kb2ma intends to add higher level "put" type functions that work on a pkt, into gcoap. IMO, those can actually reside in nanocoap.

I propose using coap_opt_put_<type>_raw() for the put functions that write directly into a buffer, then introduce higher-level functions without _raw as described in #8831.

@haukepetersen
Copy link
Contributor Author

Thanks @kb2ma! Now I start to remember/understand what the option handling concept was all about :-) I agree with your proposed changes and merged them in, will do one more verification round on my side now and then I hope this PR should be ready to go.

@kb2ma
Copy link
Member

kb2ma commented Aug 23, 2018

Excellent! Since you're working with Uri-Query options, remember that coap_parse() currently does not set the coap_pkt_t.qs attribute for gcoap. I'll watch for your OK for final review.

@haukepetersen
Copy link
Contributor Author

alright, fixed one more alignment issue and did some (successful) testing. Also cleaned up the commits and squashed. On my part this PR should be ready for final review!

Copy link
Member

@kb2ma kb2ma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, please take a look at sys/net/application_layer/nanocoap/sock.c. It uses the obsolete coap_put_option_uri(). One more minor issue, the commit comment includes the word 'genering' :-)

}

/**
* @brief Convenience function for getting the packet's LOCATION_PATH option
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be LOCATION_QUERY

@@ -296,7 +304,7 @@ ssize_t coap_handle_req(coap_pkt_t *pkt, uint8_t *resp_buf, unsigned resp_buf_le
uint8_t *uri = pkt->url;
#else
uint8_t uri[NANOCOAP_URI_MAX];
if (coap_get_uri(pkt, uri) <= 0) {
if (coap_get_uri_query(pkt, uri) <= 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be coap_get_uri_path()

@kb2ma
Copy link
Member

kb2ma commented Aug 28, 2018

Tested OK on native and samr21-xpro, with the code updates in my review. Test included use of rdcli-simple example to register with libcoap coap-rd server. Good stuff!

@haukepetersen haukepetersen force-pushed the add_nanocaop_urilocationoption branch 2 times, most recently from 90fab04 to 2cc095d Compare August 29, 2018 11:05
@haukepetersen
Copy link
Contributor Author

addressed comments and squashed. Thanks for the testing!

@haukepetersen haukepetersen added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Aug 29, 2018
@haukepetersen
Copy link
Contributor Author

@kaspar030, @bergzand: are your change requests satisfies as well?

@kb2ma
Copy link
Member

kb2ma commented Aug 29, 2018

Still don't see the fix to sock.c and Murdock is unhappy with documentation.

@haukepetersen
Copy link
Contributor Author

you are right, I missed that one

- add generic string put and get functions
- add location path and location query options
- add dedicated functions for getting and setting
  URI query, URI path, location query, and location path
  options
@haukepetersen
Copy link
Contributor Author

ok, should be fixed now.

@kb2ma
Copy link
Member

kb2ma commented Aug 30, 2018

Looks good to me! Since you've got an open question out there, I'll leave it to you to merge when ready.

@haukepetersen
Copy link
Contributor Author

Lets wait for the other two to approve or dismiss their review -> @kaspar030, @bergzand

@bergzand
Copy link
Member

I'll try to take a look at this PR today to see if I can spot any remaining issues.

Copy link
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@bergzand bergzand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK

@bergzand bergzand merged commit e8dfabd into RIOT-OS:master Aug 31, 2018
@haukepetersen
Copy link
Contributor Author

awesome, thanks guys!

-> let's go!

@haukepetersen
Copy link
Contributor Author

dammit, 10 seconds too late :-)

@haukepetersen haukepetersen deleted the add_nanocaop_urilocationoption branch August 31, 2018 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: CoAP Area: Constrained Application Protocol implementations Area: network Area: Networking CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants