From d4c9a7d80c60a90da1051342d8b8d81f581bd27e Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Mon, 13 Feb 2017 07:39:34 +0530 Subject: [PATCH 01/20] net: remove obsolete CONFIG_NET_YAIP Change-Id: Ie8ef79e7d7a6f229af3771b7786af3db89c5e458 Signed-off-by: Anas Nashif --- samples/net/leds_demo/prj_802154.conf | 1 - samples/net/zoap_server/prj_cc2520.conf | 1 - samples/net/zperf/prj_frdm_k64f_prof.conf | 1 - samples/net/zperf/prj_qemu_x86.conf | 1 - 4 files changed, 4 deletions(-) diff --git a/samples/net/leds_demo/prj_802154.conf b/samples/net/leds_demo/prj_802154.conf index 1efd33265ca..63080d3d705 100644 --- a/samples/net/leds_demo/prj_802154.conf +++ b/samples/net/leds_demo/prj_802154.conf @@ -6,7 +6,6 @@ CONFIG_NET_L2_IEEE802154_ORFD_CHANNEL=20 CONFIG_NET_L2_IEEE802154_FRAGMENT=y CONFIG_NET_LOG=y CONFIG_NET_UDP=y -CONFIG_NET_YAIP=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_IEEE802154_CC2520=y CONFIG_ZOAP=y diff --git a/samples/net/zoap_server/prj_cc2520.conf b/samples/net/zoap_server/prj_cc2520.conf index 934a1a5980a..b73aa209224 100644 --- a/samples/net/zoap_server/prj_cc2520.conf +++ b/samples/net/zoap_server/prj_cc2520.conf @@ -6,7 +6,6 @@ CONFIG_NET_L2_IEEE802154_ORFD_CHANNEL=20 CONFIG_NET_L2_IEEE802154_FRAGMENT=y CONFIG_NET_LOG=y CONFIG_NET_UDP=y -CONFIG_NET_YAIP=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_IEEE802154_CC2520=y CONFIG_ZOAP=y diff --git a/samples/net/zperf/prj_frdm_k64f_prof.conf b/samples/net/zperf/prj_frdm_k64f_prof.conf index edf0dd1a7c5..f9229eed732 100644 --- a/samples/net/zperf/prj_frdm_k64f_prof.conf +++ b/samples/net/zperf/prj_frdm_k64f_prof.conf @@ -3,7 +3,6 @@ CONFIG_NET_LOG=y CONFIG_NET_IPV6=y CONFIG_NET_IPV4=y CONFIG_NET_DHCPV4=y -CONFIG_NET_YAIP=y CONFIG_NET_UDP=y CONFIG_NET_TCP=y CONFIG_NET_STATISTICS=y diff --git a/samples/net/zperf/prj_qemu_x86.conf b/samples/net/zperf/prj_qemu_x86.conf index b9044b21904..5924af03ef0 100644 --- a/samples/net/zperf/prj_qemu_x86.conf +++ b/samples/net/zperf/prj_qemu_x86.conf @@ -3,7 +3,6 @@ CONFIG_NET_LOG=y CONFIG_NET_IPV6=y CONFIG_NET_IPV4=y CONFIG_NET_DHCPV4=n -CONFIG_NET_YAIP=y CONFIG_NET_UDP=y CONFIG_NET_TCP=n CONFIG_NET_STATISTICS=y From 0c94d6a0856f16a0f8899729e534f0566233d665 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Wed, 1 Feb 2017 16:38:35 -0800 Subject: [PATCH 02/20] iot/zoap: Improve zoap.h documentation Now types and functions have better explanations of their usage and parameters associated. Jira: ZEP-1657 Change-Id: I146688324080ac3cf0876f1db3c92c9514e1303d Signed-off-by: Vinicius Costa Gomes --- include/net/zoap.h | 419 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 333 insertions(+), 86 deletions(-) diff --git a/include/net/zoap.h b/include/net/zoap.h index b035d4c8392..a1d9a346a57 100644 --- a/include/net/zoap.h +++ b/include/net/zoap.h @@ -147,16 +147,18 @@ struct zoap_reply; struct zoap_resource; /** - * Type of the callback being called when a resource's method is invoked by - * remote entity. + * @typedef zoap_method_t + * @brief Type of the callback being called when a resource's method is + * invoked by the remote entity. */ typedef int (*zoap_method_t)(struct zoap_resource *resource, struct zoap_packet *request, const struct sockaddr *from); /** - * Type of the callback being called when a resource's has observers to be - * informed when an update happens. + * @typedef zoap_notify_t + * @brief Type of the callback being called when a resource's has observers + * to be informed when an update happens. */ typedef void (*zoap_notify_t)(struct zoap_resource *resource, struct zoap_observer *observer); @@ -168,6 +170,7 @@ typedef void (*zoap_notify_t)(struct zoap_resource *resource, * them, by fetching their state or requesting updates to them. */ struct zoap_resource { + /** Which function to be called for each CoAP method */ zoap_method_t get, post, put, del; zoap_notify_t notify; const char * const *path; @@ -177,7 +180,7 @@ struct zoap_resource { }; /** - * Represents a remote device that is observing a local resource. + * @brief Represents a remote device that is observing a local resource. */ struct zoap_observer { sys_snode_t list; @@ -187,7 +190,7 @@ struct zoap_observer { }; /** - * Representation of a CoAP packet. + * @brief Representation of a CoAP packet. */ struct zoap_packet { struct net_buf *buf; @@ -196,7 +199,8 @@ struct zoap_packet { }; /** - * Helper function to be called when a response matches the + * @typedef zoap_reply_t + * @brief Helper function to be called when a response matches the * a pending request. */ typedef int (*zoap_reply_t)(const struct zoap_packet *response, @@ -204,7 +208,7 @@ typedef int (*zoap_reply_t)(const struct zoap_packet *response, const struct sockaddr *from); /** - * Represents a request awaiting for an acknowledgment (ACK). + * @brief Represents a request awaiting for an acknowledgment (ACK). */ struct zoap_pending { struct zoap_packet request; @@ -212,8 +216,8 @@ struct zoap_pending { }; /** - * Represents the handler for the reply of a request, it is also used when - * observing resources. + * @brief Represents the handler for the reply of a request, it is + * also used when observing resources. */ struct zoap_reply { zoap_reply_t reply; @@ -224,48 +228,76 @@ struct zoap_reply { }; /** - * Indicates that the remote device referenced by @a addr, with @a request, - * wants to observe a resource. + * @brief Indicates that the remote device referenced by @a addr, with + * @a request, wants to observe a resource. + * + * @param observer Observer to be initialized + * @param request Request on which the observer will be based + * @param addr Address of the remote device */ void zoap_observer_init(struct zoap_observer *observer, const struct zoap_packet *request, const struct sockaddr *addr); /** - * After the observer is initialized, associate the observer with an resource. - * Returns whether this is the first observer added to this resource. + * @brief After the observer is initialized, associate the observer + * with an resource. + * + * @param resource Resource to add an observer + * @param observer Observer to be added + * + * @return true if this is the first observer added to this resource. */ bool zoap_register_observer(struct zoap_resource *resource, struct zoap_observer *observer); /** - * Remove this observer from the list of registered observers of - * that resource. + * @brief Remove this observer from the list of registered observers + * of that resource. + * + * @param resource Resource in which to remove the observer + * @param observer Observer to be removed */ void zoap_remove_observer(struct zoap_resource *resource, struct zoap_observer *observer); /** - * Returns the observer that matches address @a addr. + * @brief Returns the observer that matches address @a addr. + * + * @param observers Pointer to the array of observers + * @param len Size of the array of observers + * @param addr Address of the endpoint observing a resource + * + * @return A pointer to a observer if a match is found, NULL + * otherwise. */ struct zoap_observer *zoap_find_observer_by_addr( struct zoap_observer *observers, size_t len, const struct sockaddr *addr); /** - * Returns the next available observer representation. + * @brief Returns the next available observer representation. + * + * @param observers Pointer to the array of observers + * @param len Size of the array of observers + * + * @return A pointer to a observer if there's an available observer, + * NULL otherwise. */ struct zoap_observer *zoap_observer_next_unused( struct zoap_observer *observers, size_t len); /** - * Indicates that a reply is expected for @a request. + * @brief Indicates that a reply is expected for @a request. + * + * @param reply Reply structure to be initialized + * @param request Request from which @a reply will be based */ void zoap_reply_init(struct zoap_reply *reply, const struct zoap_packet *request); /** - * Represents the value of a CoAP option. + * @brief Represents the value of a CoAP option. * * To be used with zoap_find_options(). */ @@ -275,51 +307,97 @@ struct zoap_option { }; /** - * Parses the CoAP packet in @a buf, validating it and initializing @a pkt. - * @a buf must remain valid while @a pkt is used. Used when receiving packets. + * @brief Parses the CoAP packet in @a buf, validating it and + * initializing @a pkt. @a buf must remain valid while @a pkt is used. + * + * @param pkt Packet to be initialized from received @a buf. + * @param buf Buffer containing a CoAP packet, its @a data pointer is + * positioned on the start of the CoAP packet. + * + * @return 0 in case of success or negative in case of error. */ int zoap_packet_parse(struct zoap_packet *pkt, struct net_buf *buf); /** - * Creates a new CoAP packet from a net_buf. @a buf must remain valid while - * @a pkt is used. Used when creating packets to be sent. + * @brief Creates a new CoAP packet from a net_buf. @a buf must remain + * valid while @a pkt is used. + * + * @param pkt New packet to be initialized using the storage from @a + * buf. + * @param buf Buffer that will contain a CoAP packet + * + * @return 0 in case of success or negative in case of error. */ int zoap_packet_init(struct zoap_packet *pkt, struct net_buf *buf); /** - * Initialize a pending request with a request. The request's fields are - * copied into the pending struct, so @a request doesn't have to live for as - * long as the pending struct lives, but net_buf needs to live for at least - * that long. + * @brief Initialize a pending request with a request. + * + * The request's fields are copied into the pending struct, so @a + * request doesn't have to live for as long as the pending struct + * lives, but net_buf needs to live for at least that long. + * + * @param pending Structure representing the waiting for a + * confirmation message, initialized with data from @a request + * @param request Message waiting for confirmation + * + * @return 0 in case of success or negative in case of error. */ int zoap_pending_init(struct zoap_pending *pending, const struct zoap_packet *request); /** - * Returns the next available pending struct, that can be used to track - * the retransmission status of a request. + * @brief Returns the next available pending struct, that can be used + * to track the retransmission status of a request. + * + * @param pendings Pointer to the array of #zoap_pending structures + * @param len Size of the array of #zoap_pending structures + * + * @return pointer to a free #zoap_pending structure, NULL in case + * none could be found. */ struct zoap_pending *zoap_pending_next_unused( struct zoap_pending *pendings, size_t len); /** - * Returns the next available reply struct, so it can be used to track replies - * and notifications received. + * @brief Returns the next available reply struct, so it can be used + * to track replies and notifications received. + * + * @param replies Pointer to the array of #zoap_reply structures + * @param len Size of the array of #zoap_reply structures + * + * @return pointer to a free #zoap_reply structure, NULL in case + * none could be found. */ struct zoap_reply *zoap_reply_next_unused( struct zoap_reply *replies, size_t len); /** - * After a response is received, clear all pending retransmissions related to - * that response. + * @brief After a response is received, clear all pending + * retransmissions related to that response. + * + * @param response The received response + * @param pendings Pointer to the array of #zoap_reply structures + * @param len Size of the array of #zoap_reply structures + * + * @return pointer to the associated #zoap_pending structure, NULL in + * case none could be found. */ struct zoap_pending *zoap_pending_received( const struct zoap_packet *response, struct zoap_pending *pendings, size_t len); /** - * After a response is received, clear all pending retransmissions related to - * that response. + * @brief After a response is received, clear all pending + * retransmissions related to that response. + * + * @param response A response received + * @param from Address from which the response was received + * @param replies Pointer to the array of #zoap_reply structures + * @param len Size of the array of #zoap_reply structures + * + * @return Pointer to the reply matching the packet received, NULL if + * none could be found. */ struct zoap_reply *zoap_response_received( const struct zoap_packet *response, @@ -327,91 +405,170 @@ struct zoap_reply *zoap_response_received( struct zoap_reply *replies, size_t len); /** - * Returns the next pending about to expire, pending->timeout informs how many - * ms to next expiration. + * @brief Returns the next pending about to expire, pending->timeout + * informs how many ms to next expiration. + * + * @param pendings Pointer to the array of #zoap_pending structures + * @param len Size of the array of #zoap_pending structures + * + * @return The next #zoap_pending to expire, NULL if none is about to + * expire. */ struct zoap_pending *zoap_pending_next_to_expire( struct zoap_pending *pendings, size_t len); /** - * After a request is sent, user may want to cycle the pending retransmission - * so the timeout is updated. Returns false if this is the last - * retransmission. + * @brief After a request is sent, user may want to cycle the pending + * retransmission so the timeout is updated. + * + * @param pending Pending representation to have its timeout updated + * + * @return false if this is the last retransmission. */ bool zoap_pending_cycle(struct zoap_pending *pending); /** - * Cancels the pending retransmission, so it again becomes available. + * @brief Cancels the pending retransmission, so it again becomes + * available. + * + * @param pending Pending representation to be canceled */ void zoap_pending_clear(struct zoap_pending *pending); /** - * Cancels awaiting for this reply, so it becomes available again. + * @brief Cancels awaiting for this reply, so it becomes available + * again. + * + * @param reply The reply to be cancelled */ void zoap_reply_clear(struct zoap_reply *reply); /** - * When a request is received, call the appropriate methods of the - * matching resources. + * @brief When a request is received, call the appropriate methods of + * the matching resources. + * + * @param pkt Packet received + * @param resources Array of known resources + * @param from Address from which the packet was received + * + * @return 0 in case of success or negative in case of error. */ int zoap_handle_request(struct zoap_packet *pkt, struct zoap_resource *resources, const struct sockaddr *from); /** - * Indicates that this resource was updated and that the @a notify callback - * should be called for every registered observer. + * @brief Indicates that this resource was updated and that the @a + * notify callback should be called for every registered observer. + * + * @param resource Resource that was updated + * + * @return 0 in case of success or negative in case of error. */ int zoap_resource_notify(struct zoap_resource *resource); /** - * Returns if this request is enabling observing a resource. + * @brief Returns if this request is enabling observing a resource. + * + * @param request Request to be checked + * + * @return True if the request is enabling observing a resource, False + * otherwise */ bool zoap_request_is_observe(const struct zoap_packet *request); /** - * Returns a pointer to the start of the payload, and how much memory - * is available (to the payload), it will also insert the - * COAP_MARKER (0xFF). When the payload is already set, for example, - * for incoming packets, it will return how many bytes the payload - * occupies. + * @brief Returns a pointer to the start of the payload and its size + * + * It will insert the COAP_MARKER (0xFF), if its not set, and return the + * available size for the payload. + * + * @param pkt Packet to get (or insert) the payload + * @param len Amount of space for the payload + * + * @return pointer to the start of the payload, NULL in case of error. */ uint8_t *zoap_packet_get_payload(struct zoap_packet *pkt, uint16_t *len); /** - * Returns the internal buffer of the CoAP packet, appending the - * COAP_MARKER to the buffer if necessary. + * @brief Returns the internal buffer of the CoAP packet, appending + * the COAP_MARKER to the buffer if necessary. + * + * @param pkt Packet to get (or insert) the payload + * + * @return pointer to the net_buf storing the payload. */ struct net_buf *zoap_packet_get_buf(struct zoap_packet *pkt); /** - * Sets how much space was used by the payload. + * @brief Sets how much space was used by the payload. + * + * Used for outgoing packets, after zoap_packet_get_payload(), to + * update the internal representation with the amount of data that was + * added to the packet. + * + * @param pkt Packet to be updated + * @param len Amount of data that was added to the payload + * + * @return 0 in case of success or negative in case of error. */ int zoap_packet_set_used(struct zoap_packet *pkt, uint16_t len); /** - * Adds an option to the packet. Note that options must be added - * in numeric order of their codes. + * @brief Adds an option to the packet. + * + * Note: ptions must be added in numeric order of their codes. + * + * @param pkt Packet to be updated + * @param code Option code to add to the packet, see #zoap_option_num + * @param value Pointer to the value of the option, will be copied to the packet + * @param len Size of the data to be added + * + * @return 0 in case of success or negative in case of error. */ int zoap_add_option(struct zoap_packet *pkt, uint16_t code, const void *value, uint16_t len); /** - * Converts an option to its integer representation. It assumes that - * the number is encoded in the network byte order in the option. + * @brief Converts an option to its integer representation. + * + * Assumes that the number is encoded in the network byte order in the + * option. + * + * @param option Pointer to the option value, retrieved by + * zoap_find_options() + * + * @return The integer representation of the option */ unsigned int zoap_option_value_to_int(const struct zoap_option *option); /** - * Adds an integer value option to the packet. The option must be - * added in numeric order of their codes, and the least amount of - * bytes will be used to encode the value. + * @brief Adds an integer value option to the packet. + * + * The option must be added in numeric order of their codes, and the + * least amount of bytes will be used to encode the value. + * + * @param pkt Packet to be updated + * @param code Option code to add to the packet, see #zoap_option_num + * @param val Integer value to be added + * + * @return 0 in case of success or negative in case of error. */ int zoap_add_option_int(struct zoap_packet *pkt, uint16_t code, unsigned int val); /** - * Return the values associated with the option of value @a code. + * @brief Return the values associated with the option of value @a + * code. + * + * @param pkt CoAP packet representation + * @param code Option number to look for + * @param options Array of #zoap_option where to store the value + * of the options found + * @param veclen Number of elements in the options array + * + * @return The number of options found in packet matching code, + * negative on error. */ int zoap_find_options(const struct zoap_packet *pkt, uint16_t code, struct zoap_option *options, uint16_t veclen); @@ -435,7 +592,12 @@ enum zoap_block_size { }; /** - * Helper for converting the enumeration to the size expressed in bytes. + * @brief Helper for converting the enumeration to the size expressed + * in bytes. + * + * @param block_size The block size to be converted + * + * @return The size in bytes that the block_size represents */ static inline uint16_t zoap_block_size_to_bytes( enum zoap_block_size block_size) @@ -444,7 +606,7 @@ static inline uint16_t zoap_block_size_to_bytes( } /** - * Represents the current state of a block-wise transaction. + * @brief Represents the current state of a block-wise transaction. */ struct zoap_block_context { size_t total_size; @@ -453,103 +615,186 @@ struct zoap_block_context { }; /** - * Initializes the context of a block-wise transfer. + * @brief Initializes the context of a block-wise transfer. + * + * @param ctx The context to be initialized + * @param block_size The size of the block + * @param total_size The total size of the transfer, if known + * + * @return 0 in case of success or negative in case of error. */ int zoap_block_transfer_init(struct zoap_block_context *ctx, enum zoap_block_size block_size, size_t total_size); /** - * Add BLOCK1 option to the packet. + * @brief Add BLOCK1 option to the packet. + * + * @param pkt Packet to be updated + * @param ctx Block context from which to retrieve the + * information for the Block1 option + * + * @return 0 in case of success or negative in case of error. */ int zoap_add_block1_option(struct zoap_packet *pkt, struct zoap_block_context *ctx); /** - * Add BLOCK2 option to the packet. + * @brief Add BLOCK2 option to the packet. + * + * @param pkt Packet to be updated + * @param ctx Block context from which to retrieve the + * information for the Block2 option + * + * @return 0 in case of success or negative in case of error. */ int zoap_add_block2_option(struct zoap_packet *pkt, struct zoap_block_context *ctx); /** - * Add SIZE1 option to the packet. + * @brief Add SIZE1 option to the packet. + * + * @param pkt Packet to be updated + * @param ctx Block context from which to retrieve the + * information for the Size1 option + * + * @return 0 in case of success or negative in case of error. */ int zoap_add_size1_option(struct zoap_packet *pkt, struct zoap_block_context *ctx); /** - * Add SIZE2 option to the packet. + * @brief Add SIZE2 option to the packet. + * + * @param pkt Packet to be updated + * @param ctx Block context from which to retrieve the + * information for the Size2 option + * + * @return 0 in case of success or negative in case of error. */ int zoap_add_size2_option(struct zoap_packet *pkt, struct zoap_block_context *ctx); /** - * Retrieves BLOCK{1,2} and SIZE{1,2} from @a pkt and updates + * @brief Retrieves BLOCK{1,2} and SIZE{1,2} from @a pkt and updates * @a ctx accordingly. * - * Returns an error if the packet contains invalid options. + * @param pkt Packet in which to look for block-wise transfers options + * @param ctx Block context to be updated + * + * @return 0 in case of success or negative in case of error. */ int zoap_update_from_block(struct zoap_packet *pkt, struct zoap_block_context *ctx); + /** - * Updates @a ctx so after this is called the current entry + * @brief Updates @a ctx so after this is called the current entry * indicates the correct offset in the body of data being * transferred. + * + * @param ctx Block context to be updated + * + * @return The offset in the block-wise transfer, 0 if the transfer + * has finished. */ size_t zoap_next_block(struct zoap_block_context *ctx); /** - * Returns the version present in a CoAP packet. + * @brief Returns the version present in a CoAP packet. + * + * @param pkt CoAP packet representation + * + * @return the CoAP version in packet */ uint8_t zoap_header_get_version(const struct zoap_packet *pkt); /** - * Returns the type of the packet present in the CoAP packet. + * @brief Returns the type of the CoAP packet. + * + * @param pkt CoAP packet representation + * + * @return the type of the packet */ uint8_t zoap_header_get_type(const struct zoap_packet *pkt); /** - * Returns the token associated with a CoAP packet. + * @brief Returns the token (if any) in the CoAP packet. + * + * @param pkt CoAP packet representation + * @param len Where to store the length of the token + * + * @return pointer to the start of the token in the CoAP packet. */ const uint8_t *zoap_header_get_token(const struct zoap_packet *pkt, uint8_t *len); /** - * Returns the code present in the header of a CoAP packet. + * @brief Returns the code of the CoAP packet. + * + * @param pkt CoAP packet representation + * + * @return the code present in the packet */ uint8_t zoap_header_get_code(const struct zoap_packet *pkt); /** - * Returns the message id associated with a CoAP packet. + * @brief Returns the message id associated with the CoAP packet. + * + * @param pkt CoAP packet representation + * + * @return the message id present in the packet */ uint16_t zoap_header_get_id(const struct zoap_packet *pkt); /** - * Sets the CoAP version present in the CoAP header of a packet. + * @brief Sets the version of the CoAP packet. + * + * @param pkt CoAP packet representation + * @param ver The CoAP version to set in the packet */ void zoap_header_set_version(struct zoap_packet *pkt, uint8_t ver); /** - * Sets the type of a CoAP message. + * @brief Sets the type of the CoAP packet. + * + * @param pkt CoAP packet representation + * @param type The packet type to set */ void zoap_header_set_type(struct zoap_packet *pkt, uint8_t type); /** - * Sets the token present in the CoAP header of a packet. + * @brief Sets the token in the CoAP packet. + * + * @param pkt CoAP packet representation + * @param token Token to set in the packet, will be copied + * @param tokenlen Size of the token to be set, 8 bytes maximum + * + * @return 0 in case of success or negative in case of error. */ int zoap_header_set_token(struct zoap_packet *pkt, const uint8_t *token, uint8_t tokenlen); /** - * Sets the code present in the header of a CoAP packet. + * @brief Sets the code present in the CoAP packet. + * + * @param pkt CoAP packet representation + * @param code The code set in the packet */ void zoap_header_set_code(struct zoap_packet *pkt, uint8_t code); /** - * Sets the message id associated with a CoAP packet. + * @brief Sets the message id present in the CoAP packet. + * + * @param pkt CoAP packet representation + * @param id The message id to set in the packet */ void zoap_header_set_id(struct zoap_packet *pkt, uint16_t id); +/** + * @brief Helper to generate message ids + * + * @return a new message id + */ static inline uint16_t zoap_next_id(void) { static uint16_t message_id; @@ -558,8 +803,10 @@ static inline uint16_t zoap_next_id(void) } /** - * Returns a randomly generated array of 8 bytes, that can be used as a - * message's token. + * @brief Returns a randomly generated array of 8 bytes, that can be + * used as a message's token. + * + * @return a 8-byte pseudo-random token. */ uint8_t *zoap_next_token(void); From 62a6c9c6d045b8a244dff345d550e570021f2126 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 9 Feb 2017 16:27:01 -0800 Subject: [PATCH 03/20] samples/zoap-server: Update docs with information about libcoap Add information about how to run libcoap's[1] implementation of the ETSI testcases against zoap-server. Jira: ZEP-1538 [1] https://github.com/obgm/libcoap (branch develop) Change-Id: I6aa5989575cc15630371aa0761bee98fb6fe1b80 Signed-off-by: Vinicius Costa Gomes --- samples/net/zoap_server/README.rst | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/samples/net/zoap_server/README.rst b/samples/net/zoap_server/README.rst index 562b777de17..d4ab9ce6e91 100644 --- a/samples/net/zoap_server/README.rst +++ b/samples/net/zoap_server/README.rst @@ -12,15 +12,20 @@ some adjustments to the configuration may be needed. The sample will listen for requests in the CoAP UDP port (5683) in the site-local IPv6 multicast address reserved for CoAP nodes. -The exported resource, with path '/test', will just respond any GET to -that path with the the type, code and message identification retrieved -from the request. The response will have this format: +The sample exports the following resources: .. code-block:: none - Type: - Code: - MID: + /test + /seg1/seg2/seg3 + /query + /separate + /large + /location-query + /large-update + +These resources allow a good part of the ETSI testcases to be run +against zoap-server. Building And Running ******************** @@ -37,6 +42,14 @@ It can be built and executed on QEMU as follows: make run + +Use this command on the host to run the`libcoap`_ implementation of +the ETSI testcases: + +.. code-block:: console + + sudo ./examples/etsi_coaptest.sh -i tap0 2001:db8::1 + To build the version supporting the TI CC2520 radio, use the supplied configuration file enabling IEEE 802.15.4: @@ -44,4 +57,7 @@ configuration file enabling IEEE 802.15.4: make CONF_FILE=prj_cc2520.conf run + .. _`net-tools`: https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=tree + +.. _`libcoap`: https://github.com/obgm/libcoap From e190ffe200b0d19daba98aebf57f87e58ec0ae65 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 9 Feb 2017 10:53:26 -0800 Subject: [PATCH 04/20] iot/zoap: Fix handling of 16-bytes block-wise transfers This fixes the case that a request for block number (NUM) 0, using a 16 byte block was considered invalid. This was because it is encoded as the value 0 (zero), which can be expressed as the BLOCK1 option present but without any value associated. The old code considered this the same as the option not existing. Change-Id: I0f3912803a88865e9f544a6d0078ed4231775a88 Signed-off-by: Vinicius Costa Gomes --- subsys/net/lib/zoap/zoap.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/subsys/net/lib/zoap/zoap.c b/subsys/net/lib/zoap/zoap.c index 6ff02b2f85f..94dab4a7c36 100644 --- a/subsys/net/lib/zoap/zoap.c +++ b/subsys/net/lib/zoap/zoap.c @@ -1210,15 +1210,16 @@ struct block_transfer { bool more; }; -static unsigned int get_block_option(struct zoap_packet *pkt, uint16_t code) +static int get_block_option(struct zoap_packet *pkt, uint16_t code) { struct zoap_option option; unsigned int val; int count = 1; count = zoap_find_options(pkt, code, &option, count); - if (count <= 0) - return 0; + if (count <= 0) { + return -ENOENT; + } val = zoap_option_value_to_int(&option); @@ -1230,15 +1231,15 @@ static int update_descriptive_block(struct zoap_block_context *ctx, { size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4); - if (block == 0) { - return -ENOENT; + if (block == -ENOENT) { + return 0; } if (size && ctx->total_size && ctx->total_size != size) { return -EINVAL; } - if (ctx->block_size > 0 && GET_BLOCK_SIZE(block) > ctx->block_size) { + if (ctx->current > 0 && GET_BLOCK_SIZE(block) > ctx->block_size) { return -EINVAL; } @@ -1250,7 +1251,7 @@ static int update_descriptive_block(struct zoap_block_context *ctx, ctx->total_size = size; } ctx->current = new_current; - ctx->block_size = GET_BLOCK_SIZE(block); + ctx->block_size = min(GET_BLOCK_SIZE(block), ctx->block_size); return 0; } @@ -1260,7 +1261,7 @@ static int update_control_block1(struct zoap_block_context *ctx, { size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4); - if (block == 0) { + if (block == -ENOENT) { return 0; } @@ -1283,7 +1284,7 @@ static int update_control_block2(struct zoap_block_context *ctx, { size_t new_current = GET_NUM(block) << (GET_BLOCK_SIZE(block) + 4); - if (block == 0) { + if (block == -ENOENT) { return 0; } @@ -1296,8 +1297,7 @@ static int update_control_block2(struct zoap_block_context *ctx, } ctx->current = new_current; - ctx->block_size = GET_BLOCK_SIZE(block); - ctx->total_size = size; + ctx->block_size = min(GET_BLOCK_SIZE(block), ctx->block_size); return 0; } @@ -1305,14 +1305,16 @@ static int update_control_block2(struct zoap_block_context *ctx, int zoap_update_from_block(struct zoap_packet *pkt, struct zoap_block_context *ctx) { - unsigned int block1, block2, size1, size2; - int r; + int r, block1, block2, size1, size2; block1 = get_block_option(pkt, ZOAP_OPTION_BLOCK1); block2 = get_block_option(pkt, ZOAP_OPTION_BLOCK2); size1 = get_block_option(pkt, ZOAP_OPTION_SIZE1); size2 = get_block_option(pkt, ZOAP_OPTION_SIZE2); + size1 = size1 == -ENOENT ? 0 : size1; + size2 = size2 == -ENOENT ? 0 : size2; + if (is_request(pkt)) { r = update_control_block2(ctx, block2, size2); if (r) { From b032f54f601e6e051a091509f631597e39a35168 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 9 Feb 2017 16:43:42 -0800 Subject: [PATCH 05/20] iot/zoap: Fix header indentation Change-Id: Iea2dd0f2493e240caa33f81fa68e5be894f0de86 Signed-off-by: Vinicius Costa Gomes --- include/net/zoap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/zoap.h b/include/net/zoap.h index a1d9a346a57..9151b343a7a 100644 --- a/include/net/zoap.h +++ b/include/net/zoap.h @@ -624,8 +624,8 @@ struct zoap_block_context { * @return 0 in case of success or negative in case of error. */ int zoap_block_transfer_init(struct zoap_block_context *ctx, - enum zoap_block_size block_size, - size_t total_size); + enum zoap_block_size block_size, + size_t total_size); /** * @brief Add BLOCK1 option to the packet. From d8d16e81f5560c9d7ea79d2689f25d6867c97a28 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Thu, 9 Feb 2017 16:44:14 -0800 Subject: [PATCH 06/20] iot/zoap: Add missing const modifier to header file Makes it cleared that zoap_update_from_block() doesn't modify the packet. Change-Id: I35429b153370c50eb5ae9c914b47a3144faf2f04 Signed-off-by: Vinicius Costa Gomes --- include/net/zoap.h | 2 +- subsys/net/lib/zoap/zoap.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/net/zoap.h b/include/net/zoap.h index 9151b343a7a..e255efd8564 100644 --- a/include/net/zoap.h +++ b/include/net/zoap.h @@ -684,7 +684,7 @@ int zoap_add_size2_option(struct zoap_packet *pkt, * * @return 0 in case of success or negative in case of error. */ -int zoap_update_from_block(struct zoap_packet *pkt, +int zoap_update_from_block(const struct zoap_packet *pkt, struct zoap_block_context *ctx); /** diff --git a/subsys/net/lib/zoap/zoap.c b/subsys/net/lib/zoap/zoap.c index 94dab4a7c36..9ffd4ece308 100644 --- a/subsys/net/lib/zoap/zoap.c +++ b/subsys/net/lib/zoap/zoap.c @@ -548,7 +548,7 @@ static zoap_method_t method_from_code(const struct zoap_resource *resource, } } -static bool is_request(struct zoap_packet *pkt) +static bool is_request(const struct zoap_packet *pkt) { uint8_t code = zoap_header_get_code(pkt); @@ -1210,7 +1210,7 @@ struct block_transfer { bool more; }; -static int get_block_option(struct zoap_packet *pkt, uint16_t code) +static int get_block_option(const struct zoap_packet *pkt, uint16_t code) { struct zoap_option option; unsigned int val; @@ -1302,7 +1302,7 @@ static int update_control_block2(struct zoap_block_context *ctx, return 0; } -int zoap_update_from_block(struct zoap_packet *pkt, +int zoap_update_from_block(const struct zoap_packet *pkt, struct zoap_block_context *ctx) { int r, block1, block2, size1, size2; From 449cbbd87454337db36f3f54b820e9e5d58e7af8 Mon Sep 17 00:00:00 2001 From: Flavio Santes Date: Sun, 12 Feb 2017 20:01:09 -0600 Subject: [PATCH 07/20] net/dns: Update QEMU prj file Update the IPv4 addresses to 192.0.2.x. Change-Id: I0eafccfaf691cfd2ffb896e18d3fdcf091837edc Signed-off-by: Flavio Santes --- samples/net/dns_client/prj_qemu_x86.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/net/dns_client/prj_qemu_x86.conf b/samples/net/dns_client/prj_qemu_x86.conf index 39410474949..9f09444f12a 100644 --- a/samples/net/dns_client/prj_qemu_x86.conf +++ b/samples/net/dns_client/prj_qemu_x86.conf @@ -29,5 +29,5 @@ CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=1 CONFIG_NET_SAMPLES_IP_ADDRESSES=y CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1" CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2" -CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.168.1.101" -CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.168.1.10" +CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2" From bed71d0a027efad2280eccd0f0296a6985097620 Mon Sep 17 00:00:00 2001 From: Flavio Santes Date: Wed, 8 Feb 2017 15:02:58 -0600 Subject: [PATCH 08/20] net/mqtt: Fix inline doc for MQTT Fix inline documentation for the MQTT API. Jira: ZEP-1669 Change-Id: I90702eae236a9189b58e0f2fb2a6c5a3eeaf959c Signed-off-by: Flavio Santes --- include/net/mqtt.h | 390 +++++++++++++------------- subsys/net/lib/mqtt/mqtt.c | 110 ++++---- subsys/net/lib/mqtt/mqtt_pkt.c | 287 ++++++++++--------- subsys/net/lib/mqtt/mqtt_pkt.h | 495 +++++++++++++++++---------------- 4 files changed, 659 insertions(+), 623 deletions(-) diff --git a/include/net/mqtt.h b/include/net/mqtt.h index b05d34f37bc..d7d55e63671 100644 --- a/include/net/mqtt.h +++ b/include/net/mqtt.h @@ -17,7 +17,7 @@ */ /** - * @brief mqtt_app MQTT application type + * MQTT application type */ enum mqtt_app { /** Publisher and Subscriber application */ @@ -31,9 +31,9 @@ enum mqtt_app { }; /** - * @brief struct mqtt_ctx MQTT context structure - * @details - * Context structure for the MQTT high-level API with support for QoS. + * MQTT context structure + * + * @details Context structure for the MQTT high-level API with support for QoS. * * This API is designed for asynchronous operation, so callbacks are * executed when some events must be addressed outside the MQTT routines. @@ -74,84 +74,66 @@ struct mqtt_ctx { /** Callback executed when a #MQTT_APP_PUBLISHER application receives * a MQTT PUBxxxx msg. + * If type is MQTT_PUBACK, MQTT_PUBCOMP or MQTT_PUBREC, this callback + * must return 0 if pkt_id matches the packet id of a previously + * received MQTT_PUBxxx message. If this callback returns 0, the caller + * will continue. + * Any other value will stop the QoS handshake and the caller will + * return -EINVAL. The application must discard all the messages + * already processed. * * Note: this callback must be not NULL * - * @param [in] ctx MQTT context - * @param [in] pkt_id Packet Identifier for the input MQTT msg - * @param [in] type Packet type - * @return If this callback returns 0, the caller will - * continue. - * - * @return If type is MQTT_PUBACK, MQTT_PUBCOMP or - * MQTT_PUBREC, this callback must return 0 if - * pkt_id matches the packet id of a previously - * received MQTT_PUBxxx message. - * - * @return Note: the application must discard all the - * messages already processed - * - * @return Any other value will stop the QoS handshake - * and the caller will return -EINVAL + * @param [in] ctx MQTT context + * @param [in] pkt_id Packet Identifier for the input MQTT msg + * @param [in] type Packet type */ int (*publish_tx)(struct mqtt_ctx *ctx, uint16_t pkt_id, enum mqtt_packet type); /** Callback executed when a MQTT_APP_SUBSCRIBER, - * MQTT_APP_PUBLISHER_SUBSCRIBER or MQTT_APP_SERVER application receive - * a MQTT PUBxxxx msg. + * MQTT_APP_PUBLISHER_SUBSCRIBER or MQTT_APP_SERVER applications receive + * a MQTT PUBxxxx msg. If this callback returns 0, the caller will + * continue. If type is MQTT_PUBREL this callback must return 0 if + * pkt_id matches the packet id of a previously received MQTT_PUBxxx + * message. Any other value will stop the QoS handshake and the caller + * will return -EINVAL * * Note: this callback must be not NULL * - * @param [in] ctx MQTT context - * @param [in] msg Publish message, this parameter is only used - * when the type is MQTT_PUBLISH - * @param [in] pkt_id Packet Identifier for the input msg - * @param [in] type Packet type - * @return If this callback returns 0, the caller will - * continue. - * - * @return If type is MQTT_PUBREL this callback must return - * 0 if pkt_id matches the packet id of a - * previously received MQTT_PUBxxx message. - * - * @return Note: the application must discard all the - * messages already processed - * - * @return Any other value will stop the QoS handshake - * and the caller will return -EINVAL + * @param [in] ctx MQTT context + * @param [in] msg Publish message, this parameter is only used + * when the type is MQTT_PUBLISH + * @param [in] pkt_id Packet Identifier for the input msg + * @param [in] type Packet type */ int (*publish_rx)(struct mqtt_ctx *ctx, struct mqtt_publish_msg *msg, uint16_t pkt_id, enum mqtt_packet type); /** Callback executed when a MQTT_APP_SUBSCRIBER or * MQTT_APP_PUBLISHER_SUBSCRIBER receives the MQTT SUBACK message + * If this callback returns 0, the caller will continue. Any other + * value will make the caller return -EINVAL. * * Note: this callback must be not NULL * - * @param [in] ctx MQTT context - * @param [in] pkt_id Packet Identifier for the MQTT SUBACK msg - * @param [in] items Number of elements in the qos array - * @param [in] qos Array of QoS values - * @return If this callback returns 0, the caller will - * continue - * @return Any other value will make the caller return - * -EINVAL + * @param [in] ctx MQTT context + * @param [in] pkt_id Packet Identifier for the MQTT SUBACK msg + * @param [in] items Number of elements in the qos array + * @param [in] qos Array of QoS values */ int (*subscribe)(struct mqtt_ctx *ctx, uint16_t pkt_id, uint8_t items, enum mqtt_qos qos[]); /** Callback executed when a MQTT_APP_SUBSCRIBER or * MQTT_APP_PUBLISHER_SUBSCRIBER receives the MQTT UNSUBACK message + * If this callback returns 0, the caller will continue. Any other value + * will make the caller return -EINVAL * * Note: this callback must be not NULL * * @param [in] ctx MQTT context * @param [in] pkt_id Packet Identifier for the MQTT SUBACK msg - * @return If this callback returns 0, the caller will - * continue - * @return Any other value will make the caller return - * -EINVAL */ int (*unsubscribe)(struct mqtt_ctx *ctx, uint16_t pkt_id); @@ -182,219 +164,253 @@ struct mqtt_ctx { }; /** - * @brief mqtt_init Initializes the MQTT context structure - * @param ctx MQTT context structure - * @param app_type See enum mqtt_app - * @return 0, always. + * Initializes the MQTT context structure + * + * @param ctx MQTT context structure + * @param app_type See enum mqtt_app + * @retval 0, always. */ int mqtt_init(struct mqtt_ctx *ctx, enum mqtt_app app_type); /** - * @brief mqtt_tx_connect Sends the MQTT CONNECT message - * @param [in] ctx MQTT context structure - * @param [in] msg MQTT CONNECT msg - * @return 0 on success - * @return -EIO on network error - * @return -ENOMEM if no data/tx buffer is available - * @return -EINVAL if invalid data was passed to this - * routine + * Sends the MQTT CONNECT message + * + * @param [in] ctx MQTT context structure + * @param [in] msg MQTT CONNECT msg + * + * @retval 0 on success + * @retval -EIO + * @retval -ENOMEM + * @retval -EINVAL */ int mqtt_tx_connect(struct mqtt_ctx *ctx, struct mqtt_connect_msg *msg); /** - * @brief mqtt_tx_disconnect Send the MQTT DISCONNECT message - * @param [in] ctx MQTT context structure - * @return 0 on success - * @return -EIO on network error - * @return -ENOMEM if no data/tx buffer is available - * @return -EINVAL if invalid data was passed to this - * routine + * Send the MQTT DISCONNECT message + * + * @param [in] ctx MQTT context structure + * + * @retval 0 on success + * @retval -EIO + * @retval -ENOMEM + * @retval -EINVAL */ int mqtt_tx_disconnect(struct mqtt_ctx *ctx); /** - * @brief mqtt_tx_puback Sends the MQTT PUBACK message with the given - * packet id - * @param [in] ctx MQTT context structure - * @param [in] id MQTT Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed to - * this routine - * @return -ENOMEM if a tx buffer is not available - * @return -EIO on network error + * Sends the MQTT PUBACK message with the given packet id + * + * @param [in] ctx MQTT context structure + * @param [in] id MQTT Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM + * @retval -EIO */ int mqtt_tx_puback(struct mqtt_ctx *ctx, uint16_t id); /** - * @brief mqtt_tx_pubcomp Sends the MQTT PUBCOMP message with the given - * packet id - * @param [in] ctx MQTT context structure - * @param [in] id MQTT Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed to - * this routine - * @return -ENOMEM if a tx buffer is not available - * @return -EIO on network error + * Sends the MQTT PUBCOMP message with the given packet id + * + * @param [in] ctx MQTT context structure + * @param [in] id MQTT Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM + * @retval -EIO */ int mqtt_tx_pubcomp(struct mqtt_ctx *ctx, uint16_t id); /** - * @brief mqtt_tx_pubrec Sends the MQTT PUBREC message with the given - * packet id - * @param [in] ctx MQTT context structure - * @param [in] id MQTT Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed to - * this routine - * @return -ENOMEM if a tx buffer is not available - * @return -EIO on network error + * Sends the MQTT PUBREC message with the given packet id + * + * @param [in] ctx MQTT context structure + * @param [in] id MQTT Packet Identifier + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM + * @retval -EIO */ int mqtt_tx_pubrec(struct mqtt_ctx *ctx, uint16_t id); /** - * @brief mqtt_tx_pubrel Sends the MQTT PUBREL message with the given - * packet id - * @param [in] ctx MQTT context structure - * @param [in] id MQTT Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed to - * this routine - * @return -ENOMEM if a tx buffer is not available - * @return -EIO on network error + * Sends the MQTT PUBREL message with the given packet id + * + * @param [in] ctx MQTT context structure + * @param [in] id MQTT Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM + * @retval -EIO */ int mqtt_tx_pubrel(struct mqtt_ctx *ctx, uint16_t id); /** - * @brief mqtt_tx_publish Sends the MQTT PUBLISH message - * @param [in] ctx MQTT context structure - * @param [in] msg MQTT PUBLISH msg - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed to - * this routine - * @return -ENOMEM if a tx buffer is not available - * @return -EIO on network error + * Sends the MQTT PUBLISH message + * + * @param [in] ctx MQTT context structure + * @param [in] msg MQTT PUBLISH msg + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM + * @retval -EIO */ int mqtt_tx_publish(struct mqtt_ctx *ctx, struct mqtt_publish_msg *msg); /** - * @brief mqtt_tx_pingreq Sends the MQTT PINGREQ message - * @param [in] ctx MQTT context structure - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed to - * this routine - * @return -ENOMEM if a tx buffer is not available - * @return -EIO on network error + * Sends the MQTT PINGREQ message + * + * @param [in] ctx MQTT context structure + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM + * @retval -EIO */ int mqtt_tx_pingreq(struct mqtt_ctx *ctx); /** - * @brief mqtt_tx_subscribe Sends the MQTT SUBSCRIBE message - * @param [in] ctx MQTT context structure - * @param [in] pkt_id Packet identifier for the MQTT SUBSCRIBE msg - * @param [in] items Number of elements in 'topics' and 'qos' arrays - * @param [in] topics Array of 'items' elements containing C strings. - * For example: {"sensors", "lights", "doors"} - * @param [in] qos Array of 'items' elements containing MQTT QoS - * values: MQTT_QoS0, MQTT_QoS1, MQTT_QoS2. For - * example for the 'topics' array above the - * following QoS may be used: - * {MQTT_QoS0, MQTT_QoS2, MQTT_QoS1}, indicating - * that the subscription to 'lights' must be done - * with MQTT_QoS2 - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed to - * this routine - * @return -ENOMEM if a tx buffer is not available - * @return -EIO on network error + * Sends the MQTT SUBSCRIBE message + * + * @param [in] ctx MQTT context structure + * @param [in] pkt_id Packet identifier for the MQTT SUBSCRIBE msg + * @param [in] items Number of elements in 'topics' and 'qos' arrays + * @param [in] topics Array of 'items' elements containing C strings. + * For example: {"sensors", "lights", "doors"} + * @param [in] qos Array of 'items' elements containing MQTT QoS values: + * MQTT_QoS0, MQTT_QoS1, MQTT_QoS2. For example for the 'topics' + * array above the following QoS may be used: {MQTT_QoS0, + * MQTT_QoS2, MQTT_QoS1}, indicating that the subscription to + * 'lights' must be done with MQTT_QoS2 + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM + * @retval -EIO */ int mqtt_tx_subscribe(struct mqtt_ctx *ctx, uint16_t pkt_id, uint8_t items, const char *topics[], const enum mqtt_qos qos[]); /** - * @brief mqtt_tx_unsubscribe Sends the MQTT UNSUBSCRIBE message - * @param [in] ctx MQTT context structure - * @param [in] pkt_id Packet identifier for the MQTT UNSUBSCRIBE msg - * @param [in] items Number of elements in the 'topics' array - * @param [in] topics Array of 'items' elements containing C strings - * @return + * Sends the MQTT UNSUBSCRIBE message + * + * @param [in] ctx MQTT context structure + * @param [in] pkt_id Packet identifier for the MQTT UNSUBSCRIBE msg + * @param [in] items Number of elements in the 'topics' array + * @param [in] topics Array of 'items' elements containing C strings + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM + * @retval -EIO */ int mqtt_tx_unsubscribe(struct mqtt_ctx *ctx, uint16_t pkt_id, uint8_t items, const char *topics[]); + +/** + * Parses and validates the MQTT CONNACK msg + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * @param [in] clean_session MQTT clean session parameter + * + * @retval 0 on success + * @retval -EINVAL + */ int mqtt_rx_connack(struct mqtt_ctx *ctx, struct net_buf *rx, int clean_session); /** - * @brief mqtt_rx_puback Parses and validates the MQTT PUBACK message - * @param [in] ctx MQTT context structure - * @param [in] rx Data buffer - * @return 0 on success - * @return -EINVAL on error + * Parses and validates the MQTT PUBACK message + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_rx_puback(struct mqtt_ctx *ctx, struct net_buf *rx); /** - * @brief mqtt_rx_pubcomp Parses and validates the MQTT PUBCOMP message - * @param [in] ctx MQTT context structure - * @param [in] rx Data buffer - * @return 0 on success - * @return -EINVAL on error + * Parses and validates the MQTT PUBCOMP message + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_rx_pubcomp(struct mqtt_ctx *ctx, struct net_buf *rx); /** - * @brief mqtt_rx_pubrec Parses and validates the MQTT PUBREC message - * @param [in] ctx MQTT context structure - * @param [in] rx Data buffer - * @return 0 on success - * @return -EINVAL on error + * Parses and validates the MQTT PUBREC message + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_rx_pubrec(struct mqtt_ctx *ctx, struct net_buf *rx); /** - * @brief mqtt_rx_pubrel Parses and validates the MQTT PUBREL message - * @details rx is an RX buffer from the IP stack - * @param [in] ctx MQTT context structure - * @param [in] rx Data buffer - * @return 0 on success - * @return -EINVAL on error + * Parses and validates the MQTT PUBREL message + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_rx_pubrel(struct mqtt_ctx *ctx, struct net_buf *rx); /** - * @brief mqtt_rx_pingresp Parses the MQTT PINGRESP message - * @param [in] ctx MQTT context structure - * @param [in] rx Data buffer - * @return 0 on success - * @return -EINVAL on error + * Parses the MQTT PINGRESP message + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_rx_pingresp(struct mqtt_ctx *ctx, struct net_buf *rx); /** - * @brief mqtt_rx_suback Parses the MQTT SUBACK message - * @param [in] ctx MQTT context structure - * @param [in] rx Data buffer - * @return 0 on success - * @return -EINVAL on error + * Parses the MQTT SUBACK message + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_rx_suback(struct mqtt_ctx *ctx, struct net_buf *rx); /** - * @brief mqtt_rx_unsuback Parses the MQTT UNSUBACK message - * @param [in] ctx MQTT context structure - * @param [in] rx Data buffer - * @return 0 on success - * @return -EINVAL on error + * Parses the MQTT UNSUBACK message + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_rx_unsuback(struct mqtt_ctx *ctx, struct net_buf *rx); /** - * @brief mqtt_rx_publish Parses the MQTT PUBLISH message - * @param [in] ctx MQTT context structure - * @param [in] rx Data buffer - * @return 0 on success - * @return -EINVAL on error - * @return -ENOMEM if no data buffer is available + * Parses the MQTT PUBLISH message + * + * @param [in] ctx MQTT context structure + * @param [in] rx Data buffer + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM */ int mqtt_rx_publish(struct mqtt_ctx *ctx, struct net_buf *rx); diff --git a/subsys/net/lib/mqtt/mqtt.c b/subsys/net/lib/mqtt/mqtt.c index 9b57c8cf410..a6500bc9edf 100644 --- a/subsys/net/lib/mqtt/mqtt.c +++ b/subsys/net/lib/mqtt/mqtt.c @@ -113,16 +113,16 @@ exit_disconnect: } /** - * @brief mqtt_tx_pub_msgs Writes the MQTT PUBxxx msg indicated by pkt_type - * with identifier 'id' - * @param [in] ctx MQTT context - * @param [in] id MQTT packet identifier - * @param [in] pkt_type MQTT packet type - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed to - * this routine - * @return -ENOMEM if a tx buffer is not available - * @return -EIO on network error + * Writes the MQTT PUBxxx msg indicated by pkt_type with identifier 'id' + * + * @param [in] ctx MQTT context + * @param [in] id MQTT packet identifier + * @param [in] pkt_type MQTT packet type + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM if a tx buffer is not available + * @retval -EIO on network error */ static int mqtt_tx_pub_msgs(struct mqtt_ctx *ctx, uint16_t id, @@ -421,16 +421,19 @@ exit_connect: } /** - * @brief mqtt_rx_pub_msgs Parses and validates the MQTT PUBxxxx message - * contained in the rx buffer. It validates against - * message structure and Packet Identifier. - * @details For the MQTT PUBREC and PUBREL messages, this - * function writes the corresponding MQTT PUB msg. - * @param ctx MQTT context - * @param rx RX buffer - * @param type MQTT Packet type - * @return 0 on success - * @return -EINVAL on error + * Parses and validates the MQTT PUBxxxx message contained in the rx buffer. + * + * + * @details It validates against message structure and Packet Identifier. + * For the MQTT PUBREC and PUBREL messages, this function writes the + * corresponding MQTT PUB msg. + * + * @param ctx MQTT context + * @param rx RX buffer + * @param type MQTT Packet type + * + * @retval 0 on success + * @retval -EINVAL on error */ static int mqtt_rx_pub_msgs(struct mqtt_ctx *ctx, struct net_buf *rx, @@ -626,14 +629,15 @@ int mqtt_rx_publish(struct mqtt_ctx *ctx, struct net_buf *rx) } /** - * @brief mqtt_linearize_buffer Linearize an IP fragmented buffer - * @param [in] ctx MQTT context structure - * @param [in] rx RX IP stack buffer - * @param [in] min_size Min message size allowed. This allows us - * to exit if the rx buffer is shorter - * than the expected msg size - * @return Data buffer - * @return NULL on error + * Linearizes an IP fragmented buffer + * + * @param [in] ctx MQTT context structure + * @param [in] rx RX IP stack buffer + * @param [in] min_size Min message size allowed. This allows us to exit if the + * rx buffer is shorter than the expected msg size + * + * @retval Data buffer + * @retval NULL on error */ static struct net_buf *mqtt_linearize_buffer(struct mqtt_ctx *ctx, struct net_buf *rx, @@ -673,18 +677,19 @@ exit_error: } /** - * @brief mqtt_publisher_parser Calls the appropriate rx routine for the MQTT - * message contained in rx - * @details On error, this routine will execute the - * 'ctx->malformed' callback (if defined) - * @param ctx MQTT context - * @param rx RX buffer - * @return 0 on success - * @return -EINVAL if an unknown message is received - * @return -ENOMEM if no data buffer is available - * @return mqtt_rx_connack, mqtt_rx_puback, mqtt_rx_pubrec, - * mqtt_rx_pubcomp, and mqtt_rx_pingresp - * return codes + * Calls the appropriate rx routine for the MQTT message contained in rx + * + * @details On error, this routine will execute the 'ctx->malformed' callback + * (if defined) + * + * @param ctx MQTT context + * @param rx RX buffer + * + * @retval 0 on success + * @retval -EINVAL if an unknown message is received + * @retval -ENOMEM if no data buffer is available + * @retval mqtt_rx_connack, mqtt_rx_puback, mqtt_rx_pubrec, mqtt_rx_pubcomp + * and mqtt_rx_pingresp return codes */ static int mqtt_publisher_parser(struct mqtt_ctx *ctx, struct net_buf *rx) @@ -738,18 +743,19 @@ exit_parser: /** - * @brief mqtt_subscriber_parser Calls the appropriate rx routine for the MQTT - * message contained in rx - * @details On error, this routine will execute the - * 'ctx->malformed' callback (if defined) - * @param ctx MQTT context - * @param rx RX buffer - * @return 0 on success - * @return -EINVAL if an unknown message is received - * @return -ENOMEM if no data buffer is available - * @return mqtt_rx_publish, mqtt_rx_pubrel, mqtt_rx_pubrel, - * mqtt_rx_suback - * return codes + * Calls the appropriate rx routine for the MQTT message contained in rx + * + * @details On error, this routine will execute the 'ctx->malformed' callback + * (if defined) + * + * @param ctx MQTT context + * @param rx RX buffer + * + * @retval 0 on success + * @retval -EINVAL if an unknown message is received + * @retval -ENOMEM if no data buffer is available + * @retval mqtt_rx_publish, mqtt_rx_pubrel, mqtt_rx_pubrel and mqtt_rx_suback + * return codes */ static int mqtt_subscriber_parser(struct mqtt_ctx *ctx, struct net_buf *rx) diff --git a/subsys/net/lib/mqtt/mqtt_pkt.c b/subsys/net/lib/mqtt/mqtt_pkt.c index cd3c2b13adc..a04ee8f70ab 100644 --- a/subsys/net/lib/mqtt/mqtt_pkt.c +++ b/subsys/net/lib/mqtt/mqtt_pkt.c @@ -50,21 +50,22 @@ QoS_SIZE) /** - * @brief mqtt_strlen Enhanced strlen function - * @details This function is introduced to allow developers to - * pass null strings to functions that compute the length - * of strings. - * strlen returns random values for null arguments, so - * mqtt_strlen(NULL) is quite useful when optional strings - * are allowed by mqtt-related functions. For example: - * username in the MQTT CONNECT message is an optional - * parameter, so connect(..., username = NULL, ...) will - * work fine without passing an additional parameter like: - * connect(.., is_username_present, username, ...) or - * connect(.., username, username_len, ...). - * @param str C-string or NULL - * @return 0 for NULL - * @return strlen otherwise + * Enhanced strlen function + * + * @details This function is introduced to allow developers to pass null strings + * to functions that compute the length of strings. strlen returns random values + * for null arguments, so mqtt_strlen(NULL) is quite useful when optional + * strings are allowed by mqtt-related functions. For example: username in the + * MQTT CONNECT message is an optional parameter, so + * connect(..., username = NULL, ...) will work fine without passing an + * additional parameter like: + * connect(.., is_username_present, username, ...) or + * connect(.., username, username_len, ...). + * + * @param str C-string or NULL + * + * @retval 0 for NULL + * @retval strlen otherwise */ static inline uint16_t mqtt_strlen(const char *str) @@ -77,14 +78,13 @@ uint16_t mqtt_strlen(const char *str) } /** - * @brief compute_rlen_size Computes the amount of bytes needed to - * codify the value stored in len - * @details See MQTT 2.2.3, Table 2.4 - * @param [out] size Amount of bytes required to codify the value - * stored in len - * @param [in] len Value to be codified - * @return 0 on success - * @return -EINVAL is len is out of range + * Computes the amount of bytes needed to codify the value stored in len. + * + * @param [out] size Amount of bytes required to codify the value stored in len + * @param [in] len Value to be codified + * + * @retval 0 on success + * @retval -EINVAL */ static int compute_rlen_size(uint16_t *size, uint32_t len) @@ -105,11 +105,12 @@ int compute_rlen_size(uint16_t *size, uint32_t len) } /** - * @brief rlen_encode Remaining Length encoding algorithm - * @details See MQTT 2.2.3 Remaining Length - * @param [out] buf Buffer where the encoded value will be stored - * @param [in] len Value to encode - * @return 0 always + * Remaining Length encoding algorithm. See MQTT 2.2.3 Remaining Length + * + * @param [out] buf Buffer where the encoded value will be stored + * @param [in] len Value to encode + * + * @retval 0 always */ static int rlen_encode(uint8_t *buf, int len) { @@ -133,15 +134,15 @@ static int rlen_encode(uint8_t *buf, int len) } /** - * @brief rlen_decode Remaining Length decoding algorithm - * @details See MQTT 2.2.3 Remaining Length - * @param [out] rlen Remaining Length (decoded) - * @param [out] rlen_size Number of bytes required to codify rlen's value - * @param [in] buf Buffer where the codified Remaining Length - * is codified - * @param [in] size Buffer size - * @return 0 on success - * @return -ENOMEM if size < 4 + * Remaining Length decoding algorithm. See MQTT 2.2.3 Remaining Length + * + * @param [out] rlen Remaining Length (decoded) + * @param [out] rlen_size Number of bytes required to codify rlen's value + * @param [in] buf Buffer where the codified Remaining Length is codified + * @param [in] size Buffer size + * + * @retval 0 on success + * @retval -ENOMEM if size < 4 */ static int rlen_decode(uint16_t *rlen, uint16_t *rlen_size, uint8_t *buf, uint16_t size) @@ -184,23 +185,22 @@ int mqtt_pack_connack(uint8_t *buf, uint16_t *length, uint16_t size, } /** - * @brief pack_pkt_id Packs a message that only contains the - * Packet Identifier as payload. - * @details Many MQTT messages only codify the packet type, - * reserved flags and the Packet Identifier as payload, - * so this function is used by those MQTT messages. + * Packs a message that only contains the Packet Identifier as payload. * - * The total size of this message is always 4 bytes, - * with a payload of only 2 bytes to codify the - * identifier. - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] type MQTT Control Packet type + * @details Many MQTT messages only codify the packet type, reserved flags and + * the Packet Identifier as payload, so this function is used by those MQTT + * messages. The total size of this message is always 4 bytes, with a payload + * of only 2 bytes to codify the identifier. + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer's size + * @param [in] type MQTT Control Packet type * @param [in] reserved Control Packet Reserved Flags. See MQTT 2.2.2 Flags - * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier - * @return 0 on success - * @return -ENOMEM if size < 4 + * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier + * + * @retval 0 on success + * @retval -ENOMEM if size < 4 */ static int pack_pkt_id(uint8_t *buf, uint16_t *length, uint16_t size, @@ -415,15 +415,15 @@ int mqtt_pack_connect(uint8_t *buf, uint16_t *length, uint16_t size, } /** - * @brief recover_value_len Recovers the length and sets val to point to - * the beginning of the value - * @param [in] buf Buffer where the length and value are stored - * @param [in] length Buffer's length - * @param [out] val Pointer to the beginning of the value - * @param [out] val_len Recovered value's length - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Recovers the length and sets val to point to the beginning of the value + * + * @param [in] buf Buffer where the length and value are stored + * @param [in] length Buffer's length + * @param [out] val Pointer to the beginning of the value + * @param [out] val_len Recovered value's length + * + * @retval 0 on success + * @retval -EINVAL */ static int recover_value_len(uint8_t *buf, uint16_t length, uint8_t **val, @@ -568,17 +568,18 @@ int mqtt_unpack_connect(uint8_t *buf, uint16_t length, } /** - * @brief subscribe_size Computes the packet size for the SUBSCRIBE - * and UNSUBSCRIBE messages without considering - * the packet type field size (1 byte) - * @param rlen_size Remaining length size - * @param payload_size SUBSCRIBE or UNSUBSCRIBE payload size - * @param items Number of topics - * @param topics Array of C-strings containing the topics - * to subscribe to - * @param with_qos 0 for UNSUBSCRIBE, != 0 for SUBSCRIBE - * @return 0 on success - * @return -EINVAL on error + * Computes the packet size for the SUBSCRIBE and UNSUBSCRIBE messages + * + * This routine does not consider the packet type field size (1 byte) + * + * @param rlen_size Remaining length size + * @param payload_size SUBSCRIBE or UNSUBSCRIBE payload size + * @param items Number of topics + * @param topics Array of C-strings containing the topics to subscribe to + * @param with_qos 0 for UNSUBSCRIBE, != 0 for SUBSCRIBE + * + * @retval 0 on success + * @retval -EINVAL on error */ static int subscribe_size(uint16_t *rlen_size, uint16_t *payload_size, uint8_t items, @@ -607,19 +608,18 @@ int subscribe_size(uint16_t *rlen_size, uint16_t *payload_size, uint8_t items, } /** - * @brief mqtt_pack_subscribe_unsubscribe - * @details Packs the SUBSCRIBE and UNSUBSCRIBE messages - * @param buf Buffer where the message will be stored - * @param pkt_id Packet Identifier - * @param items Number of topics - * @param topics Array of C-strings containing the topics - * to subscribe to - * @param qos Array of QoS' values, qos[i] is the QoS of topic[i] - * @param type MQTT_SUBSCRIBE or MQTT_UNSUBSCRIBE - * @return 0 on success - * @return -EINVAL if invalid parameters were passed as arguments - * @return -ENOMEM if buf has no enough space to store the - * resultant message + * Packs the SUBSCRIBE and UNSUBSCRIBE messages + * + * @param buf Buffer where the message will be stored + * @param pkt_id Packet Identifier + * @param items Number of topics + * @param topics Array of C-strings containing the topics to subscribe to + * @param qos Array of QoS' values, qos[i] is the QoS of topic[i] + * @param type MQTT_SUBSCRIBE or MQTT_UNSUBSCRIBE + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM */ static int mqtt_pack_subscribe_unsubscribe(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id, @@ -969,19 +969,20 @@ int mqtt_unpack_connack(uint8_t *buf, uint16_t length, uint8_t *session, } /** - * @brief pack_zerolen Packs a zero length message - * @details This function packs MQTT messages with no - * payload. No validations are made about the - * input arguments, besides 'size' that must be - * at least 2 bytes - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_type MQTT Control Packet Type. See MQTT 2.2.1 - * @param [in] reserved Reserved bits. See MQTT 2.2 - * @return 0 on success - * @return -ENOMEM if buf has no enough reserved space - * to store the resultant message + * Packs a zero length message + * + * @details This function packs MQTT messages with no payload. No validations + * are made about the input arguments, besides 'size' that must be at least + * 2 bytes + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_type MQTT Control Packet Type. See MQTT 2.2.1 + * @param [in] reserved Reserved bits. See MQTT 2.2 + * + * @retval 0 on success + * @retval -ENOMEM */ static int pack_zerolen(uint8_t *buf, uint16_t *length, uint16_t size, @@ -1014,16 +1015,16 @@ int mqtt_pack_disconnect(uint8_t *buf, uint16_t *length, uint16_t size) } /** - * @brief unpack_pktid Unpacks a MQTT message with a Packet Id - * as payload - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] type MQTT Control Packet type - * @param [out] reserved Reserved flags - * @param [out] pkt_id Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks a MQTT message with a Packet Id as payload + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] type MQTT Control Packet type + * @param [out] reserved Reserved flags + * @param [out] pkt_id Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL */ static int unpack_pktid(uint8_t *buf, uint16_t length, enum mqtt_packet *type, @@ -1045,26 +1046,22 @@ int unpack_pktid(uint8_t *buf, uint16_t length, enum mqtt_packet *type, } /** - * @brief unpack_pktid_validate Unpacks and validates a MQTT message - * containing a Packet Identifier - * @details The message codified in buf must contain a - * 1) packet type, 2) reserved flags and - * 3) packet identifier. - * The user must provide the expected packet type - * and expected reserved flags. - * See MQTT 2.2.2 Flags. - * If the message contains different values for - * type and reserved flags than the ones passed as - * arguments, the function will return -EINVAL - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_id Packet Identifier - * @param [in] expected_type Expected MQTT Control Packet type - * @param [in] expected_reserv Expected Reserved Flags - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine or if - * any test failed + * Unpacks and validates a MQTT message containing a Packet Identifier + * + * @details The message codified in buf must contain a 1) packet type, + * 2) reserved flags and 3) packet identifier. The user must provide the + * expected packet type and expected reserved flags. See MQTT 2.2.2 Flags. + * If the message contains different values for type and reserved flags + * than the ones passed as arguments, the function will return -EINVAL + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_id Packet Identifier + * @param [in] expected_type Expected MQTT Control Packet type + * @param [in] expected_reserv Expected Reserved Flags + * + * @retval 0 on success + * @retval -EINVAL */ static int unpack_pktid_validate(uint8_t *buf, uint16_t length, uint16_t *pkt_id, @@ -1117,14 +1114,15 @@ int mqtt_unpack_unsuback(uint8_t *buf, uint16_t length, uint16_t *pkt_id) } /** - * @brief unpack_zerolen Unpacks a zero-length MQTT message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_type MQTT Control Packet type - * @param [out] reserved Reserved flags - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks a zero-length MQTT message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_type MQTT Control Packet type + * @param [out] reserved Reserved flags + * + * @retval 0 on success + * @retval -EINVAL */ static int unpack_zerolen(uint8_t *buf, uint16_t length, enum mqtt_packet *pkt_type, @@ -1145,14 +1143,15 @@ int unpack_zerolen(uint8_t *buf, uint16_t length, enum mqtt_packet *pkt_type, } /** - * @brief unpack_zerolen_validate Unpacks and validates a zero-len MQTT message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param expected_type Expected MQTT Control Packet type - * @param expected_reserved Expected Reserved Flags - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks and validates a zero-len MQTT message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param expected_type Expected MQTT Control Packet type + * @param expected_reserved Expected Reserved Flags + * + * @retval 0 on success + * @retval -EINVAL */ static int unpack_zerolen_validate(uint8_t *buf, uint16_t length, diff --git a/subsys/net/lib/mqtt/mqtt_pkt.h b/subsys/net/lib/mqtt/mqtt_pkt.h index db9721a3274..87db2bab137 100644 --- a/subsys/net/lib/mqtt/mqtt_pkt.h +++ b/subsys/net/lib/mqtt/mqtt_pkt.h @@ -10,8 +10,8 @@ * @brief MQTT v3.1.1 packet library, see: * http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html * - * This file is part of the Zephyr Project - * http://www.zephyrproject.org + * This file is part of the Zephyr Project + * http://www.zephyrproject.org */ #ifndef _MQTT_PKT_H_ @@ -25,368 +25,383 @@ #define MQTT_PACKET_TYPE(first_byte) (((first_byte) & 0xF0) >> 4) /** - * @brief mqtt_pack_connack Packs the MQTT CONNACK message - * @details See MQTT 3.2 CONNACK - Acknowledge connection - * request - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] session_present Session Present parameter (0 for clean session) - * @param [in] ret_code Connect return code. See MQTT 3.2.2.3 - * @return 0 on success - * @return -ENOMEM if size < 4 + * Packs the MQTT CONNACK message. See MQTT 3.2 CONNACK - Acknowledge + * connection request + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] session_present Session Present parameter (0 for clean session) + * @param [in] ret_code Connect return code. See MQTT 3.2.2.3 + * + * @retval 0 on success + * @retval -ENOMEM if size < 4 */ int mqtt_pack_connack(uint8_t *buf, uint16_t *length, uint16_t size, uint8_t session_present, uint8_t ret_code); /** - * @brief mqtt_pack_puback Packs the MQTT PUBACK message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet - * Identifier - * @return 0 on success - * @return -ENOMEM if size < 4 + * Packs the MQTT PUBACK message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier + * + * @retval 0 on success + * @retval -ENOMEM if size < 4 */ int mqtt_pack_puback(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id); /** - * @brief mqtt_pack_pubrec Packs the MQTT PUBREC message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet - * Identifier - * @return 0 on success - * @return -ENOMEM if size < 4 + * Packs the MQTT PUBREC message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier + * + * @retval 0 on success + * @retval -ENOMEM if size < 4 */ int mqtt_pack_pubrec(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id); /** - * @brief mqtt_pack_puback Packs the MQTT PUBREL message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet - * Identifier - * @return 0 on success - * @return -ENOMEM if size < 4 + * Packs the MQTT PUBREL message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier + * + * @retval 0 on success + * @retval -ENOMEM if size < 4 */ int mqtt_pack_pubrel(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id); /** - * @brief mqtt_pack_pubcomp Packs the MQTT PUBCOMP message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet - * Identifier - * @return 0 on success - * @return -ENOMEM if size < 4 + * Packs the MQTT PUBCOMP message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier + * + * @retval 0 on success + * @retval -ENOMEM if size < 4 */ int mqtt_pack_pubcomp(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id); /** - * @brief mqtt_pack_suback Packs the MQTT SUBACK message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 - * @param [in] elements Number of elements in the granted_qos array - * @param [in] granted_qos Array where the QoS values are stored - * See MQTT 3.9 SUBACK, 3.9.3 Payload - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine - * @return -ENOMEM if buf does not have enough reserved - * space to store the resultant message + * Packs the MQTT SUBACK message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 + * @param [in] elements Number of elements in the granted_qos array + * @param [in] granted_qos Array where the QoS values are stored + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM */ int mqtt_pack_suback(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id, uint8_t elements, enum mqtt_qos granted_qos[]); /** - * @brief mqtt_pack_connect Packs the MQTT CONNECT message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] msg MQTT CONNECT msg - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine - * @return -ENOMEM if buf does not have enough reserved - * space to store the resultant message + * Packs the MQTT CONNECT message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] msg MQTT CONNECT msg + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM */ int mqtt_pack_connect(uint8_t *buf, uint16_t *length, uint16_t size, struct mqtt_connect_msg *msg); /** - * @brief mqtt_unpack_connect Unpacks the MQTT CONNECT message - * @param [in] buf Buffer where the message is stored - * @param [in] length MQTT CONNECT message's length - * @param [out] msg MQTT CONNECT parameters - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks the MQTT CONNECT message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length MQTT CONNECT message's length + * @param [out] msg MQTT CONNECT parameters + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_connect(uint8_t *buf, uint16_t length, struct mqtt_connect_msg *msg); /** - * @brief mqtt_pack_subscribe Packs the MQTT SUBSCRIBE message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1 - * @param [in] items Number of elements in topics - * @param [in] topics Array of topics. - * For example: {"sensors", "lights", "doors"} - * @param [in] qos Array of QoS values per topic. For example: - {MQTT_QoS1, MQTT_QoS2, MQTT_QoS0} - NOTE: qos and topics must have the same - cardinality (# of items) - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine - * @return -ENOMEM if buf does not have enough reserved - * space to store the resultant message + * Packs the MQTT SUBSCRIBE message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1 + * @param [in] items Number of elements in topics + * @param [in] topics Array of topics. + * For example: {"sensors", "lights", "doors"} + * @param [in] qos Array of QoS values per topic. + * For example: {MQTT_QoS1, MQTT_QoS2, MQTT_QoS0} + * NOTE: qos and topics must have the same cardinality + * (# of items) + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM */ int mqtt_pack_subscribe(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id, uint8_t items, const char *topics[], const enum mqtt_qos qos[]); /** - * @brief mqtt_pack_unsubscribe Packs the MQTT UNSUBSCRIBE message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1 - * @param [in] items Number of elements in topics - * @param [in] topics Array of topics. - * For example: {"sensors", "lights", "doors"} - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine - * @return -ENOMEM if buf does not have enough reserved - * space to store the resultant message + * Packs the MQTT UNSUBSCRIBE message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1 + * @param [in] items Number of elements in topics + * @param [in] topics Array of topics. + * For example: {"sensors", "lights", "doors"} + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM */ int mqtt_pack_unsubscribe(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id, uint8_t items, const char *topics[]); /** - * @brief mqtt_unpack_subscribe Unpacks the MQTT SUBSCRIBE message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1 - * @param [out] items Number of recovered topics - * @param [in] elements Max number of topics to recover from buf - * @param [out] topics Array of topics. Each element in this array - * points to the beginning of a topic in buf - * @param [out] topic_len Array of topics' length. Each element in this - * array contains the length of the - * @param [out] qos Array of QoS, - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks the MQTT SUBSCRIBE message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1 + * @param [out] items Number of recovered topics + * @param [in] elements Max number of topics to recover from buf + * @param [out] topics Array of topics. Each element in this array points to + * the beginning of a topic in buf + * @param [out] topic_len Array containing the length of each topic in topics + * @param [out] qos Array of QoS values + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_subscribe(uint8_t *buf, uint16_t length, uint16_t *pkt_id, uint8_t *items, uint8_t elements, char *topics[], uint16_t topic_len[], enum mqtt_qos qos[]); /** - * @brief mqtt_unpack_suback Unpacks the MQTT SUBACK message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1 - * @param [out] items Number of recovered topics - * @param [in] elements Max number of topics to recover from buf - * @param [out] granted_qos Granted QoS values per topic. See MQTT 3.9 - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks the MQTT SUBACK message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_id MQTT Message Packet Identifier. See MQTT 2.3.1 + * @param [out] items Number of recovered topics + * @param [in] elements Max number of topics to recover from buf + * @param [out] granted_qos Granted QoS values per topic. See MQTT 3.9 + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_suback(uint8_t *buf, uint16_t length, uint16_t *pkt_id, uint8_t *items, uint8_t elements, enum mqtt_qos granted_qos[]); /** - * @brief mqtt_pack_publish Packs the MQTT PUBLISH message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] msg MQTT PUBLISH message - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine - * @return -ENOMEM if buf does not have enough reserved - * space to store the resultant message + * Packs the MQTT PUBLISH message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] msg MQTT PUBLISH message + * + * @retval 0 on success + * @retval -EINVAL + * @retval -ENOMEM */ int mqtt_pack_publish(uint8_t *buf, uint16_t *length, uint16_t size, struct mqtt_publish_msg *msg); /** - * @brief mqtt_unpack_publish Unpacks the MQTT PUBLISH message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] msg MQTT PUBLISH message - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks the MQTT PUBLISH message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] msg MQTT PUBLISH message + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_publish(uint8_t *buf, uint16_t length, struct mqtt_publish_msg *msg); /** - * @brief mqtt_unpack_connack Unpacks the MQTT CONNACK message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] session Session Present. See MQTT 3.2.2.2 - * @param [out] connect_rc CONNECT return code. See MQTT 3.2.2.3 - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks the MQTT CONNACK message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] session Session Present. See MQTT 3.2.2.2 + * @param [out] connect_rc CONNECT return code. See MQTT 3.2.2.3 + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_connack(uint8_t *buf, uint16_t length, uint8_t *session, uint8_t *connect_rc); /** - * @brief mqtt_pack_pingreq Packs the MQTT PINGREQ message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @return 0 on success - * @return -ENOMEM if buf does not have enough reserved - * space to store the resultant message + * Packs the MQTT PINGREQ message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * + * @retval 0 on success + * @retval -ENOMEM */ int mqtt_pack_pingreq(uint8_t *buf, uint16_t *length, uint16_t size); /** - * @brief mqtt_pack_pingresp Packs the MQTT PINGRESP message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @return 0 on success - * @return -ENOMEM if buf does not have enough reserved - * space to store the resultant message + * Packs the MQTT PINGRESP message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * + * @retval 0 on success + * @retval -ENOMEM */ int mqtt_pack_pingresp(uint8_t *buf, uint16_t *length, uint16_t size); /** - * @brief mqtt_pack_disconnect Packs the MQTT DISCONNECT message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @return 0 on success - * @return -ENOMEM if buf does not have enough reserved - * space to store the resultant message + * Packs the MQTT DISCONNECT message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * + * @retval 0 on success + * @retval -ENOMEM */ int mqtt_pack_disconnect(uint8_t *buf, uint16_t *length, uint16_t size); /** - * @brief mqtt_pack_unsuback Packs the MQTT UNSUBACK message - * @param [out] buf Buffer where the resultant message is stored - * @param [out] length Number of bytes required to codify the message - * @param [in] size Buffer's size - * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet - * Identifier - * @return 0 on success - * @return -ENOMEM if size < 4 + * Packs the MQTT UNSUBACK message + * + * @param [out] buf Buffer where the resultant message is stored + * @param [out] length Number of bytes required to codify the message + * @param [in] size Buffer size + * @param [in] pkt_id Packet Identifier. See MQTT 2.3.1 Packet Identifier + * + * @retval 0 on success + * @retval -ENOMEM if size < 4 */ int mqtt_pack_unsuback(uint8_t *buf, uint16_t *length, uint16_t size, uint16_t pkt_id); /** - * @brief mqtt_unpack_puback Unpacks the MQTT PUBACK message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_id Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine or if - * buf does not contain the desired msg + * Unpacks the MQTT PUBACK message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_id Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_puback(uint8_t *buf, uint16_t length, uint16_t *pkt_id); /** - * @brief mqtt_unpack_pubrec Unpacks the MQTT PUBREC message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_id Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine or if - * buf does not contain the desired msg + * Unpacks the MQTT PUBREC message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_id Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_pubrec(uint8_t *buf, uint16_t length, uint16_t *pkt_id); /** - * @brief mqtt_unpack_pubrel Unpacks the MQTT PUBREL message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_id Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine or if - * buf does not contain the desired msg + * Unpacks the MQTT PUBREL message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_id Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_pubrel(uint8_t *buf, uint16_t length, uint16_t *pkt_id); /** - * @brief mqtt_unpack_pubcomp Unpacks the MQTT PUBCOMP message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_id Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine or if - * buf does not contain the desired msg + * Unpacks the MQTT PUBCOMP message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_id Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_pubcomp(uint8_t *buf, uint16_t length, uint16_t *pkt_id); /** - * @brief mqtt_unpack_unsuback Unpacks the MQTT UNSUBACK message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @param [out] pkt_id Packet Identifier - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine or if - * buf does not contain the desired msg + * Unpacks the MQTT UNSUBACK message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * @param [out] pkt_id Packet Identifier + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_unsuback(uint8_t *buf, uint16_t length, uint16_t *pkt_id); /** - * @brief mqtt_unpack_pingreq Unpacks the MQTT PINGREQ message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks the MQTT PINGREQ message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_pingreq(uint8_t *buf, uint16_t length); /** - * @brief mqtt_unpack_pingresp Unpacks the MQTT PINGRESP message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks the MQTT PINGRESP message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_pingresp(uint8_t *buf, uint16_t length); /** - * @brief mqtt_unpack_disconnect Unpacks the MQTT DISCONNECT message - * @param [in] buf Buffer where the message is stored - * @param [in] length Message's length - * @return 0 on success - * @return -EINVAL if an invalid parameter was passed - * as an argument to this routine + * Unpacks the MQTT DISCONNECT message + * + * @param [in] buf Buffer where the message is stored + * @param [in] length Message's length + * + * @retval 0 on success + * @retval -EINVAL */ int mqtt_unpack_disconnect(uint8_t *buf, uint16_t length); From 79a064fae814d04fb615bc60a3975b934f4853c2 Mon Sep 17 00:00:00 2001 From: Flavio Santes Date: Sun, 12 Feb 2017 00:40:09 -0600 Subject: [PATCH 09/20] net/http: Add QEMU support to the HTTP server sample app This patch adds the QEMU prj file for the HTTP server sample app. Change-Id: I0b910b5ec9970a7ffe9621e19d9544d899c22132 Signed-off-by: Flavio Santes --- samples/net/http_server/prj_qemu_x86.conf | 30 +++++++++++++++++++++++ samples/net/http_server/testcase.ini | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 samples/net/http_server/prj_qemu_x86.conf diff --git a/samples/net/http_server/prj_qemu_x86.conf b/samples/net/http_server/prj_qemu_x86.conf new file mode 100644 index 00000000000..8e869d43eef --- /dev/null +++ b/samples/net/http_server/prj_qemu_x86.conf @@ -0,0 +1,30 @@ +CONFIG_NETWORKING=y +CONFIG_NET_TCP=y +CONFIG_RANDOM_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_LOG=y +CONFIG_NET_SLIP_TAP=y +CONFIG_INIT_STACKS=y + +CONFIG_NET_NBUF_RX_COUNT=16 +CONFIG_NET_NBUF_TX_COUNT=16 +CONFIG_NET_NBUF_DATA_COUNT=16 + +CONFIG_NET_IPV6_RA_RDNSS=y +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 + +CONFIG_STDOUT_CONSOLE=y + +CONFIG_HTTP_PARSER=y + +# Enable IPv6 support +CONFIG_NET_IPV6=n +# Enable IPv4 support +CONFIG_NET_IPV4=y + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1" + +CONFIG_NET_MAX_CONTEXTS=16 diff --git a/samples/net/http_server/testcase.ini b/samples/net/http_server/testcase.ini index 1c14f3d7052..6b7a95b312c 100644 --- a/samples/net/http_server/testcase.ini +++ b/samples/net/http_server/testcase.ini @@ -1,4 +1,4 @@ [test] tags = net http build_only = true -platform_whitelist = frdm_k64f +platform_whitelist = frdm_k64f qemu_x86 From f40bdd67ac1cdc963a25840b3801fc5b7090c8c4 Mon Sep 17 00:00:00 2001 From: Flavio Santes Date: Sun, 12 Feb 2017 00:43:34 -0600 Subject: [PATCH 10/20] net/http: Improve network configuration routines Modify the network setup routine to accept the following parameters: - network context - accept callback - server IP address - server port This change will allow us to reuse this routine for TLS. Change-Id: I1fdbaa908783c69f87863cbc597b42f39358762c Signed-off-by: Flavio Santes --- samples/net/http_server/src/http_server.c | 26 ++++++ samples/net/http_server/src/http_server.h | 4 + samples/net/http_server/src/main.c | 99 ++++++++--------------- 3 files changed, 64 insertions(+), 65 deletions(-) diff --git a/samples/net/http_server/src/http_server.c b/samples/net/http_server/src/http_server.c index 3355a4ce037..a94c59ede6b 100644 --- a/samples/net/http_server/src/http_server.c +++ b/samples/net/http_server/src/http_server.c @@ -21,6 +21,32 @@ NET_BUF_POOL_DEFINE(http_msg_pool, HTTP_BUF_CTR, HTTP_BUF_SIZE, 0, NULL); +void http_accept_cb(struct net_context *net_ctx, struct sockaddr *addr, + socklen_t addr_len, int status, void *data) +{ + struct http_server_ctx *http_ctx = NULL; + + ARG_UNUSED(addr_len); + ARG_UNUSED(data); + + if (status != 0) { + net_context_put(net_ctx); + return; + } + + print_client_banner(addr); + + http_ctx = http_ctx_get(); + if (!http_ctx) { + net_context_put(net_ctx); + return; + } + + http_ctx_set(http_ctx, net_ctx); + + net_context_recv(net_ctx, http_rx_tx, K_NO_WAIT, http_ctx); +} + /** * @brief http_ctx_release Releases an HTTP context * @return 0, future versions may return error codes diff --git a/samples/net/http_server/src/http_server.h b/samples/net/http_server/src/http_server.h index 45751c56fcf..5e00279d33f 100644 --- a/samples/net/http_server/src/http_server.h +++ b/samples/net/http_server/src/http_server.h @@ -9,6 +9,10 @@ #include +/* Callback executed when a new connection is accepted */ +void http_accept_cb(struct net_context *net_ctx, struct sockaddr *addr, + socklen_t addr_len, int status, void *data); + /** * @brief http_rx_tx Reads the HTTP request from the `rx` buffer * and writes an HTTP 1.1 200 OK response with client diff --git a/samples/net/http_server/src/main.c b/samples/net/http_server/src/main.c index c01d789bb07..e5ebd16e8e3 100644 --- a/samples/net/http_server/src/main.c +++ b/samples/net/http_server/src/main.c @@ -15,82 +15,49 @@ #include "http_write_utils.h" #include "config.h" -static void network_setup(void); +/* Sets the network parameters */ +static +int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb, + const char *addr, uint16_t port); void main(void) { + struct net_context *net_ctx = NULL; + http_ctx_init(); http_url_default_handler(http_write_soft_404_not_found); http_url_add("/headers", HTTP_URL_STANDARD, http_write_header_fields); http_url_add("/index.html", HTTP_URL_STANDARD, http_write_it_works); - network_setup(); + network_setup(&net_ctx, http_accept_cb, ZEPHYR_ADDR, ZEPHYR_PORT); } -/** - * @brief connection_cb Callback executed when a connection is accepted - * @param ctx Network context - * @param addr Client's address - * @param addr_len Address length - * @param status Status code, 0 on success, < 0 otherwise - * @param data User-provided data - */ -void connection_cb(struct net_context *net_ctx, struct sockaddr *addr, - socklen_t addr_len, int status, void *data) +static +int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb, + const char *addr, uint16_t port) { - struct http_server_ctx *http_ctx = NULL; - - ARG_UNUSED(addr_len); - ARG_UNUSED(data); - - if (status != 0) { - printk("Status code: %d\n", status); - net_context_put(net_ctx); - return; - } - - print_client_banner(addr); - - http_ctx = http_ctx_get(); - if (!http_ctx) { - printk("Unable to get free HTTP context\n"); - net_context_put(net_ctx); - return; - } - - http_ctx_set(http_ctx, net_ctx); - - net_context_recv(net_ctx, http_rx_tx, 0, http_ctx); -} - -/** - * @brief network_setup This routine configures the HTTP server. - * It puts the application in listening mode and - * installs the accept connection callback. - */ -static void network_setup(void) -{ - struct net_context *ctx = NULL; struct sockaddr local_sock; void *ptr; int rc; + *net_ctx = NULL; + #ifdef CONFIG_NET_IPV6 - net_sin6(&local_sock)->sin6_port = htons(ZEPHYR_PORT); - sock_addr.family = AF_INET6; + net_sin6(&local_sock)->sin6_port = htons(port); + local_sock.family = AF_INET6; ptr = &(net_sin6(&local_sock)->sin6_addr); - rc = net_addr_pton(AF_INET6, ZEPHYR_ADDR, ptr); + rc = net_addr_pton(AF_INET6, addr, ptr); #else - net_sin(&local_sock)->sin_port = htons(ZEPHYR_PORT); + net_sin(&local_sock)->sin_port = htons(port); local_sock.family = AF_INET; ptr = &(net_sin(&local_sock)->sin_addr); - rc = net_addr_pton(AF_INET, ZEPHYR_ADDR, ptr); + rc = net_addr_pton(AF_INET, addr, ptr); #endif if (rc) { - printk("Invalid IP address/Port: %s, %d\n", - ZEPHYR_ADDR, ZEPHYR_PORT); + printk("Invalid IP address/Port: %s, %d\n", addr, port); + return rc; } #ifdef CONFIG_NET_IPV6 @@ -102,41 +69,43 @@ static void network_setup(void) &net_sin(&local_sock)->sin_addr, NET_ADDR_MANUAL, 0); #endif - print_server_banner(&local_sock); #if defined(CONFIG_NET_IPV6) - rc = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &ctx); + rc = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, net_ctx); #else - rc = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ctx); + rc = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, net_ctx); #endif if (rc != 0) { printk("net_context_get error\n"); - return; + return rc; } - rc = net_context_bind(ctx, (const struct sockaddr *)&local_sock, + rc = net_context_bind(*net_ctx, (const struct sockaddr *)&local_sock, sizeof(local_sock)); if (rc != 0) { printk("net_context_bind error\n"); goto lb_error; } - rc = net_context_listen(ctx, 0); + rc = net_context_listen(*net_ctx, 0); if (rc != 0) { - printk("[%s:%d] net_context_listen %d, <%s>\n", - __func__, __LINE__, rc, RC_STR(rc)); + printk("net_context_listen error\n"); goto lb_error; } - rc = net_context_accept(ctx, connection_cb, 0, NULL); + rc = net_context_accept(*net_ctx, accept_cb, 0, NULL); if (rc != 0) { - printk("[%s:%d] net_context_accept %d, <%s>\n", - __func__, __LINE__, rc, RC_STR(rc)); + printk("net_context_accept error\n"); goto lb_error; } - return; + print_server_banner(&local_sock); + + return 0; lb_error: - net_context_put(ctx); + net_context_put(*net_ctx); + *net_ctx = NULL; + + return rc; } From bbada2de5047a66df393082d56595e608e161342 Mon Sep 17 00:00:00 2001 From: Marcus Shawcroft Date: Fri, 6 Jan 2017 22:20:47 +0000 Subject: [PATCH 11/20] eth/mcux: Add basic PHY support. Add basic PHY management sufficient to detect link up, link down and auto negotiated link speed / duplex. The PHY driver is implemented as a state machine that executed in the system work queue. The implementation is non blocking, using the MII interrupt to capture the completion of read and write events. This PHY management should be fairly generic. In the future, it may be beneficial to pull this code out as a standalone PHY driver for use with other ethernet drivers. JIRA: ZEP-1674 Change-Id: I3dcb5c14982ef4b40591fcf10d84840b8a2558e5 Signed-off-by: Marcus Shawcroft --- boards/arm/frdm_k64f/doc/frdm_k64f.rst | 10 +- drivers/ethernet/Kconfig.mcux | 7 + drivers/ethernet/eth_mcux.c | 196 +++++++++++++++++++++---- 3 files changed, 173 insertions(+), 40 deletions(-) diff --git a/boards/arm/frdm_k64f/doc/frdm_k64f.rst b/boards/arm/frdm_k64f/doc/frdm_k64f.rst index b67c5a8c8a0..fc2a98c1678 100644 --- a/boards/arm/frdm_k64f/doc/frdm_k64f.rst +++ b/boards/arm/frdm_k64f/doc/frdm_k64f.rst @@ -76,8 +76,7 @@ The frdm_k64f board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | SPI | on-chip | spi | +-----------+------------+-------------------------------------+ -| ETHERNET | on-chip | ethernet (work in progress, known | -| | | issues exist, see below) | +| ETHERNET | on-chip | ethernet | +-----------+------------+-------------------------------------+ | UART | on-chip | serial port-polling; | | | | serial port-interrupt | @@ -224,13 +223,6 @@ the following message: Hello World! arm -Work in progress and known issues -********************************* - -Ethernet PHY is currently initialized only at the application startup. -For successful initialization, a network cable must be connected between -the board and a host/router. If a cable is not connected when the board -is powered on or reset, the startup will be aborted with an error message. .. _FRDM-K64F Website: http://www.nxp.com/products/software-and-tools/hardware-development-tools/freedom-development-boards/freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F diff --git a/drivers/ethernet/Kconfig.mcux b/drivers/ethernet/Kconfig.mcux index 2661f2b91e7..383348e8ab5 100644 --- a/drivers/ethernet/Kconfig.mcux +++ b/drivers/ethernet/Kconfig.mcux @@ -15,6 +15,13 @@ menuconfig ETH_MCUX configuration change. if ETH_MCUX +config ETH_MCUX_PHY_TICK_MS + int "PHY poll period (ms)" + default 1000 + range 100 30000 + help + Set the PHY status polling period. + config ETH_MCUX_RX_BUFFERS int "Number of MCUX RX buffers" depends on ETH_MCUX diff --git a/drivers/ethernet/eth_mcux.c b/drivers/ethernet/eth_mcux.c index 2b1111b0898..e9012b1558f 100644 --- a/drivers/ethernet/eth_mcux.c +++ b/drivers/ethernet/eth_mcux.c @@ -1,15 +1,12 @@ /* MCUX Ethernet Driver * - * Copyright (c) 2016 ARM Ltd + * Copyright (c) 2016-2017 ARM Ltd * Copyright (c) 2016 Linaro Ltd * * SPDX-License-Identifier: Apache-2.0 */ -/* The driver performs one shot PHY setup. There is no support for - * PHY disconnect, reconnect or configuration change. The PHY setup, - * implemented via MCUX contains polled code that can block the - * initialization thread for a few seconds. +/* Driver Limitations: * * There is no statistics collection for either normal operation or * error behaviour. @@ -30,11 +27,27 @@ #include "fsl_phy.h" #include "fsl_port.h" +enum eth_mcux_phy_state { + eth_mcux_phy_state_initial, + eth_mcux_phy_state_reset, + eth_mcux_phy_state_autoneg, + eth_mcux_phy_state_restart, + eth_mcux_phy_state_read_status, + eth_mcux_phy_state_read_duplex, + eth_mcux_phy_state_wait +}; + struct eth_context { struct net_if *iface; enet_handle_t enet_handle; struct k_sem tx_buf_sem; + enum eth_mcux_phy_state phy_state; + bool link_up; + phy_duplex_t phy_duplex; + phy_speed_t phy_speed; uint8_t mac_addr[6]; + struct k_work phy_work; + struct k_delayed_work delayed_phy_work; /* TODO: FIXME. This Ethernet frame sized buffer is used for * interfacing with MCUX. How it works is that hardware uses * DMA scatter buffers to receive a frame, and then public @@ -70,6 +83,137 @@ rx_buffer[CONFIG_ETH_MCUX_RX_BUFFERS][ETH_MCUX_BUFFER_SIZE]; static uint8_t __aligned(ENET_BUFF_ALIGNMENT) tx_buffer[CONFIG_ETH_MCUX_TX_BUFFERS][ETH_MCUX_BUFFER_SIZE]; +static void eth_mcux_decode_duplex_and_speed(uint32_t status, + phy_duplex_t *p_phy_duplex, + phy_speed_t *p_phy_speed) +{ + switch (status & PHY_CTL1_SPEEDUPLX_MASK) { + case PHY_CTL1_10FULLDUPLEX_MASK: + *p_phy_duplex = kPHY_FullDuplex; + *p_phy_speed = kPHY_Speed10M; + break; + case PHY_CTL1_100FULLDUPLEX_MASK: + *p_phy_duplex = kPHY_FullDuplex; + *p_phy_speed = kPHY_Speed100M; + break; + case PHY_CTL1_100HALFDUPLEX_MASK: + *p_phy_duplex = kPHY_HalfDuplex; + *p_phy_speed = kPHY_Speed100M; + break; + case PHY_CTL1_10HALFDUPLEX_MASK: + *p_phy_duplex = kPHY_HalfDuplex; + *p_phy_speed = kPHY_Speed10M; + break; + } +} + +static void eth_mcux_phy_event(struct eth_context *context) +{ + uint32_t status; + bool link_up; + phy_duplex_t phy_duplex = kPHY_FullDuplex; + phy_speed_t phy_speed = kPHY_Speed100M; + const uint32_t phy_addr = 0; + + SYS_LOG_DBG("phy_state=%d", context->phy_state); + + switch (context->phy_state) { + case eth_mcux_phy_state_initial: + /* Reset the PHY. */ + ENET_StartSMIWrite(ENET, phy_addr, PHY_BASICCONTROL_REG, + kENET_MiiWriteValidFrame, + PHY_BCTL_RESET_MASK); + context->phy_state = eth_mcux_phy_state_reset; + break; + case eth_mcux_phy_state_reset: + /* Setup PHY autonegotiation. */ + ENET_StartSMIWrite(ENET, phy_addr, PHY_AUTONEG_ADVERTISE_REG, + kENET_MiiWriteValidFrame, + (PHY_100BASETX_FULLDUPLEX_MASK | + PHY_100BASETX_HALFDUPLEX_MASK | + PHY_10BASETX_FULLDUPLEX_MASK | + PHY_10BASETX_HALFDUPLEX_MASK | 0x1U)); + context->phy_state = eth_mcux_phy_state_autoneg; + break; + case eth_mcux_phy_state_autoneg: + /* Setup PHY autonegotiation. */ + ENET_StartSMIWrite(ENET, phy_addr, PHY_BASICCONTROL_REG, + kENET_MiiWriteValidFrame, + (PHY_BCTL_AUTONEG_MASK | + PHY_BCTL_RESTART_AUTONEG_MASK)); + context->phy_state = eth_mcux_phy_state_restart; + break; + case eth_mcux_phy_state_wait: + case eth_mcux_phy_state_restart: + /* Start reading the PHY basic status. */ + ENET_StartSMIRead(ENET, phy_addr, PHY_BASICSTATUS_REG, + kENET_MiiReadValidFrame); + context->phy_state = eth_mcux_phy_state_read_status; + break; + case eth_mcux_phy_state_read_status: + /* PHY Basic status is available. */ + status = ENET_ReadSMIData(ENET); + link_up = status & PHY_BSTATUS_LINKSTATUS_MASK; + if (link_up && !context->link_up) { + /* Start reading the PHY control register. */ + ENET_StartSMIRead(ENET, phy_addr, PHY_CONTROL1_REG, + kENET_MiiReadValidFrame); + context->link_up = link_up; + context->phy_state = eth_mcux_phy_state_read_duplex; + } else if (!link_up && context->link_up) { + SYS_LOG_INF("Link down"); + context->link_up = link_up; + k_delayed_work_submit(&context->delayed_phy_work, + CONFIG_ETH_MCUX_PHY_TICK_MS); + context->phy_state = eth_mcux_phy_state_wait; + } else { + k_delayed_work_submit(&context->delayed_phy_work, + CONFIG_ETH_MCUX_PHY_TICK_MS); + context->phy_state = eth_mcux_phy_state_wait; + } + + break; + case eth_mcux_phy_state_read_duplex: + /* PHY control register is available. */ + status = ENET_ReadSMIData(ENET); + eth_mcux_decode_duplex_and_speed(status, + &phy_duplex, + &phy_speed); + if (phy_speed != context->phy_speed || + phy_duplex != context->phy_duplex) { + context->phy_speed = phy_speed; + context->phy_duplex = phy_duplex; + ENET_SetMII(ENET, + (enet_mii_speed_t) phy_speed, + (enet_mii_duplex_t) phy_duplex); + } + + SYS_LOG_INF("Enabled %sM %s-duplex mode.", + (phy_speed ? "100" : "10"), + (phy_duplex ? "full" : "half")); + k_delayed_work_submit(&context->delayed_phy_work, + CONFIG_ETH_MCUX_PHY_TICK_MS); + context->phy_state = eth_mcux_phy_state_wait; + break; + } +} + +static void eth_mcux_phy_work(struct k_work *item) +{ + struct eth_context *context = + CONTAINER_OF(item, struct eth_context, phy_work); + + eth_mcux_phy_event(context); +} + +static void eth_mcux_delayed_phy_work(struct k_work *item) +{ + struct eth_context *context = + CONTAINER_OF(item, struct eth_context, delayed_phy_work); + + eth_mcux_phy_event(context); +} + static int eth_tx(struct net_if *iface, struct net_buf *buf) { struct eth_context *context = iface->dev->driver_data; @@ -265,9 +409,6 @@ static int eth_0_init(struct device *dev) struct eth_context *context = dev->driver_data; enet_config_t enet_config; uint32_t sys_clock; - const uint32_t phy_addr = 0x0; - bool link; - status_t status; enet_buffer_config_t buffer_config = { .rxBdNumber = CONFIG_ETH_MCUX_RX_BUFFERS, .txBdNumber = CONFIG_ETH_MCUX_TX_BUFFERS, @@ -281,34 +422,16 @@ static int eth_0_init(struct device *dev) k_sem_init(&context->tx_buf_sem, CONFIG_ETH_MCUX_TX_BUFFERS, CONFIG_ETH_MCUX_TX_BUFFERS); + k_work_init(&context->phy_work, eth_mcux_phy_work); + k_delayed_work_init(&context->delayed_phy_work, + eth_mcux_delayed_phy_work); sys_clock = CLOCK_GetFreq(kCLOCK_CoreSysClk); ENET_GetDefaultConfig(&enet_config); enet_config.interrupt |= kENET_RxFrameInterrupt; enet_config.interrupt |= kENET_TxFrameInterrupt; - - status = PHY_Init(ENET, phy_addr, sys_clock); - if (status) { - SYS_LOG_ERR("PHY_Init() failed: %d", status); - return 1; - } - - PHY_GetLinkStatus(ENET, phy_addr, &link); - if (link) { - phy_speed_t phy_speed; - phy_duplex_t phy_duplex; - - PHY_GetLinkSpeedDuplex(ENET, phy_addr, &phy_speed, &phy_duplex); - enet_config.miiSpeed = (enet_mii_speed_t) phy_speed; - enet_config.miiDuplex = (enet_mii_duplex_t) phy_duplex; - - SYS_LOG_INF("Enabled %dM %s-duplex mode.", - (phy_speed ? 100 : 10), - (phy_duplex ? "full" : "half")); - } else { - SYS_LOG_INF("Link down."); - } + enet_config.interrupt |= kENET_MiiInterrupt; #if defined(CONFIG_ETH_MCUX_0_RANDOM_MAC) generate_mac(context->mac_addr); @@ -321,6 +444,8 @@ static int eth_0_init(struct device *dev) context->mac_addr, sys_clock); + ENET_SetSMI(ENET, sys_clock, false); + SYS_LOG_DBG("MAC %02x:%02x:%02x:%02x:%02x:%02x", context->mac_addr[0], context->mac_addr[1], context->mac_addr[2], context->mac_addr[3], @@ -329,6 +454,9 @@ static int eth_0_init(struct device *dev) ENET_SetCallback(&context->enet_handle, eth_callback, dev); eth_0_config_func(); ENET_ActiveRead(ENET); + + k_work_submit(&context->phy_work); + return 0; } @@ -367,11 +495,17 @@ static void eth_mcux_error_isr(void *p) { struct device *dev = p; struct eth_context *context = dev->driver_data; + uint32_t pending = ENET_GetInterruptStatus(ENET); - ENET_ErrorIRQHandler(ENET, &context->enet_handle); + if (pending & ENET_EIR_MII_MASK) { + k_work_submit(&context->phy_work); + ENET_ClearInterruptStatus(ENET, kENET_MiiInterrupt); + } } static struct eth_context eth_0_context = { + .phy_duplex = kPHY_FullDuplex, + .phy_speed = kPHY_Speed100M, .mac_addr = { /* Freescale's OUI */ 0x00, From d502c24a5d546606c7127427bea2ebd15d0967b9 Mon Sep 17 00:00:00 2001 From: Richard Peters Date: Fri, 10 Feb 2017 20:48:52 +0100 Subject: [PATCH 12/20] samples: net: Add .conf file for qemu_cortex_m3 in echo_* Added conf files for qemu_cortex_m3, until a better solution than CONF_FILE=prj_$(BOARD).conf exists in the makefile. Change-Id: I1edc4f37bb3c49ecb65abf7c93b3c9f4608d601e Signed-off-by: Richard Peters --- .../net/echo_client/prj_qemu_cortex_m3.conf | 26 ++++++++++++++++++ .../net/echo_server/prj_qemu_cortex_m3.conf | 27 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 samples/net/echo_client/prj_qemu_cortex_m3.conf create mode 100644 samples/net/echo_server/prj_qemu_cortex_m3.conf diff --git a/samples/net/echo_client/prj_qemu_cortex_m3.conf b/samples/net/echo_client/prj_qemu_cortex_m3.conf new file mode 100644 index 00000000000..b26453750e4 --- /dev/null +++ b/samples/net/echo_client/prj_qemu_cortex_m3.conf @@ -0,0 +1,26 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=y +CONFIG_NET_UDP=y +CONFIG_NET_TCP=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_LOG=y +CONFIG_NET_SLIP_TAP=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_NBUF_RX_COUNT=14 +CONFIG_NET_NBUF_TX_COUNT=14 +CONFIG_NET_NBUF_DATA_COUNT=30 +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 +CONFIG_NET_MAX_CONTEXTS=10 + +CONFIG_NET_SHELL=y + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::2" +CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::1" +CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.2" +CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.1" diff --git a/samples/net/echo_server/prj_qemu_cortex_m3.conf b/samples/net/echo_server/prj_qemu_cortex_m3.conf new file mode 100644 index 00000000000..663d5d73d50 --- /dev/null +++ b/samples/net/echo_server/prj_qemu_cortex_m3.conf @@ -0,0 +1,27 @@ + +CONFIG_NETWORKING=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=y +CONFIG_NET_UDP=y +CONFIG_NET_TCP=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_LOG=y +CONFIG_NET_SLIP_TAP=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_NBUF_RX_COUNT=16 +CONFIG_NET_NBUF_TX_COUNT=16 +CONFIG_NET_NBUF_DATA_COUNT=40 +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 +CONFIG_NET_MAX_CONTEXTS=16 + +CONFIG_NET_SHELL=y + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2" +CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2" From 45e199c812ebfdc3e2a98697971712b10d6d58ed Mon Sep 17 00:00:00 2001 From: Marcus Shawcroft Date: Fri, 10 Feb 2017 15:19:11 +0000 Subject: [PATCH 13/20] net/dhcpv4: Fix event/state mismatch Fix long standing issue where a dhcpv4 message type is compared against a dhcpv4 state machine state name rather than a message type. The issue probably arizes due to the similarity in names between messages and states. By accident, the relevant message types and states happen to share the same numbers, hence the implementation works, but is ill defined. Change-Id: I5c028de4336ff42f6696e28b3492c932c58b5a05 Signed-off-by: Marcus Shawcroft --- subsys/net/ip/dhcpv4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/ip/dhcpv4.c b/subsys/net/ip/dhcpv4.c index 08277c49702..7d888578994 100644 --- a/subsys/net/ip/dhcpv4.c +++ b/subsys/net/ip/dhcpv4.c @@ -709,7 +709,7 @@ static inline void handle_dhcpv4_reply(struct net_if *iface, uint8_t msg_type) * Rest of the replies are discarded. */ if (iface->dhcpv4.state == NET_DHCPV4_DISCOVER) { - if (msg_type != NET_DHCPV4_OFFER) { + if (msg_type != DHCPV4_MSG_TYPE_OFFER) { NET_DBG("Reply ignored"); return; } @@ -724,7 +724,7 @@ static inline void handle_dhcpv4_reply(struct net_if *iface, uint8_t msg_type) iface->dhcpv4.state == NET_DHCPV4_RENEWAL) { uint32_t timeout; - if (msg_type != NET_DHCPV4_ACK) { + if (msg_type != DHCPV4_MSG_TYPE_ACK) { NET_DBG("Reply ignored"); return; } From ccd6d8c79f1cce7786abfdd5dad966c07ae9c137 Mon Sep 17 00:00:00 2001 From: Marcus Shawcroft Date: Thu, 9 Feb 2017 15:57:58 +0000 Subject: [PATCH 14/20] net/dhcpv4: Remove unused dhcpv4 offer state The offer state is unused, remove it. Change-Id: I9d6217dae291bb90c57c77ce439809bf7e9a9177 Signed-off-by: Marcus Shawcroft --- include/net/dhcpv4.h | 1 - subsys/net/ip/dhcpv4.c | 1 - subsys/net/ip/net_shell.c | 2 -- 3 files changed, 4 deletions(-) diff --git a/include/net/dhcpv4.h b/include/net/dhcpv4.h index 6c0ba84955b..a330debcb93 100644 --- a/include/net/dhcpv4.h +++ b/include/net/dhcpv4.h @@ -28,7 +28,6 @@ enum net_dhcpv4_state { NET_DHCPV4_INIT, NET_DHCPV4_DISCOVER, - NET_DHCPV4_OFFER, NET_DHCPV4_REQUEST, NET_DHCPV4_RENEWAL, NET_DHCPV4_ACK, diff --git a/subsys/net/ip/dhcpv4.c b/subsys/net/ip/dhcpv4.c index 7d888578994..1cbd2f4cf84 100644 --- a/subsys/net/ip/dhcpv4.c +++ b/subsys/net/ip/dhcpv4.c @@ -120,7 +120,6 @@ net_dhcpv4_state_name(enum net_dhcpv4_state state) static const char * const name[] = { "init", "discover", - "offer", "request", "renewal", "ack" diff --git a/subsys/net/ip/net_shell.c b/subsys/net/ip/net_shell.c index f51faafa521..e95f430b759 100644 --- a/subsys/net/ip/net_shell.c +++ b/subsys/net/ip/net_shell.c @@ -80,8 +80,6 @@ static inline const char *dhcpv4state2str(enum net_dhcpv4_state state) return "init"; case NET_DHCPV4_DISCOVER: return "discover"; - case NET_DHCPV4_OFFER: - return "offer"; case NET_DHCPV4_REQUEST: return "request"; case NET_DHCPV4_RENEWAL: From 0296cdd728b6520635a99ab503a8774277aac150 Mon Sep 17 00:00:00 2001 From: Marcus Shawcroft Date: Fri, 10 Feb 2017 15:13:09 +0000 Subject: [PATCH 15/20] net/dhcpv4: Ensure udp header checksum is computed correctly The dhcpv4 client code builds ip and udp packets from scratch rather than using the network stack to do the heavy lifting (why ?). When it computes the udp checksum of each packet it builds it neglects to clear any preexisting detritus from the checksum field. The result of this is that some packets will be built with correct checksums and some will be built with incorrect checksums. This is the underlying reason that the dhcp client often taken many retransmissions and elapsed time before in order to acquire an IP address. Change-Id: Iebd1ed34e06f7f2e53d45f6d1555e22f48490287 Signed-off-by: Marcus Shawcroft --- subsys/net/ip/dhcpv4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/net/ip/dhcpv4.c b/subsys/net/ip/dhcpv4.c index 1cbd2f4cf84..b38e8e1ac60 100644 --- a/subsys/net/ip/dhcpv4.c +++ b/subsys/net/ip/dhcpv4.c @@ -315,6 +315,7 @@ static void setup_header(struct net_buf *buf) udp->src_port = htons(DHCPV4_CLIENT_PORT); udp->dst_port = htons(DHCPV4_SERVER_PORT); udp->len = htons(len); + udp->chksum = 0; udp->chksum = ~net_calc_chksum_udp(buf); } From f994efa8c1be00d8ffada4b8e918688e48321ffb Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Fri, 3 Feb 2017 13:45:11 +0100 Subject: [PATCH 16/20] net/mqtt: Add BT support to MQTT publisher sample Change-Id: I56d54c3550a530bf250210e939840e7c7e89c5d9 Signed-off-by: Jorge Ramirez-Ortiz --- .../net/mqtt_publisher/prj_96b_nitrogen.conf | 65 +++++++++++++++++++ samples/net/mqtt_publisher/src/Makefile | 4 ++ samples/net/mqtt_publisher/src/main.c | 59 ++++++++++++++++- samples/net/mqtt_publisher/testcase.ini | 5 ++ 4 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 samples/net/mqtt_publisher/prj_96b_nitrogen.conf diff --git a/samples/net/mqtt_publisher/prj_96b_nitrogen.conf b/samples/net/mqtt_publisher/prj_96b_nitrogen.conf new file mode 100644 index 00000000000..2268eff7330 --- /dev/null +++ b/samples/net/mqtt_publisher/prj_96b_nitrogen.conf @@ -0,0 +1,65 @@ +CONFIG_INIT_STACKS=y +CONFIG_NETWORKING=y + +CONFIG_NET_TCP=y +CONFIG_NET_UDP=n +CONFIG_NET_ARP=y +CONFIG_NET_L2_BLUETOOTH=y +CONFIG_NET_L2_BLUETOOTH_SEC_LEVEL=1 +CONFIG_NET_LOG=y +CONFIG_NET_IPV6_RA_RDNSS=y +CONFIG_NET_IPV4=n +CONFIG_NET_IPV6=y +CONFIG_NET_IPV6_MAX_NEIGHBORS=8 +CONFIG_NET_MAX_CONTEXTS=5 +CONFIG_NET_SHELL=y + +CONFIG_NET_NBUF_RX_COUNT=16 +CONFIG_NET_NBUF_TX_COUNT=16 +CONFIG_NET_NBUF_DATA_SIZE=256 +CONFIG_NET_NBUF_DATA_COUNT=30 + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2" + +CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.168.1.101" +CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.168.1.10" + +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=3 + +CONFIG_PRINTK=y + +CONFIG_MQTT_LIB=y + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_RANDOM_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_TIMER_RANDOM_GENERATOR=y + +CONFIG_BLUETOOTH_RX_STACK_SIZE=1024 +CONFIG_BLUETOOTH_DEVICE_NAME="Zephyr" + +CONFIG_BLUETOOTH_L2CAP_TX_BUF_COUNT=3 +CONFIG_BLUETOOTH_L2CAP_TX_MTU=65 +CONFIG_BLUETOOTH_L2CAP_TX_USER_DATA_SIZE=4 + +CONFIG_BLUETOOTH_HCI_TX_STACK_SIZE=640 +CONFIG_BLUETOOTH_HCI_HOST=y +CONFIG_BLUETOOTH_RECV_IS_RX_THREAD=y +CONFIG_BLUETOOTH_HCI_CMD_COUNT=2 +CONFIG_BLUETOOTH_MAX_CMD_LEN=64 +CONFIG_BLUETOOTH_RX_BUF_COUNT=20 +CONFIG_BLUETOOTH_RX_BUF_LEN=1024 +CONFIG_BLUETOOTH_CONN=y +CONFIG_BLUETOOTH_SIGNING=y +CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BLUETOOTH_DEBUG=y +CONFIG_BLUETOOTH_DEBUG_LOG=y +CONFIG_BLUETOOTH_DEBUG_COLOR=y + +CONFIG_CONSOLE_SHELL=y +CONFIG_CONSOLE_SHELL_STACKSIZE=2000 +CONFIG_CONSOLE_SHELL_MAX_CMD_QUEUED=3 diff --git a/samples/net/mqtt_publisher/src/Makefile b/samples/net/mqtt_publisher/src/Makefile index 9715a81e71f..bd5dd34b81f 100644 --- a/samples/net/mqtt_publisher/src/Makefile +++ b/samples/net/mqtt_publisher/src/Makefile @@ -6,3 +6,7 @@ obj-y += main.o +ifeq ($(CONFIG_NET_L2_BLUETOOTH), y) +ccflags-y +=-I${ZEPHYR_BASE}/samples/bluetooth/ +obj-y += ../../../bluetooth/gatt/ipss.o +endif diff --git a/samples/net/mqtt_publisher/src/main.c b/samples/net/mqtt_publisher/src/main.c index 909a1d21123..ce7289bb28c 100644 --- a/samples/net/mqtt_publisher/src/main.c +++ b/samples/net/mqtt_publisher/src/main.c @@ -14,6 +14,12 @@ #include #include +#if defined(CONFIG_NET_L2_BLUETOOTH) +#include +#include +#include +#endif + #include "config.h" /** @@ -334,6 +340,29 @@ int set_addr(struct sockaddr *sock_addr, const char *addr, uint16_t port) return rc; } +#if defined(CONFIG_NET_L2_BLUETOOTH) +static bool bt_connected; + +static +void bt_connect_cb(struct bt_conn *conn, uint8_t err) +{ + bt_connected = true; +} + +static +void bt_disconnect_cb(struct bt_conn *conn, uint8_t reason) +{ + bt_connected = false; + printk("bt disconnected (reason %u)\n", reason); +} + +static +struct bt_conn_cb bt_conn_cb = { + .connected = bt_connect_cb, + .disconnected = bt_disconnect_cb, +}; +#endif + int network_setup(struct net_context **net_ctx, const char *local_addr, const char *server_addr, uint16_t server_port) { @@ -345,11 +374,37 @@ int network_setup(struct net_context **net_ctx, const char *local_addr, socklen_t addr_len = sizeof(struct sockaddr_in); sa_family_t family = AF_INET; #endif - struct sockaddr local_sock; - struct sockaddr server_sock; + struct sockaddr server_sock, local_sock; void *p; int rc; +#if defined(CONFIG_NET_L2_BLUETOOTH) + const char *progress_mark = "/-\\|"; + int i = 0; + + rc = bt_enable(NULL); + if (rc) { + printk("bluetooth init failed\n"); + return rc; + } + + ipss_init(); + bt_conn_cb_register(&bt_conn_cb); + rc = ipss_advertise(); + if (rc) { + printk("advertising failed to start\n"); + return rc; + } + + printk("\nwaiting for bt connection: "); + while (bt_connected == false) { + k_sleep(250); + printk("%c\b", progress_mark[i]); + i = (i + 1) % (sizeof(progress_mark) - 1); + } + printk("\n"); +#endif + rc = set_addr(&local_sock, local_addr, 0); if (rc) { printk("set_addr (local) error\n"); diff --git a/samples/net/mqtt_publisher/testcase.ini b/samples/net/mqtt_publisher/testcase.ini index 16ecfdae3c8..4daf6534fcb 100644 --- a/samples/net/mqtt_publisher/testcase.ini +++ b/samples/net/mqtt_publisher/testcase.ini @@ -2,3 +2,8 @@ tags = net mqtt build_only = true platform_whitelist = frdm_k64f + +[test_bt] +tags = net mqtt bluetooth +build_only = true +platform_whitelist = 96b_nitrogen From d599af40c8f11974c6e0eb6d3f48a4644504a9d1 Mon Sep 17 00:00:00 2001 From: Flavio Santes Date: Sun, 12 Feb 2017 01:04:39 -0600 Subject: [PATCH 17/20] ext/lib/mbedtls: Add the TLS configuration file This patch adds the TLS configuration file required by mbed. Change-Id: I8d99f27e028775de153a69cdd6706b8e2d0a3d9b Signed-off-by: Flavio Santes --- .../mbedtls/configs/config-mini-tls1_2.h | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 ext/lib/crypto/mbedtls/configs/config-mini-tls1_2.h diff --git a/ext/lib/crypto/mbedtls/configs/config-mini-tls1_2.h b/ext/lib/crypto/mbedtls/configs/config-mini-tls1_2.h new file mode 100644 index 00000000000..e39c3cfe0f7 --- /dev/null +++ b/ext/lib/crypto/mbedtls/configs/config-mini-tls1_2.h @@ -0,0 +1,91 @@ +/* + * Minimal configuration for TLS 1.1 (RFC 4346) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Minimal configuration for TLS 1.1 (RFC 4346), implementing only the + * required ciphersuite: MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_PLATFORM_EXIT_ALT +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define MBEDTLS_PLATFORM_PRINTF_ALT + +#if !defined(CONFIG_ARM) +#define MBEDTLS_HAVE_ASM +#endif + +#if defined(CONFIG_MBEDTLS_TEST) +#define MBEDTLS_SELF_TEST +#define MBEDTLS_DEBUG_C +#else +#define MBEDTLS_ENTROPY_C +#endif + +/* mbed TLS feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_DES_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +/* For test certificates */ +#define MBEDTLS_BASE64_C +#define MBEDTLS_CERTS_C +#define MBEDTLS_PEM_PARSE_C + + +#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024 + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ From 5035f97686498fb9312d4045ead726acbdd1b075 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 8 Feb 2017 13:42:40 +0300 Subject: [PATCH 18/20] eth/mcux: Add temporary workaround to unbreak IPv6 ND features. This is a workaround for lack of driver API support for multicast management. So, instead we want to receive all multicast frames "by default", or otherwise basic IPv6 features, like address resolution, don't work. On Kinetis Ethernet controller, that translates to enabling promiscuous mode. The real fix depends on ZEP-1673. Change-Id: I98a27584be65bdc405de005383eb30bad2a7fcfc Signed-off-by: Paul Sokolovsky --- drivers/ethernet/eth_mcux.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/ethernet/eth_mcux.c b/drivers/ethernet/eth_mcux.c index e9012b1558f..310f53720e1 100644 --- a/drivers/ethernet/eth_mcux.c +++ b/drivers/ethernet/eth_mcux.c @@ -432,6 +432,14 @@ static int eth_0_init(struct device *dev) enet_config.interrupt |= kENET_RxFrameInterrupt; enet_config.interrupt |= kENET_TxFrameInterrupt; enet_config.interrupt |= kENET_MiiInterrupt; + /* FIXME: Workaround for lack of driver API support for multicast + * management. So, instead we want to receive all multicast + * frames "by default", or otherwise basic IPv6 features, like + * address resolution, don't work. On Kinetis Ethernet controller, + * that translates to enabling promiscuous mode. The real + * fix depends on https://jira.zephyrproject.org/browse/ZEP-1673. + */ + enet_config.macSpecialConfig |= kENET_ControlPromiscuousEnable; #if defined(CONFIG_ETH_MCUX_0_RANDOM_MAC) generate_mac(context->mac_addr); From f054d3e897db4aa92a0f4ee78afeba715961d0b5 Mon Sep 17 00:00:00 2001 From: Sergio Rodriguez Date: Mon, 13 Feb 2017 17:39:38 -0800 Subject: [PATCH 19/20] libc/include: Adding time.h Dummy time.h to fulfill the compilations requirements of certain libraries i.e. mbedTLS Change-Id: I07e66dbf07337b935dabe9eecdf1be3850bbf394 Signed-off-by: Sergio Rodriguez --- lib/libc/minimal/include/time.h | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 lib/libc/minimal/include/time.h diff --git a/lib/libc/minimal/include/time.h b/lib/libc/minimal/include/time.h new file mode 100644 index 00000000000..ecb198e1ac8 --- /dev/null +++ b/lib/libc/minimal/include/time.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +/* Dummy time.h to fulfill the requirements of certain libraries + * i.e. mbedTLS + */ From de60e4c8cd4bf7ee27e720b874502626c10ea23e Mon Sep 17 00:00:00 2001 From: Sergio Rodriguez Date: Fri, 10 Feb 2017 11:29:58 -0800 Subject: [PATCH 20/20] samples/net/http: Add HTTP over TLS sample application Add the HTTPS (HTTP over TLS) server sample application on top of the current HTTP Parser Library and mbedTLS. This code uses TLS to stablish a secure connection and HTTP parser to identify the request and the proper response. Jira: ZEP-799 Change-Id: Ifbbcd0347bec47d12158440e50a82dc2966334d3 Signed-off-by: Sergio Rodriguez Signed-off-by: Flavio Santes --- samples/net/http_server/README.rst | 57 ++- samples/net/http_server/prj_qemu_x86.conf | 4 + samples/net/http_server/src/Makefile | 5 + samples/net/http_server/src/config.h | 4 + samples/net/http_server/src/https_server.c | 406 +++++++++++++++++++++ samples/net/http_server/src/main.c | 7 + samples/net/http_server/src/ssl_utils.c | 295 +++++++++++++++ samples/net/http_server/src/ssl_utils.h | 37 ++ samples/net/http_server/src/test_certs.h | 92 +++++ 9 files changed, 906 insertions(+), 1 deletion(-) create mode 100644 samples/net/http_server/src/https_server.c create mode 100644 samples/net/http_server/src/ssl_utils.c create mode 100644 samples/net/http_server/src/ssl_utils.h create mode 100644 samples/net/http_server/src/test_certs.h diff --git a/samples/net/http_server/README.rst b/samples/net/http_server/README.rst index 27b77829c60..792bbdaa1e6 100644 --- a/samples/net/http_server/README.rst +++ b/samples/net/http_server/README.rst @@ -109,7 +109,6 @@ Refer to the board documentation in Zephyr, :ref:`frdm_k64f`, for more information about this board and how to access the FRDM serial console under other operating systems. - Sample Output ============= @@ -223,6 +222,60 @@ and this is the HTML message that wget will save:

404 Not Found

+HTTPS Server +============ + +The sample code also includes a HTTPS (HTTP over TLS) server example +running side by side with the HTTP server, this server runs on qemu. +In order to compile and run the code execute: + +.. code-block:: console + + make BOARD=qemu_x86 run + +The sample code supports only one hard-coded valid URL (index.html) and +will return 404 code for other requests. + +Sample Output +============= + +The app will show the following on the screen: + +.. code-block:: console + + Zephyr HTTP Server + Address: 192.0.2.1, port: 80 + Zephyr HTTPS Server + Address: 192.0.2.1, port: 443 + failed + ! mbedtls_ssl_handshake returned -29312 + +Now execute the following command on a different terminal window + +.. code-block:: console + + wget https://192.0.2.1 --no-check-certificate + +This will be shown on the screen + +.. code-block:: console + + Connecting to 192.0.2.1:443... connected. + WARNING: cannot verify 192.0.2.1's certificate + Unable to locally verify the issuer's authority. + HTTP request sent, awaiting response... 200 OK + Length: unspecified [text/html] + Saving to: ‘index.html’ + + index.html [ <=> ] + +The inspection of the file index.html will show + +.. code-block:: console + +

Zephyr TLS Test Server

+

Successful connection

+ Known Issues and Limitations ============================ @@ -230,3 +283,5 @@ Known Issues and Limitations chunk transfer mode. - Clients must close the connection to allow the HTTP server to release the network context and accept another connection. +- The use of mbedTLS and IPv6 takes more than the available ram for the + emulation platform, so only IPv4 works for now in QEMU. diff --git a/samples/net/http_server/prj_qemu_x86.conf b/samples/net/http_server/prj_qemu_x86.conf index 8e869d43eef..88ba68d55cd 100644 --- a/samples/net/http_server/prj_qemu_x86.conf +++ b/samples/net/http_server/prj_qemu_x86.conf @@ -28,3 +28,7 @@ CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1" CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1" CONFIG_NET_MAX_CONTEXTS=16 + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_CFG_FILE="config-mini-tls1_2.h" diff --git a/samples/net/http_server/src/Makefile b/samples/net/http_server/src/Makefile index 11d9be11798..5219783b92f 100644 --- a/samples/net/http_server/src/Makefile +++ b/samples/net/http_server/src/Makefile @@ -8,3 +8,8 @@ obj-y += main.o obj-y += http_utils.o obj-y += http_server.o obj-y += http_write_utils.o +ifdef CONFIG_MBEDTLS +obj-y += https_server.o ssl_utils.o +endif + + diff --git a/samples/net/http_server/src/config.h b/samples/net/http_server/src/config.h index 672b663633a..054a4c4e3bc 100644 --- a/samples/net/http_server/src/config.h +++ b/samples/net/http_server/src/config.h @@ -25,4 +25,8 @@ #define APP_SLEEP_MSECS 500 +#ifdef CONFIG_MBEDTLS +#define SERVER_PORT 443 +#endif + #endif diff --git a/samples/net/http_server/src/https_server.c b/samples/net/http_server/src/https_server.c new file mode 100644 index 00000000000..6173c7ec21a --- /dev/null +++ b/samples/net/http_server/src/https_server.c @@ -0,0 +1,406 @@ +/* Minimal TLS server. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * SPDX-License-Identifier: Apache-2.0 + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#include +#include + +#include +#include + +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_time_t time_t +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#include +#include +#include +#include "config.h" +#include "ssl_utils.h" +#include "test_certs.h" + +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" + +#if defined(MBEDTLS_DEBUG_C) +#include "mbedtls/debug.h" +#define DEBUG_THRESHOLD 0 +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +static unsigned char heap[12000]; +#endif + +/* + * Hardcoded values for server host and port + */ + +static const char *pers = "tls_server"; + +#if defined(CONFIG_NET_IPV6) +static struct in6_addr server_addr; +#else +static struct in_addr server_addr; +#endif + +struct parsed_url { + const char *url; + uint16_t url_len; +}; + +#define HTTP_RESPONSE \ + "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ + "

Zephyr TLS Test Server

\r\n" \ + "

Successful connection

\r\n" + +#define HTTP_NOT_FOUND \ + "HTTP/1.0 404 NOT FOUND\r\nContent-Type: text/html\r\n\r\n" \ + "

Zephyr TLS page not found

\r\n" \ + "

Successful connection

\r\n" + +static void my_debug(void *ctx, int level, + const char *file, int line, const char *str) +{ + const char *p, *basename; + + ARG_UNUSED(ctx); + + /* Extract basename from file */ + for (p = basename = file; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') { + basename = p + 1; + } + + } + + mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); +} + +static int entropy_source(void *data, unsigned char *output, size_t len, + size_t *olen) +{ + uint32_t seed; + + ARG_UNUSED(data); + + seed = sys_rand32_get(); + + if (len > sizeof(seed)) { + len = sizeof(seed); + } + + memcpy(output, &seed, len); + + *olen = len; + return 0; +} + +static +int on_url(struct http_parser *parser, const char *at, size_t length) +{ + struct parsed_url *req = (struct parsed_url *)parser->data; + + req->url = at; + req->url_len = length; + + return 0; +} + +static unsigned char payload[256]; + +void https_server(void) +{ + struct ssl_context ctx; + struct parsed_url request; + int ret, len = 0; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt srvcert; + mbedtls_pk_context pkey; + + mbedtls_platform_set_printf(printk); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); +#endif + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold(DEBUG_THRESHOLD); + mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); +#endif + mbedtls_x509_crt_init(&srvcert); + mbedtls_pk_init(&pkey); + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + /* + * 1. Load the certificates and private RSA key + */ + + ret = mbedtls_x509_crt_parse(&srvcert, rsa_example_cert_der, + rsa_example_cert_der_len); + if (ret != 0) { + mbedtls_printf(" failed\n !" + " mbedtls_x509_crt_parse returned %d\n\n", ret); + goto exit; + } + + ret = mbedtls_pk_parse_key(&pkey, rsa_example_keypair_der, + rsa_example_keypair_der_len, NULL, 0); + if (ret != 0) { + mbedtls_printf(" failed\n !" + " mbedtls_pk_parse_key returned %d\n\n", ret); + goto exit; + } + + /* + * 3. Seed the RNG + */ + + mbedtls_entropy_add_source(&entropy, entropy_source, NULL, + MBEDTLS_ENTROPY_MAX_GATHER, + MBEDTLS_ENTROPY_SOURCE_STRONG); + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (ret != 0) { + mbedtls_printf(" failed\n !" + " mbedtls_ctr_drbg_seed returned %d\n", ret); + goto exit; + } + + /* + * 4. Setup stuff + */ + ret = mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if (ret != 0) { + mbedtls_printf(" failed\n !" + " mbedtls_ssl_config_defaults returned %d\n\n", + ret); + goto exit; + } + + mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); + mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); + + mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL); + ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey); + if (ret != 0) { + mbedtls_printf(" failed\n !" + " mbedtls_ssl_conf_own_cert returned %d\n\n", + ret); + goto exit; + } + + ret = mbedtls_ssl_setup(&ssl, &conf); + if (ret != 0) { + mbedtls_printf(" failed\n !" + " mbedtls_ssl_setup returned %d\n\n", ret); + goto exit; + } + + /* + * 3. Wait until a client connects + */ + ret = ssl_init(&ctx, &server_addr); + if (ret != 0) { + mbedtls_printf(" failed\n ! ssl_init returned %d\n\n", ret); + goto exit; + + } + + /* + * 4. Prepare http parser + */ + http_parser_init(&ctx.parser, HTTP_REQUEST); + http_parser_settings_init(&ctx.parser_settings); + ctx.parser.data = &request; + ctx.parser_settings.on_url = on_url; + + mbedtls_printf("Zephyr HTTPS Server\n"); + mbedtls_printf("Address: %s, port: %d\n", ZEPHYR_ADDR, SERVER_PORT); +reset: + mbedtls_ssl_session_reset(&ssl); + mbedtls_ssl_set_bio(&ssl, &ctx, ssl_tx, ssl_rx, NULL); + /* + * 5. Handshake + */ + do { + ret = mbedtls_ssl_handshake(&ssl); + if (ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + if (ret < 0) { + mbedtls_printf(" failed\n !" + " mbedtls_ssl_handshake returned %d\n\n", + ret); + goto reset; + } + } + } while (ret != 0); + + /* + * 6. Read the HTTPS Request + */ + mbedtls_printf("Read HTTPS request\n"); + do { + len = sizeof(payload) - 1; + memset(payload, 0, sizeof(payload)); + ret = mbedtls_ssl_read(&ssl, payload, len); + + if (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + continue; + } + + if (ret <= 0) { + switch (ret) { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf(" connection was" + " closed gracefully\n"); + goto close; + + case MBEDTLS_ERR_NET_CONN_RESET: + mbedtls_printf(" connection was" + " reset by peer\n"); + break; + + default: + mbedtls_printf + (" mbedtls_ssl_read returned -0x%x\n", + -ret); + break; + } + + break; + } + + len = ret; + ret = http_parser_execute(&ctx.parser, &ctx.parser_settings, + payload, len); + if (ret < 0) { + } + } while (ret < 0); + + /* + * 7. Write the Response + */ + mbedtls_printf("Write HTTPS response\n"); + + if (!strncmp("/index.html", request.url, request.url_len)) { + len = snprintf((char *)payload, sizeof(payload), + HTTP_RESPONSE); + } else { + + len = snprintf((char *)payload, sizeof(payload), + HTTP_NOT_FOUND); + } + + do { + ret = mbedtls_ssl_write(&ssl, payload, len); + if (ret == MBEDTLS_ERR_NET_CONN_RESET) { + mbedtls_printf(" failed\n !" + " peer closed the connection\n"); + goto reset; + } + + if (ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + if (ret < 0) { + mbedtls_printf(" failed\n !" + " mbedtls_ssl_write" + " returned %d\n", ret); + goto exit; + } + } + } while (ret <= 0); + +close: + + mbedtls_ssl_close_notify(&ssl); + ret = 0; + goto reset; + +exit: +#ifdef MBEDTLS_ERROR_C + if (ret != 0) { + mbedtls_strerror(ret, payload, 100); + mbedtls_printf("Last error was: %d - %s\n", ret, payload); + } +#endif + + mbedtls_ssl_free(&ssl); + mbedtls_ssl_config_free(&conf); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); +} + +#define STACK_SIZE 8192 +uint8_t stack[STACK_SIZE]; + +static inline int init_app(void) +{ +#if defined(CONFIG_NET_IPV6) + if (net_addr_pton(AF_INET6, ZEPHYR_ADDR, &server_addr) < 0) { + mbedtls_printf("Invalid IPv6 address %s", ZEPHYR_ADDR); + } + + if (!net_if_ipv6_addr_add(net_if_get_default(), &server_addr, + NET_ADDR_MANUAL, 0)) { + return -EIO; + } +#else + if (net_addr_pton(AF_INET, ZEPHYR_ADDR, &server_addr) < 0) { + mbedtls_printf("Invalid IPv4 address %s", ZEPHYR_ADDR); + } + + if (!net_if_ipv4_addr_add(net_if_get_default(), &server_addr, + NET_ADDR_MANUAL, 0)) { + return -EIO; + } +#endif + + return 0; +} + +void https_server_start(void) +{ + if (init_app() != 0) { + printk("Cannot initialize network\n"); + return; + } + + k_thread_spawn(stack, STACK_SIZE, (k_thread_entry_t) https_server, + NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0); + +} diff --git a/samples/net/http_server/src/main.c b/samples/net/http_server/src/main.c index e5ebd16e8e3..d71f897ad89 100644 --- a/samples/net/http_server/src/main.c +++ b/samples/net/http_server/src/main.c @@ -20,6 +20,10 @@ static int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb, const char *addr, uint16_t port); +#if defined(CONFIG_MBEDTLS) +#include "ssl_utils.h" +#endif + void main(void) { struct net_context *net_ctx = NULL; @@ -101,6 +105,9 @@ int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb, print_server_banner(&local_sock); +#if defined(CONFIG_MBEDTLS) + https_server_start(); +#endif return 0; lb_error: diff --git a/samples/net/http_server/src/ssl_utils.c b/samples/net/http_server/src/ssl_utils.c new file mode 100644 index 00000000000..ac75aadd0e1 --- /dev/null +++ b/samples/net/http_server/src/ssl_utils.c @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif + +#include "mbedtls/ssl.h" + +#include "config.h" +#include "ssl_utils.h" + +#define RX_FIFO_DEPTH 4 + +K_MEM_POOL_DEFINE(rx_pkts, 4, 64, RX_FIFO_DEPTH, 4); + +static void ssl_received(struct net_context *context, + struct net_buf *buf, int status, void *user_data) +{ + struct ssl_context *ctx = user_data; + struct rx_fifo_block *rx_data = NULL; + struct k_mem_block block; + + ARG_UNUSED(context); + ARG_UNUSED(status); + + if (!net_nbuf_appdatalen(buf)) { + net_nbuf_unref(buf); + return; + } + + k_mem_pool_alloc(&rx_pkts, &block, + sizeof(struct rx_fifo_block), K_FOREVER); + rx_data = block.data; + rx_data->buf = buf; + + /* For freeing memory later */ + memcpy(&rx_data->block, &block, sizeof(struct k_mem_block)); + k_fifo_put(&ctx->rx_fifo, (void *)rx_data); +} + +static inline void ssl_sent(struct net_context *context, + int status, void *token, void *user_data) +{ + struct ssl_context *ctx = user_data; + + k_sem_give(&ctx->tx_sem); +} + +int ssl_tx(void *context, const unsigned char *buf, size_t size) +{ + struct ssl_context *ctx = context; + struct net_context *net_ctx; + struct net_buf *send_buf; + + int rc, len; + + net_ctx = ctx->net_ctx; + + send_buf = net_nbuf_get_tx(net_ctx, K_NO_WAIT); + if (!send_buf) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + rc = net_nbuf_append(send_buf, size, (uint8_t *) buf, K_FOREVER); + if (!rc) { + net_nbuf_unref(send_buf); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + len = net_buf_frags_len(send_buf); + + rc = net_context_send(send_buf, ssl_sent, K_NO_WAIT, NULL, ctx); + + if (rc < 0) { + net_nbuf_unref(send_buf); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + k_sem_take(&ctx->tx_sem, K_FOREVER); + return len; +} + +int ssl_rx(void *context, unsigned char *buf, size_t size) +{ + struct ssl_context *ctx = context; + uint16_t read_bytes; + struct rx_fifo_block *rx_data; + uint8_t *ptr; + int pos; + int len; + int rc = 0; + + if (ctx->frag == NULL) { + rx_data = k_fifo_get(&ctx->rx_fifo, K_FOREVER); + ctx->rx_nbuf = rx_data->buf; + k_mem_pool_free(&rx_data->block); + + read_bytes = net_nbuf_appdatalen(ctx->rx_nbuf); + + ctx->remaining = read_bytes; + ctx->frag = ctx->rx_nbuf->frags; + ptr = net_nbuf_appdata(ctx->rx_nbuf); + + len = ptr - ctx->frag->data; + net_buf_pull(ctx->frag, len); + } else { + read_bytes = ctx->remaining; + ptr = ctx->frag->data; + } + + len = ctx->frag->len; + pos = 0; + if (read_bytes > size) { + while (ctx->frag) { + read_bytes = len < (size - pos) ? len : (size - pos); + memcpy(buf + pos, ptr, read_bytes); + pos += read_bytes; + if (pos < size) { + ctx->frag = ctx->frag->frags; + ptr = ctx->frag->data; + len = ctx->frag->len; + } else { + if (read_bytes == len) { + ctx->frag = ctx->frag->frags; + } else { + net_buf_pull(ctx->frag, read_bytes); + } + + ctx->remaining -= size; + return size; + } + } + } else { + while (ctx->frag) { + memcpy(buf + pos, ptr, len); + pos += len; + ctx->frag = ctx->frag->frags; + if (!ctx->frag) { + break; + } + + ptr = ctx->frag->data; + len = ctx->frag->len; + } + + net_nbuf_unref(ctx->rx_nbuf); + ctx->rx_nbuf = NULL; + ctx->frag = NULL; + ctx->remaining = 0; + + if (read_bytes != pos) { + return -EIO; + } + + rc = read_bytes; + } + + return rc; +} + +static void ssl_accepted(struct net_context *context, + struct sockaddr *addr, + socklen_t addrlen, int error, void *user_data) +{ + int ret; + struct ssl_context *ctx = user_data; + + ctx->net_ctx = context; + ret = net_context_recv(context, ssl_received, 0, user_data); + if (ret < 0) { + printk("Cannot receive TCP packet (family %d)", + net_context_get_family(context)); + } + +} + +#if defined(CONFIG_NET_IPV6) +int ssl_init(struct ssl_context *ctx, void *addr) +{ + struct net_context *tcp_ctx = { 0 }; + struct sockaddr_in6 my_addr = { 0 }; + struct in6_addr *server_addr = addr; + int rc; + + k_sem_init(&ctx->tx_sem, 0, UINT_MAX); + k_fifo_init(&ctx->rx_fifo); + + my_mcast_addr.sin6_family = AF_INET6; + + net_ipaddr_copy(&my_addr.sin6_addr, server_addr); + my_addr.sin6_family = AF_INET6; + my_addr.sin6_port = htons(SERVER_PORT); + + rc = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &tcp_ctx); + if (rc < 0) { + printk("Cannot get network context for IPv6 TCP (%d)", rc); + return -EIO; + } + + rc = net_context_bind(tcp_ctx, (struct sockaddr *)&my_addr, + sizeof(struct sockaddr_in6)); + if (rc < 0) { + printk("Cannot bind IPv6 TCP port %d (%d)", SERVER_PORT, rc); + goto error; + } + + ctx->rx_nbuf = NULL; + ctx->remaining = 0; + ctx->net_ctx = tcp_ctx; + + rc = net_context_listen(ctx->net_ctx, 0); + if (rc < 0) { + printk("Cannot listen IPv6 TCP (%d)", rc); + return -EIO; + } + + rc = net_context_accept(ctx->net_ctx, ssl_accepted, 0, ctx); + if (rc < 0) { + printk("Cannot accept IPv4 (%d)", rc); + return -EIO; + } + + return 0; + +error: + net_context_put(tcp_ctx); + return -EINVAL; +} + +#else +int ssl_init(struct ssl_context *ctx, void *addr) +{ + struct net_context *tcp_ctx = { 0 }; + struct sockaddr_in my_addr4 = { 0 }; + struct in_addr *server_addr = addr; + int rc; + + k_sem_init(&ctx->tx_sem, 0, UINT_MAX); + k_fifo_init(&ctx->rx_fifo); + + net_ipaddr_copy(&my_addr4.sin_addr, server_addr); + my_addr4.sin_family = AF_INET; + my_addr4.sin_port = htons(SERVER_PORT); + + rc = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &tcp_ctx); + if (rc < 0) { + printk("Cannot get network context for IPv4 TCP (%d)", rc); + return -EIO; + } + + rc = net_context_bind(tcp_ctx, (struct sockaddr *)&my_addr4, + sizeof(struct sockaddr_in)); + if (rc < 0) { + printk("Cannot bind IPv4 TCP port %d (%d)", SERVER_PORT, rc); + goto error; + } + + ctx->rx_nbuf = NULL; + ctx->remaining = 0; + ctx->net_ctx = tcp_ctx; + + rc = net_context_listen(ctx->net_ctx, 0); + if (rc < 0) { + printk("Cannot listen IPv4 (%d)", rc); + return -EIO; + } + + rc = net_context_accept(ctx->net_ctx, ssl_accepted, 0, ctx); + if (rc < 0) { + printk("Cannot accept IPv4 (%d)", rc); + return -EIO; + } + + return 0; + +error: + net_context_put(tcp_ctx); + return -EINVAL; +} +#endif diff --git a/samples/net/http_server/src/ssl_utils.h b/samples/net/http_server/src/ssl_utils.h new file mode 100644 index 00000000000..a0ef50eff1f --- /dev/null +++ b/samples/net/http_server/src/ssl_utils.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SSL_UTILS_H_ +#define _SSL_UTILS_H_ + +#include +#include + +struct rx_fifo_block { + sys_snode_t snode; + struct k_mem_block block; + struct net_buf *buf; +}; + +struct ssl_context { + struct net_context *net_ctx; + struct net_buf *rx_nbuf; + struct net_buf *frag; + struct k_sem tx_sem; + struct k_fifo rx_fifo; + struct http_parser_settings parser_settings; + struct http_parser parser; + + int remaining; +}; + +int ssl_init(struct ssl_context *ctx, void *addr); +int ssl_tx(void *ctx, const unsigned char *buf, size_t size); +int ssl_rx(void *ctx, unsigned char *buf, size_t size); + +void https_server_start(void); + +#endif diff --git a/samples/net/http_server/src/test_certs.h b/samples/net/http_server/src/test_certs.h new file mode 100644 index 00000000000..5b6326110dc --- /dev/null +++ b/samples/net/http_server/src/test_certs.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __TEST_CERTS_H__ +#define __TEST_CERTS_H__ + +static const unsigned char rsa_example_keypair_der[] = { + 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0x9b, 0xfc, + 0x66, 0x90, 0x79, 0x84, 0x42, 0xbb, 0xab, 0x13, 0xfd, 0x2b, 0x7b, 0xf8, + 0xde, 0x15, 0x12, 0xe5, 0xf1, 0x93, 0xe3, 0x06, 0x8a, 0x7b, 0xb8, 0xb1, + 0xe1, 0x9e, 0x26, 0xbb, 0x95, 0x01, 0xbf, 0xe7, 0x30, 0xed, 0x64, 0x85, + 0x02, 0xdd, 0x15, 0x69, 0xa8, 0x34, 0xb0, 0x06, 0xec, 0x3f, 0x35, 0x3c, + 0x1e, 0x1b, 0x2b, 0x8f, 0xfa, 0x8f, 0x00, 0x1b, 0xdf, 0x07, 0xc6, 0xac, + 0x53, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x1b, 0x4a, 0xf7, + 0x7b, 0x31, 0xf7, 0xe5, 0x61, 0x46, 0xd6, 0xd1, 0x86, 0x69, 0x43, 0xab, + 0x40, 0x0e, 0xb5, 0x73, 0x26, 0x88, 0x23, 0x9d, 0xd9, 0x76, 0x00, 0x91, + 0xd4, 0x85, 0x3c, 0x6f, 0x1e, 0xc0, 0x51, 0xeb, 0xe6, 0x90, 0x5b, 0x41, + 0x7f, 0xe6, 0xaa, 0x31, 0x6b, 0xac, 0x59, 0x53, 0x96, 0x26, 0xf1, 0xae, + 0xda, 0xbe, 0x55, 0xa4, 0x75, 0x40, 0x22, 0x5f, 0x27, 0x17, 0xa0, 0xd2, + 0x91, 0x02, 0x21, 0x00, 0xc8, 0xc4, 0x27, 0x7c, 0xd5, 0x61, 0xad, 0xbf, + 0x32, 0x8e, 0x1e, 0xcb, 0xe8, 0x94, 0xf4, 0x9f, 0x55, 0x77, 0xe5, 0xa8, + 0xc9, 0x70, 0xd0, 0x0f, 0x81, 0x04, 0xb7, 0x09, 0xb2, 0x1b, 0x53, 0xe9, + 0x02, 0x21, 0x00, 0xc6, 0xe6, 0x65, 0xbe, 0x10, 0xc8, 0x6d, 0xb7, 0x1e, + 0xee, 0x8e, 0x41, 0xbc, 0xe8, 0x67, 0x09, 0x9d, 0x8d, 0xee, 0x46, 0x1b, + 0xd5, 0x90, 0xb9, 0xee, 0x0d, 0xc5, 0xf9, 0xc6, 0xc9, 0xc9, 0x6f, 0x02, + 0x21, 0x00, 0x9b, 0xb0, 0x31, 0x87, 0x06, 0xda, 0x36, 0xa8, 0x9c, 0x85, + 0xc5, 0xb0, 0x0e, 0xee, 0xe4, 0x3c, 0x63, 0x45, 0x15, 0x1d, 0xad, 0x09, + 0x04, 0xef, 0xe0, 0xf7, 0x4d, 0x12, 0x01, 0xc2, 0x5b, 0x71, 0x02, 0x20, + 0x46, 0xd1, 0x25, 0x8c, 0x84, 0xa1, 0x38, 0x1f, 0x29, 0x0e, 0x3a, 0xec, + 0x40, 0xfc, 0x66, 0x23, 0x50, 0x4b, 0x86, 0x78, 0xc3, 0xd4, 0x48, 0x51, + 0x4a, 0xe6, 0xf0, 0x84, 0x3c, 0x39, 0x00, 0x55, 0x02, 0x21, 0x00, 0x8d, + 0x03, 0x6e, 0x29, 0x0e, 0xd7, 0x4e, 0x1f, 0x27, 0x70, 0xb5, 0x20, 0x79, + 0xfb, 0x31, 0x6a, 0x14, 0xb7, 0xe6, 0x55, 0x9a, 0x65, 0x40, 0xcf, 0xe0, + 0xe6, 0x46, 0xf8, 0xb2, 0x8e, 0xf4, 0x63, 0x0a +}; + +static const unsigned int rsa_example_keypair_der_len = 320; + +static const unsigned char rsa_example_cert_der[] = { + 0x30, 0x82, 0x02, 0x12, 0x30, 0x82, 0x01, 0x7b, 0x02, 0x02, 0x0d, 0xfa, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x30, 0x81, 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4a, 0x50, 0x31, 0x0e, 0x30, 0x0c, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x13, 0x05, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x31, + 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68, + 0x75, 0x6f, 0x2d, 0x6b, 0x75, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x08, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x44, 0x44, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0f, 0x57, + 0x65, 0x62, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x75, 0x70, 0x70, 0x6f, + 0x72, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x0f, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x44, 0x44, 0x20, 0x57, 0x65, + 0x62, 0x20, 0x43, 0x41, 0x31, 0x23, 0x30, 0x21, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x14, 0x73, 0x75, 0x70, + 0x70, 0x6f, 0x72, 0x74, 0x40, 0x66, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x64, + 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, + 0x38, 0x32, 0x32, 0x30, 0x35, 0x32, 0x36, 0x35, 0x34, 0x5a, 0x17, 0x0d, + 0x31, 0x37, 0x30, 0x38, 0x32, 0x31, 0x30, 0x35, 0x32, 0x36, 0x35, 0x34, + 0x5a, 0x30, 0x4a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x4a, 0x50, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x05, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x31, 0x11, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x46, 0x72, 0x61, 0x6e, 0x6b, + 0x34, 0x44, 0x44, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, + 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9b, 0xfc, 0x66, 0x90, 0x79, 0x84, + 0x42, 0xbb, 0xab, 0x13, 0xfd, 0x2b, 0x7b, 0xf8, 0xde, 0x15, 0x12, 0xe5, + 0xf1, 0x93, 0xe3, 0x06, 0x8a, 0x7b, 0xb8, 0xb1, 0xe1, 0x9e, 0x26, 0xbb, + 0x95, 0x01, 0xbf, 0xe7, 0x30, 0xed, 0x64, 0x85, 0x02, 0xdd, 0x15, 0x69, + 0xa8, 0x34, 0xb0, 0x06, 0xec, 0x3f, 0x35, 0x3c, 0x1e, 0x1b, 0x2b, 0x8f, + 0xfa, 0x8f, 0x00, 0x1b, 0xdf, 0x07, 0xc6, 0xac, 0x53, 0x07, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x14, 0xb6, + 0x4c, 0xbb, 0x81, 0x79, 0x33, 0xe6, 0x71, 0xa4, 0xda, 0x51, 0x6f, 0xcb, + 0x08, 0x1d, 0x8d, 0x60, 0xec, 0xbc, 0x18, 0xc7, 0x73, 0x47, 0x59, 0xb1, + 0xf2, 0x20, 0x48, 0xbb, 0x61, 0xfa, 0xfc, 0x4d, 0xad, 0x89, 0x8d, 0xd1, + 0x21, 0xeb, 0xd5, 0xd8, 0xe5, 0xba, 0xd6, 0xa6, 0x36, 0xfd, 0x74, 0x50, + 0x83, 0xb6, 0x0f, 0xc7, 0x1d, 0xdf, 0x7d, 0xe5, 0x2e, 0x81, 0x7f, 0x45, + 0xe0, 0x9f, 0xe2, 0x3e, 0x79, 0xee, 0xd7, 0x30, 0x31, 0xc7, 0x20, 0x72, + 0xd9, 0x58, 0x2e, 0x2a, 0xfe, 0x12, 0x5a, 0x34, 0x45, 0xa1, 0x19, 0x08, + 0x7c, 0x89, 0x47, 0x5f, 0x4a, 0x95, 0xbe, 0x23, 0x21, 0x4a, 0x53, 0x72, + 0xda, 0x2a, 0x05, 0x2f, 0x2e, 0xc9, 0x70, 0xf6, 0x5b, 0xfa, 0xfd, 0xdf, + 0xb4, 0x31, 0xb2, 0xc1, 0x4a, 0x9c, 0x06, 0x25, 0x43, 0xa1, 0xe6, 0xb4, + 0x1e, 0x7f, 0x86, 0x9b, 0x16, 0x40, 0x0a +}; + +static const unsigned int rsa_example_cert_der_len = 535; + +#endif