initial commit
This commit is contained in:
738
lib/amb1_sdk/common/network/coap/include/ns_list.h
Normal file
738
lib/amb1_sdk/common/network/coap/include/ns_list.h
Normal file
@@ -0,0 +1,738 @@
|
||||
/*
|
||||
* Copyright (c) 2014-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.
|
||||
*/
|
||||
|
||||
#ifndef NS_LIST_H_
|
||||
#define NS_LIST_H_
|
||||
|
||||
#include "ns_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file
|
||||
* \brief Linked list support library
|
||||
*
|
||||
* The ns_list.h file provides a doubly-linked list/queue, providing O(1)
|
||||
* performance for all insertion/removal operations, and access to either
|
||||
* end of the list.
|
||||
*
|
||||
* Memory footprint is two pointers for the list head, and two pointers in each
|
||||
* list entry. It is similar in concept to BSD's TAILQ.
|
||||
*
|
||||
* Although the API is symmetrical and O(1) in both directions, due to internal
|
||||
* pointer design, it is *slightly* more efficient to insert at the end when
|
||||
* used as a queue, and to iterate forwards rather than backwards.
|
||||
*
|
||||
* Example of an entry type that can be stored to this list.
|
||||
* ~~~
|
||||
* typedef struct example_entry
|
||||
* {
|
||||
* uint8_t *data;
|
||||
* uint32_t data_count;
|
||||
* ns_list_link_t link;
|
||||
* }
|
||||
* example_entry_t;
|
||||
*
|
||||
* static NS_LIST_HEAD(example_entry_t, link) my_list;
|
||||
* ns_list_init(&my_list);
|
||||
* ~~~
|
||||
* OR
|
||||
* ~~~
|
||||
* NS_LIST_HEAD(example_entry_t, link) my_list = NS_LIST_INIT(my_list);
|
||||
* ~~~
|
||||
* OR
|
||||
* ~~~
|
||||
* static NS_LIST_DEFINE(my_list, example_entry_t, link);
|
||||
* ~~~
|
||||
* OR
|
||||
* ~~~
|
||||
* typedef NS_LIST_HEAD(example_entry_t, link) example_list_t;
|
||||
* example_list_t NS_LIST_NAME_INIT(my_list);
|
||||
* ~~~
|
||||
* NOTE: the link field SHALL NOT be accessed by the user.
|
||||
*
|
||||
* An entry can exist on multiple lists by having multiple link fields.
|
||||
*
|
||||
* All the list operations are implemented as macros, most of which are backed
|
||||
* by optionally-inline functions. The macros do not evaluate any arguments more
|
||||
* than once, unless documented.
|
||||
*
|
||||
* In macro documentation, `list_t` refers to a list type defined using
|
||||
* NS_LIST_HEAD(), and `entry_t` to the entry type that was passed to it.
|
||||
*/
|
||||
|
||||
/** \brief Underlying generic linked list head.
|
||||
*
|
||||
* Users should not use this type directly, but use the NS_LIST_HEAD() macro.
|
||||
*/
|
||||
typedef struct ns_list {
|
||||
void *first_entry; ///< Pointer to first entry, or NULL if list is empty
|
||||
void **last_nextptr; ///< Pointer to last entry's `next` pointer, or
|
||||
///< to head's `first_entry` pointer if list is empty
|
||||
} ns_list_t;
|
||||
|
||||
/** \brief Declare a list head type
|
||||
*
|
||||
* This union stores the real list head, and also encodes as compile-time type
|
||||
* information the offset of the link pointer, and the type of the entry.
|
||||
*
|
||||
* Note that type information is compiler-dependent; this means
|
||||
* ns_list_get_first() could return either `void *`, or a pointer to the actual
|
||||
* entry type. So `ns_list_get_first()->data` is not a portable construct -
|
||||
* always assign returned entry pointers to a properly typed pointer variable.
|
||||
* This assignment will be then type-checked where the compiler supports it, and
|
||||
* will dereference correctly on compilers that don't support this extension.
|
||||
* ~~~
|
||||
* NS_LIST_HEAD(example_entry_t, link) my_list;
|
||||
*
|
||||
* example_entry_t *entry = ns_list_get_first(&my_list);
|
||||
* do_something(entry->data);
|
||||
* ~~~
|
||||
* Each use of this macro generates a new anonymous union, so these two lists
|
||||
* have different types:
|
||||
* ~~~
|
||||
* NS_LIST_HEAD(example_entry_t, link) my_list1;
|
||||
* NS_LIST_HEAD(example_entry_t, link) my_list2;
|
||||
* ~~~
|
||||
* If you need to use a list type in multiple places, eg as a function
|
||||
* parameter, use typedef:
|
||||
* ~~~
|
||||
* typedef NS_LIST_HEAD(example_entry_t, link) example_list_t;
|
||||
*
|
||||
* void example_function(example_list_t *);
|
||||
* ~~~
|
||||
*/
|
||||
#define NS_LIST_HEAD(entry_type, field) \
|
||||
NS_LIST_HEAD_BY_OFFSET_(entry_type, offsetof(entry_type, field))
|
||||
|
||||
/** \brief Declare a list head type for an incomplete entry type.
|
||||
*
|
||||
* This declares a list head, similarly to NS_LIST_HEAD(), but unlike that
|
||||
* this can be used in contexts where the entry type may be incomplete.
|
||||
*
|
||||
* To use this, the link pointer must be the first member in the
|
||||
* actual complete structure. This is NOT checked - the definition of the
|
||||
* element should probably test NS_STATIC_ASSERT(offsetof(type, link) == 0)
|
||||
* if outside users are known to be using NS_LIST_HEAD_INCOMPLETE().
|
||||
* ~~~
|
||||
* struct opaque;
|
||||
* NS_LIST_HEAD_INCOMPLETE(struct opaque) opaque_list;
|
||||
* ~~~
|
||||
*/
|
||||
#define NS_LIST_HEAD_INCOMPLETE(entry_type) \
|
||||
NS_LIST_HEAD_BY_OFFSET_(entry_type, 0)
|
||||
|
||||
/// \privatesection
|
||||
/** \brief Internal macro defining a list head, given the offset to the link pointer
|
||||
* The +1 allows for link_offset being 0 - we can't declare a 0-size array
|
||||
*/
|
||||
#define NS_LIST_HEAD_BY_OFFSET_(entry_type, link_offset) \
|
||||
union \
|
||||
{ \
|
||||
ns_list_t slist; \
|
||||
NS_FUNNY_COMPARE_OK \
|
||||
NS_STATIC_ASSERT(link_offset <= UINT_FAST8_MAX, "link offset too large") \
|
||||
NS_FUNNY_COMPARE_RESTORE \
|
||||
char (*offset)[link_offset + 1]; \
|
||||
entry_type *type; \
|
||||
}
|
||||
|
||||
/** \brief Get offset of link field in entry.
|
||||
* \return `(ns_list_offset_t)` The offset of the link field for entries on the specified list
|
||||
*/
|
||||
#define NS_LIST_OFFSET_(list) ((ns_list_offset_t) (sizeof *(list)->offset - 1))
|
||||
|
||||
/** \brief Get the entry pointer type.
|
||||
* \def NS_LIST_PTR_TYPE_
|
||||
*
|
||||
* \return An unqualified pointer type to an entry on the specified list.
|
||||
*
|
||||
* Only available if the compiler provides a "typeof" operator.
|
||||
*/
|
||||
#if defined __cplusplus && __cplusplus >= 201103L
|
||||
#define NS_LIST_PTR_TYPE_(list) decltype((list)->type)
|
||||
#elif defined __GNUC__
|
||||
#define NS_LIST_PTR_TYPE_(list) __typeof__((list)->type)
|
||||
#endif
|
||||
|
||||
/** \brief Check for compatible pointer types
|
||||
*
|
||||
* This test will produce a diagnostic about a pointer mismatch on
|
||||
* the == inside the sizeof operator. For example ARM/Norcroft C gives the error:
|
||||
*
|
||||
* operand types are incompatible ("entry_t *" and "other_t *")
|
||||
*/
|
||||
#ifdef CPPCHECK
|
||||
#define NS_PTR_MATCH_(a, b, str) ((void) 0)
|
||||
#else
|
||||
#define NS_PTR_MATCH_(a, b, str) ((void) sizeof ((a) == (b)))
|
||||
#endif
|
||||
|
||||
/** \brief Internal macro to cast returned entry pointers to correct type.
|
||||
*
|
||||
* Not portable in C, alas. With GCC or C++11, the "get entry" macros return
|
||||
* correctly-typed pointers. Otherwise, the macros return `void *`.
|
||||
*
|
||||
* The attempt at a portable version would work if the C `?:` operator wasn't
|
||||
* broken - `x ? (t *) : (void *)` should really have type `(t *)` in C, but
|
||||
* it has type `(void *)`, which only makes sense for C++. The `?:` is left in,
|
||||
* in case some day it works. Some compilers may still warn if this is
|
||||
* assigned to a different type.
|
||||
*/
|
||||
#ifdef NS_LIST_PTR_TYPE_
|
||||
#define NS_LIST_TYPECAST_(list, val) ((NS_LIST_PTR_TYPE_(list)) (val))
|
||||
#else
|
||||
#define NS_LIST_TYPECAST_(list, val) (0 ? (list)->type : (val))
|
||||
#endif
|
||||
|
||||
/** \brief Internal macro to check types of input entry pointer. */
|
||||
#define NS_LIST_TYPECHECK_(list, entry) \
|
||||
(NS_PTR_MATCH_((list)->type, (entry), "incorrect entry type for list"), (entry))
|
||||
|
||||
/** \brief Type used to pass link offset to underlying functions
|
||||
*
|
||||
* We could use size_t, but it would be unnecessarily large on 8-bit systems,
|
||||
* where we can be (pretty) confident we won't have next pointers more than
|
||||
* 256 bytes into a structure.
|
||||
*/
|
||||
typedef uint_fast8_t ns_list_offset_t;
|
||||
|
||||
/// \publicsection
|
||||
/** \brief The type for the link member in the user's entry structure.
|
||||
*
|
||||
* Users should not access this member directly - just pass its name to the
|
||||
* list head macros. The funny prev pointer simplifies common operations
|
||||
* (eg insertion, removal), at the expense of complicating rare reverse iteration.
|
||||
*
|
||||
* NB - the list implementation relies on next being the first member.
|
||||
*/
|
||||
typedef struct ns_list_link {
|
||||
void *next; ///< Pointer to next entry, or NULL if none
|
||||
void **prev; ///< Pointer to previous entry's (or head's) next pointer
|
||||
} ns_list_link_t;
|
||||
|
||||
/** \brief "Poison" value placed in unattached entries' link pointers.
|
||||
* \internal What are good values for this? Platform dependent, maybe just NULL
|
||||
*/
|
||||
#define NS_LIST_POISON ((void *) 0xDEADBEEF)
|
||||
|
||||
/** \brief Initialiser for an entry's link member
|
||||
*
|
||||
* This initialiser is not required by the library, but a user may want an
|
||||
* initialiser to include in their own entry initialiser. See
|
||||
* ns_list_link_init() for more discussion.
|
||||
*/
|
||||
#define NS_LIST_LINK_INIT(name) \
|
||||
NS_FUNNY_INTPTR_OK \
|
||||
{ NS_LIST_POISON, NS_LIST_POISON } \
|
||||
NS_FUNNY_INTPTR_RESTORE
|
||||
|
||||
/** \hideinitializer \brief Initialise an entry's list link
|
||||
*
|
||||
* This "initialises" an unattached entry's link by filling the fields with
|
||||
* poison. This is optional, as unattached entries field pointers are not
|
||||
* meaningful, and it is not valid to call ns_list_get_next or similar on
|
||||
* an unattached entry.
|
||||
*
|
||||
* \param entry Pointer to an entry
|
||||
* \param field The name of the link member to initialise
|
||||
*/
|
||||
#define ns_list_link_init(entry, field) ns_list_link_init_(&(entry)->field)
|
||||
|
||||
/** \hideinitializer \brief Initialise a list
|
||||
*
|
||||
* Initialise a list head before use. A list head must be initialised using this
|
||||
* function or one of the NS_LIST_INIT()-type macros before use. A zero-initialised
|
||||
* list head is *not* valid.
|
||||
*
|
||||
* If used on a list containing existing entries, those entries will
|
||||
* become detached. (They are not modified, but their links are now effectively
|
||||
* undefined).
|
||||
*
|
||||
* \param list Pointer to a NS_LIST_HEAD() structure.
|
||||
*/
|
||||
#define ns_list_init(list) ns_list_init_(&(list)->slist)
|
||||
|
||||
/** \brief Initialiser for an empty list
|
||||
*
|
||||
* Usage in an enclosing initialiser:
|
||||
* ~~~
|
||||
* static my_type_including_list_t x = {
|
||||
* "Something",
|
||||
* 23,
|
||||
* NS_LIST_INIT(x),
|
||||
* };
|
||||
* ~~~
|
||||
* NS_LIST_DEFINE() or NS_LIST_NAME_INIT() may provide a shorter alternative
|
||||
* in simpler cases.
|
||||
*/
|
||||
#define NS_LIST_INIT(name) { { NULL, &(name).slist.first_entry } }
|
||||
|
||||
/** \brief Name and initialiser for an empty list
|
||||
*
|
||||
* Usage:
|
||||
* ~~~
|
||||
* list_t NS_LIST_NAME_INIT(foo);
|
||||
* ~~~
|
||||
* acts as
|
||||
* ~~~
|
||||
* list_t foo = { empty list };
|
||||
* ~~~
|
||||
* Also useful with designated initialisers:
|
||||
* ~~~
|
||||
* .NS_LIST_NAME_INIT(foo),
|
||||
* ~~~
|
||||
* acts as
|
||||
* ~~~
|
||||
* .foo = { empty list },
|
||||
* ~~~
|
||||
*/
|
||||
#define NS_LIST_NAME_INIT(name) name = NS_LIST_INIT(name)
|
||||
|
||||
/** \brief Define a list, and initialise to empty.
|
||||
*
|
||||
* Usage:
|
||||
* ~~~
|
||||
* static NS_LIST_DEFINE(my_list, entry_t, link);
|
||||
* ~~~
|
||||
* acts as
|
||||
* ~~~
|
||||
* static list_type my_list = { empty list };
|
||||
* ~~~
|
||||
*/
|
||||
#define NS_LIST_DEFINE(name, type, field) \
|
||||
NS_LIST_HEAD(type, field) NS_LIST_NAME_INIT(name)
|
||||
|
||||
/** \hideinitializer \brief Add an entry to the start of the linked list.
|
||||
*
|
||||
* ns_list_add_to_end() is *slightly* more efficient than ns_list_add_to_start().
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param entry `(entry_t * restrict)` Pointer to new entry to add.
|
||||
*/
|
||||
#define ns_list_add_to_start(list, entry) \
|
||||
ns_list_add_to_start_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \hideinitializer \brief Add an entry to the end of the linked list.
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param entry `(entry_t * restrict)` Pointer to new entry to add.
|
||||
*/
|
||||
#define ns_list_add_to_end(list, entry) \
|
||||
ns_list_add_to_end_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \hideinitializer \brief Add an entry before a specified entry.
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param before `(entry_t *)` Existing entry before which to place the new entry.
|
||||
* \param entry `(entry_t * restrict)` Pointer to new entry to add.
|
||||
*/
|
||||
#define ns_list_add_before(list, before, entry) \
|
||||
ns_list_add_before_(NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, before), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \hideinitializer \brief Add an entry after a specified entry.
|
||||
*
|
||||
* ns_list_add_before() is *slightly* more efficient than ns_list_add_after().
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param after `(entry_t *)` Existing entry after which to place the new entry.
|
||||
* \param entry `(entry_t * restrict)` Pointer to new entry to add.
|
||||
*/
|
||||
#define ns_list_add_after(list, after, entry) \
|
||||
ns_list_add_after_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, after), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \brief Check if a list is empty.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
*
|
||||
* \return `(bool)` true if the list is empty.
|
||||
*/
|
||||
#define ns_list_is_empty(list) ((bool) ((list)->slist.first_entry == NULL))
|
||||
|
||||
/** \brief Get the first entry.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
*
|
||||
* \return `(entry_t *)` Pointer to first entry.
|
||||
* \return NULL if list is empty.
|
||||
*/
|
||||
#define ns_list_get_first(list) NS_LIST_TYPECAST_(list, (list)->slist.first_entry)
|
||||
|
||||
/** \hideinitializer \brief Get the previous entry.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
* \param current `(const entry_t *)` Pointer to current entry.
|
||||
*
|
||||
* \return `(entry_t *)` Pointer to previous entry.
|
||||
* \return NULL if current entry is first.
|
||||
*/
|
||||
#define ns_list_get_previous(list, current) \
|
||||
NS_LIST_TYPECAST_(list, ns_list_get_previous_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current)))
|
||||
|
||||
/** \hideinitializer \brief Get the next entry.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
* \param current `(const entry_t *)` Pointer to current entry.
|
||||
*
|
||||
* \return `(entry_t *)` Pointer to next entry.
|
||||
* \return NULL if current entry is last.
|
||||
*/
|
||||
#define ns_list_get_next(list, current) \
|
||||
NS_LIST_TYPECAST_(list, ns_list_get_next_(NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current)))
|
||||
|
||||
/** \hideinitializer \brief Get the last entry.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
*
|
||||
* \return `(entry_t *)` Pointer to last entry.
|
||||
* \return NULL if list is empty.
|
||||
*/
|
||||
#define ns_list_get_last(list) \
|
||||
NS_LIST_TYPECAST_(list, ns_list_get_last_(&(list)->slist, NS_LIST_OFFSET_(list)))
|
||||
|
||||
/** \hideinitializer \brief Remove an entry.
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param entry `(entry_t *)` Entry on list to be removed.
|
||||
*/
|
||||
#define ns_list_remove(list, entry) \
|
||||
ns_list_remove_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
|
||||
|
||||
/** \hideinitializer \brief Replace an entry.
|
||||
*
|
||||
* \param list `(list_t *)` Pointer to list.
|
||||
* \param current `(entry_t *)` Existing entry on list to be replaced.
|
||||
* \param replacement `(entry_t * restrict)` New entry to be the replacement.
|
||||
*/
|
||||
#define ns_list_replace(list, current, replacement) \
|
||||
ns_list_replace_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current), NS_LIST_TYPECHECK_(list, replacement))
|
||||
|
||||
/** \hideinitializer \brief Concatenate two lists.
|
||||
*
|
||||
* Attach the entries on the source list to the end of the destination
|
||||
* list, leaving the source list empty.
|
||||
*
|
||||
* \param dst `(list_t *)` Pointer to destination list.
|
||||
* \param src `(list_t *)` Pointer to source list.
|
||||
*
|
||||
*/
|
||||
#define ns_list_concatenate(dst, src) \
|
||||
(NS_PTR_MATCH_(dst, src, "concatenating different list types"), \
|
||||
ns_list_concatenate_(&(dst)->slist, &(src)->slist, NS_LIST_OFFSET_(src)))
|
||||
|
||||
/** \brief Iterate forwards over a list.
|
||||
*
|
||||
* Example:
|
||||
* ~~~
|
||||
* ns_list_foreach(const my_entry_t, cur, &my_list)
|
||||
* {
|
||||
* printf("%s\n", cur->name);
|
||||
* }
|
||||
* ~~~
|
||||
* Deletion of the current entry is not permitted as its next is checked after
|
||||
* running user code.
|
||||
*
|
||||
* The iteration pointer is declared inside the loop, using C99/C++, so it
|
||||
* is not accessible after the loop. This encourages good code style, and
|
||||
* matches the semantics of C++11's "ranged for", which only provides the
|
||||
* declaration form:
|
||||
* ~~~
|
||||
* for (const my_entry_t cur : my_list)
|
||||
* ~~~
|
||||
* If you need to see the value of the iteration pointer after a `break`,
|
||||
* you will need to assign it to a variable declared outside the loop before
|
||||
* breaking:
|
||||
* ~~~
|
||||
* my_entry_t *match = NULL;
|
||||
* ns_list_foreach(my_entry_t, cur, &my_list)
|
||||
* {
|
||||
* if (cur->id == id)
|
||||
* {
|
||||
* match = cur;
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* ~~~
|
||||
*
|
||||
* The user has to specify the entry type for the pointer definition, as type
|
||||
* extraction from the list argument isn't portable. On the other hand, this
|
||||
* also permits const qualifiers, as in the example above, and serves as
|
||||
* documentation. The entry type will be checked against the list type where the
|
||||
* compiler supports it.
|
||||
*
|
||||
* \param type Entry type `([const] entry_t)`.
|
||||
* \param e Name for iteration pointer to be defined
|
||||
* inside the loop.
|
||||
* \param list `(const list_t *)` Pointer to list - evaluated multiple times.
|
||||
*/
|
||||
#define ns_list_foreach(type, e, list) \
|
||||
for (type *e = ns_list_get_first(list); e; e = ns_list_get_next(list, e))
|
||||
|
||||
/** \brief Iterate forwards over a list, where user may delete.
|
||||
*
|
||||
* As ns_list_foreach(), but deletion of current entry is permitted as its
|
||||
* next pointer is recorded before running user code.
|
||||
*
|
||||
* Example:
|
||||
* ~~~
|
||||
* ns_list_foreach_safe(my_entry_t, cur, &my_list)
|
||||
* {
|
||||
* ns_list_remove(cur);
|
||||
* }
|
||||
* ~~~
|
||||
* \param type Entry type `(entry_t)`.
|
||||
* \param e Name for iteration pointer to be defined
|
||||
* inside the loop.
|
||||
* \param list `(list_t *)` Pointer to list - evaluated multiple times.
|
||||
*/
|
||||
#define ns_list_foreach_safe(type, e, list) \
|
||||
for (type *e = ns_list_get_first(list), *_next##e; \
|
||||
e && (_next##e = ns_list_get_next(list, e), true); e = _next##e)
|
||||
|
||||
/** \brief Iterate backwards over a list.
|
||||
*
|
||||
* As ns_list_foreach(), but going backwards - see its documentation.
|
||||
* Iterating forwards is *slightly* more efficient.
|
||||
*/
|
||||
#define ns_list_foreach_reverse(type, e, list) \
|
||||
for (type *e = ns_list_get_last(list); e; e = ns_list_get_previous(list, e))
|
||||
|
||||
/** \brief Iterate backwards over a list, where user may delete.
|
||||
*
|
||||
* As ns_list_foreach_safe(), but going backwards - see its documentation.
|
||||
* Iterating forwards is *slightly* more efficient.
|
||||
*/
|
||||
#define ns_list_foreach_reverse_safe(type, e, list) \
|
||||
for (type *e = ns_list_get_last(list), *_next##e; \
|
||||
e && (_next##e = ns_list_get_previous(list, e), true); e = _next##e)
|
||||
|
||||
/** \hideinitializer \brief Count entries on a list
|
||||
*
|
||||
* Unlike other operations, this is O(n). Note: if list might contain over
|
||||
* 65535 entries, this function **must not** be used to get the entry count.
|
||||
*
|
||||
* \param list `(const list_t *)` Pointer to list.
|
||||
|
||||
* \return `(uint_fast16_t)` Number of entries that are stored in list.
|
||||
*/
|
||||
#define ns_list_count(list) ns_list_count_(&(list)->slist, NS_LIST_OFFSET_(list))
|
||||
|
||||
/** \privatesection
|
||||
* Internal functions - designed to be accessed using corresponding macros above
|
||||
*/
|
||||
NS_INLINE void ns_list_init_(ns_list_t *list);
|
||||
NS_INLINE void ns_list_link_init_(ns_list_link_t *link);
|
||||
NS_INLINE void ns_list_add_to_start_(ns_list_t *list, ns_list_offset_t link_offset, void *restrict entry);
|
||||
NS_INLINE void ns_list_add_to_end_(ns_list_t *list, ns_list_offset_t link_offset, void *restrict entry);
|
||||
NS_INLINE void ns_list_add_before_(ns_list_offset_t link_offset, void *before, void *restrict entry);
|
||||
NS_INLINE void ns_list_add_after_(ns_list_t *list, ns_list_offset_t link_offset, void *after, void *restrict entry);
|
||||
NS_INLINE void *ns_list_get_next_(ns_list_offset_t link_offset, const void *current);
|
||||
NS_INLINE void *ns_list_get_previous_(const ns_list_t *list, ns_list_offset_t link_offset, const void *current);
|
||||
NS_INLINE void *ns_list_get_last_(const ns_list_t *list, ns_list_offset_t offset);
|
||||
NS_INLINE void ns_list_remove_(ns_list_t *list, ns_list_offset_t link_offset, void *entry);
|
||||
NS_INLINE void ns_list_replace_(ns_list_t *list, ns_list_offset_t link_offset, void *current, void *restrict replacement);
|
||||
NS_INLINE void ns_list_concatenate_(ns_list_t *dst, ns_list_t *src, ns_list_offset_t offset);
|
||||
NS_INLINE uint_fast16_t ns_list_count_(const ns_list_t *list, ns_list_offset_t link_offset);
|
||||
|
||||
/* Provide definitions, either for inlining, or for ns_list.c */
|
||||
#if defined NS_ALLOW_INLINING || defined NS_LIST_FN
|
||||
#ifndef NS_LIST_FN
|
||||
#define NS_LIST_FN NS_INLINE
|
||||
#endif
|
||||
|
||||
/* Pointer to the link member in entry e */
|
||||
#define NS_LIST_LINK_(e, offset) ((ns_list_link_t *)((char *)(e) + offset))
|
||||
|
||||
/* Lvalue of the next link pointer in entry e */
|
||||
#define NS_LIST_NEXT_(e, offset) (NS_LIST_LINK_(e, offset)->next)
|
||||
|
||||
/* Lvalue of the prev link pointer in entry e */
|
||||
#define NS_LIST_PREV_(e, offset) (NS_LIST_LINK_(e, offset)->prev)
|
||||
|
||||
/* Convert a pointer to a link member back to the entry;
|
||||
* works for linkptr either being a ns_list_link_t pointer, or its next pointer,
|
||||
* as the next pointer is first in the ns_list_link_t */
|
||||
#define NS_LIST_ENTRY_(linkptr, offset) ((void *)((char *)(linkptr) - offset))
|
||||
|
||||
NS_LIST_FN void ns_list_init_(ns_list_t *list)
|
||||
{
|
||||
list->first_entry = NULL;
|
||||
list->last_nextptr = &list->first_entry;
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_link_init_(ns_list_link_t *link)
|
||||
{
|
||||
NS_FUNNY_INTPTR_OK
|
||||
link->next = NS_LIST_POISON;
|
||||
link->prev = NS_LIST_POISON;
|
||||
NS_FUNNY_INTPTR_RESTORE
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_add_to_start_(ns_list_t *list, ns_list_offset_t offset, void *restrict entry)
|
||||
{
|
||||
void *next;
|
||||
|
||||
NS_LIST_PREV_(entry, offset) = &list->first_entry;
|
||||
NS_LIST_NEXT_(entry, offset) = next = list->first_entry;
|
||||
|
||||
if (next) {
|
||||
NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(entry, offset);
|
||||
} else {
|
||||
list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
|
||||
list->first_entry = entry;
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_add_after_(ns_list_t *list, ns_list_offset_t offset, void *current, void *restrict entry)
|
||||
{
|
||||
void *next;
|
||||
|
||||
NS_LIST_PREV_(entry, offset) = &NS_LIST_NEXT_(current, offset);
|
||||
NS_LIST_NEXT_(entry, offset) = next = NS_LIST_NEXT_(current, offset);
|
||||
|
||||
if (next) {
|
||||
NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(entry, offset);
|
||||
} else {
|
||||
list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
|
||||
NS_LIST_NEXT_(current, offset) = entry;
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_add_before_(ns_list_offset_t offset, void *current, void *restrict entry)
|
||||
{
|
||||
void **prev_nextptr;
|
||||
|
||||
NS_LIST_NEXT_(entry, offset) = current;
|
||||
NS_LIST_PREV_(entry, offset) = prev_nextptr = NS_LIST_PREV_(current, offset);
|
||||
*prev_nextptr = entry;
|
||||
NS_LIST_PREV_(current, offset) = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_add_to_end_(ns_list_t *list, ns_list_offset_t offset, void *restrict entry)
|
||||
{
|
||||
void **prev_nextptr;
|
||||
|
||||
NS_LIST_NEXT_(entry, offset) = NULL;
|
||||
NS_LIST_PREV_(entry, offset) = prev_nextptr = list->last_nextptr;
|
||||
*prev_nextptr = entry;
|
||||
list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void *ns_list_get_next_(ns_list_offset_t offset, const void *current)
|
||||
{
|
||||
return NS_LIST_NEXT_(current, offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void *ns_list_get_previous_(const ns_list_t *list, ns_list_offset_t offset, const void *current)
|
||||
{
|
||||
if (current == list->first_entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Tricky. We don't have a direct previous pointer, but a pointer to the
|
||||
// pointer that points to us - ie &head->first_entry OR &{prev}->next.
|
||||
// This makes life easier on insertion and removal, but this is where we
|
||||
// pay the price.
|
||||
|
||||
// We have to check manually for being the first entry above, so we know it's
|
||||
// a real link's next pointer. Then next is the first field of
|
||||
// ns_list_link_t, so we can use the normal offset value.
|
||||
|
||||
return NS_LIST_ENTRY_(NS_LIST_PREV_(current, offset), offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void *ns_list_get_last_(const ns_list_t *list, ns_list_offset_t offset)
|
||||
{
|
||||
if (!list->first_entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// See comments in ns_list_get_previous_()
|
||||
return NS_LIST_ENTRY_(list->last_nextptr, offset);
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_remove_(ns_list_t *list, ns_list_offset_t offset, void *removed)
|
||||
{
|
||||
void *next;
|
||||
void **prev_nextptr;
|
||||
|
||||
next = NS_LIST_NEXT_(removed, offset);
|
||||
prev_nextptr = NS_LIST_PREV_(removed, offset);
|
||||
if (next) {
|
||||
NS_LIST_PREV_(next, offset) = prev_nextptr;
|
||||
} else {
|
||||
list->last_nextptr = prev_nextptr;
|
||||
}
|
||||
*prev_nextptr = next;
|
||||
|
||||
ns_list_link_init_(NS_LIST_LINK_(removed, offset));
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_replace_(ns_list_t *list, ns_list_offset_t offset, void *current, void *restrict replacement)
|
||||
{
|
||||
void *next;
|
||||
void **prev_nextptr;
|
||||
|
||||
NS_LIST_PREV_(replacement, offset) = prev_nextptr = NS_LIST_PREV_(current, offset);
|
||||
NS_LIST_NEXT_(replacement, offset) = next = NS_LIST_NEXT_(current, offset);
|
||||
|
||||
if (next) {
|
||||
NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(replacement, offset);
|
||||
} else {
|
||||
list->last_nextptr = &NS_LIST_NEXT_(replacement, offset);
|
||||
}
|
||||
*prev_nextptr = replacement;
|
||||
|
||||
ns_list_link_init_(NS_LIST_LINK_(current, offset));
|
||||
}
|
||||
|
||||
NS_LIST_FN void ns_list_concatenate_(ns_list_t *dst, ns_list_t *src, ns_list_offset_t offset)
|
||||
{
|
||||
ns_list_link_t *src_first;
|
||||
|
||||
src_first = src->first_entry;
|
||||
if (!src_first) {
|
||||
return;
|
||||
}
|
||||
|
||||
*dst->last_nextptr = src_first;
|
||||
NS_LIST_PREV_(src_first, offset) = dst->last_nextptr;
|
||||
dst->last_nextptr = src->last_nextptr;
|
||||
|
||||
ns_list_init_(src);
|
||||
}
|
||||
|
||||
NS_LIST_FN uint_fast16_t ns_list_count_(const ns_list_t *list, ns_list_offset_t offset)
|
||||
{
|
||||
uint_fast16_t count = 0;
|
||||
|
||||
for (void *p = list->first_entry; p; p = NS_LIST_NEXT_(p, offset)) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif /* defined NS_ALLOW_INLINING || defined NS_LIST_FN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NS_LIST_H_ */
|
||||
|
||||
403
lib/amb1_sdk/common/network/coap/include/ns_types.h
Normal file
403
lib/amb1_sdk/common/network/coap/include/ns_types.h
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* Copyright (c) 2014-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.
|
||||
*/
|
||||
/*
|
||||
* ns_types.h - Basic compiler and type setup for Nanostack libraries.
|
||||
*/
|
||||
#ifndef NS_TYPES_H_
|
||||
#define NS_TYPES_H_
|
||||
|
||||
/** \file
|
||||
* \brief Basic compiler and type setup
|
||||
*
|
||||
* We currently assume C99 or later.
|
||||
*
|
||||
* C99 features being relied on:
|
||||
*
|
||||
* - <inttypes.h> and <stdbool.h>
|
||||
* - inline (with C99 semantics, not C++ as per default GCC);
|
||||
* - designated initialisers;
|
||||
* - compound literals;
|
||||
* - restrict;
|
||||
* - [static N] in array parameters;
|
||||
* - declarations in for statements;
|
||||
* - mixing declarations and statements
|
||||
*
|
||||
* Compilers should be set to C99 or later mode when building Nanomesh source.
|
||||
* For GCC this means "-std=gnu99" (C99 with usual GNU extensions).
|
||||
*
|
||||
* Also, a little extra care is required for public header files that could be
|
||||
* included from C++, especially as C++ lacks some C99 features.
|
||||
*
|
||||
* (TODO: as this is exposed to API users, do we need a predefine to distinguish
|
||||
* internal and external use, for finer control? Not yet, but maybe...)
|
||||
*/
|
||||
|
||||
/* Make sure <stdint.h> defines its macros if C++ */
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h> // includes <stdint.h>; debugf() users need PRIu32 etc
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* Create the optional <stdint.h> 24-bit types if they don't exist (worth trying
|
||||
* to use them, as they could exist and be more efficient than 32-bit on 8-bit
|
||||
* systems...)
|
||||
*/
|
||||
#ifndef UINT24_LEAST_MAX
|
||||
typedef uint_least32_t uint_least24_t;
|
||||
#define UINT_LEAST24_MAX UINT_LEAST32_MAX
|
||||
#define UINT24_C(x) UINT32_C(x)
|
||||
#define PRIoLEAST24 PRIoLEAST32
|
||||
#define PRIuLEAST24 PRIuLEAST32
|
||||
#define PRIxLEAST24 PRIxLEAST32
|
||||
#define PRIXLEAST24 PRIXLEAST32
|
||||
#endif
|
||||
|
||||
#ifndef INT24_LEAST_MAX
|
||||
typedef int_least32_t int_least24_t;
|
||||
#define INT24_LEAST_MIN INT_LEAST32_MIN
|
||||
#define INT24_LEAST_MAX INT_LEAST32_MAX
|
||||
#define INT24_C(x) INT32_C(x)
|
||||
#define PRIdLEAST24 PRIdLEAST32
|
||||
#define PRIiLEAST24 PRIiLEAST32
|
||||
#endif
|
||||
|
||||
#ifndef UINT24_FAST_MAX
|
||||
typedef uint_fast32_t uint_fast24_t;
|
||||
#define UINT_FAST24_MAX UINT_FAST32_MAX
|
||||
#define PRIoFAST24 PRIoFAST32
|
||||
#define PRIuFAST24 PRIuFAST32
|
||||
#define PRIxFAST24 PRIxFAST32
|
||||
#define PRIXFAST24 PRIXFAST32
|
||||
#endif
|
||||
|
||||
#ifndef INT24_FAST_MAX
|
||||
typedef int_fast32_t int_fast24_t;
|
||||
#define INT_FAST24_MIN INT_FAST32_MIN
|
||||
#define INT_FAST24_MAX INT_FAST32_MAX
|
||||
#define PRIdFAST24 PRIdFAST32
|
||||
#define PRIiFAST24 PRIiFAST32
|
||||
#endif
|
||||
|
||||
/* Function attribute - C11 "noreturn" or C++11 "[[noreturn]]" */
|
||||
#ifndef NS_NORETURN
|
||||
#if defined __cplusplus && __cplusplus >= 201103L
|
||||
#define NS_NORETURN [[noreturn]]
|
||||
#elif !defined __cplusplus && __STDC_VERSION__ >= 201112L
|
||||
#define NS_NORETURN _Noreturn
|
||||
#elif defined __GNUC__
|
||||
#define NS_NORETURN __attribute__((__noreturn__))
|
||||
#elif defined __CC_ARM
|
||||
#define NS_NORETURN __declspec(noreturn)
|
||||
#elif defined __IAR_SYSTEMS_ICC__
|
||||
#define NS_NORETURN __noreturn
|
||||
#else
|
||||
#define NS_NORETURN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* C11's "alignas" macro, emulated for integer expressions if necessary */
|
||||
#ifndef __alignas_is_defined
|
||||
#if defined __CC_ARM || defined __TASKING__
|
||||
#define alignas(n) __align(n)
|
||||
#define __alignas_is_defined 1
|
||||
#elif (__STDC_VERSION__ >= 201112L) || (defined __cplusplus && __cplusplus >= 201103L)
|
||||
#include <stdalign.h>
|
||||
#elif defined __GNUC__
|
||||
#define alignas(n) __attribute__((__aligned__(n)))
|
||||
#define __alignas_is_defined 1
|
||||
#elif defined __IAR_SYSTEMS_ICC__
|
||||
/* Does this really just apply to the next variable? */
|
||||
#define alignas(n) __Alignas(data_alignment=n)
|
||||
#define __Alignas(x) _Pragma(#x)
|
||||
#define __alignas_is_defined 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Marker for functions or objects that may be unused, suppressing warnings.
|
||||
* Place after the identifier:
|
||||
* ~~~
|
||||
* static int X MAYBE_UNUSED = 3;
|
||||
* static int foo(void) MAYBE_UNUSED;
|
||||
* ~~~
|
||||
*/
|
||||
#if defined __CC_ARM || defined __GNUC__
|
||||
#define MAYBE_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* C++ (even C++11) doesn't provide restrict: define away or provide
|
||||
* alternative.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#ifdef __GNUC__
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/**
|
||||
* C++ doesn't allow "static" in function parameter types: ie
|
||||
* ~~~
|
||||
* entry_t *find_entry(const uint8_t address[static 16])
|
||||
* ~~~
|
||||
* If a header file may be included from C++, use this __static define instead.
|
||||
*
|
||||
* (Syntax introduced in C99 - `uint8_t address[16]` in a prototype was always
|
||||
* equivalent to `uint8_t *address`, but the C99 addition of static tells the
|
||||
* compiler that address is never NULL, and always points to at least 16
|
||||
* elements. This adds no new type-checking, but the information could aid
|
||||
* compiler optimisation, and it can serve as documentation).
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define __static
|
||||
#else
|
||||
#define __static static
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define NS_GCC_VERSION (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNUC_PATCHLEVEL__)
|
||||
#endif
|
||||
|
||||
/** \brief Compile-time assertion
|
||||
*
|
||||
* C11 provides _Static_assert, as does GCC even in C99 mode (and
|
||||
* as a freestanding implementation, we can't rely on <assert.h> to get
|
||||
* the static_assert macro).
|
||||
* C++11 provides static_assert as a keyword, as does G++ in C++0x mode.
|
||||
*
|
||||
* The assertion acts as a declaration that can be placed at file scope, in a
|
||||
* code block (except after a label), or as a member of a struct/union. It
|
||||
* produces a compiler error if "test" evaluates to 0.
|
||||
*
|
||||
* Note that this *includes* the required semicolon when defined, else it
|
||||
* is totally empty, permitting use in structs. (If the user provided the `;`,
|
||||
* it would leave an illegal stray `;` if unavailable).
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
# if __cplusplus >= 201103L || __cpp_static_assert >= 200410
|
||||
# define NS_STATIC_ASSERT(test, str) static_assert(test, str);
|
||||
# elif defined __GXX_EXPERIMENTAL_CXX0X__ && NS_GCC_VERSION >= 40300
|
||||
# define NS_STATIC_ASSERT(test, str) __extension__ static_assert(test, str);
|
||||
# else
|
||||
# define NS_STATIC_ASSERT(test, str)
|
||||
# endif
|
||||
#else /* C */
|
||||
# if __STDC_VERSION__ >= 201112L
|
||||
# define NS_STATIC_ASSERT(test, str) _Static_assert(test, str);
|
||||
# elif defined __GNUC__ && NS_GCC_VERSION >= 40600 && !defined __CC_ARM
|
||||
# ifdef _Static_assert
|
||||
/*
|
||||
* Some versions of glibc cdefs.h (which comes in via <stdint.h> above)
|
||||
* attempt to define their own _Static_assert (if GCC < 4.6 or
|
||||
* __STRICT_ANSI__) using an extern declaration, which doesn't work in a
|
||||
* struct/union.
|
||||
*
|
||||
* For GCC >= 4.6 and __STRICT_ANSI__, we can do better - just use
|
||||
* the built-in _Static_assert with __extension__. We have to do this, as
|
||||
* ns_list.h needs to use it in a union. No way to get at it though, without
|
||||
* overriding their define.
|
||||
*/
|
||||
# undef _Static_assert
|
||||
# define _Static_assert(x, y) __extension__ _Static_assert(x, y)
|
||||
# endif
|
||||
# define NS_STATIC_ASSERT(test, str) __extension__ _Static_assert(test, str);
|
||||
# else
|
||||
# define NS_STATIC_ASSERT(test, str)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** \brief Pragma to suppress warnings about unusual pointer values.
|
||||
*
|
||||
* Useful if using "poison" values.
|
||||
*/
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#define NS_FUNNY_INTPTR_OK _Pragma("diag_suppress=Pe1053")
|
||||
#define NS_FUNNY_INTPTR_RESTORE _Pragma("diag_default=Pe1053")
|
||||
#else
|
||||
#define NS_FUNNY_INTPTR_OK
|
||||
#define NS_FUNNY_INTPTR_RESTORE
|
||||
#endif
|
||||
|
||||
/** \brief Pragma to suppress warnings about always true/false comparisons
|
||||
*/
|
||||
#if defined __GNUC__ && NS_GCC_VERSION >= 40600 && !defined __CC_ARM
|
||||
#define NS_FUNNY_COMPARE_OK _Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
|
||||
#define NS_FUNNY_COMPARE_RESTORE _Pragma("GCC diagnostic pop")
|
||||
#else
|
||||
#define NS_FUNNY_COMPARE_OK
|
||||
#define NS_FUNNY_COMPARE_RESTORE
|
||||
#endif
|
||||
|
||||
/** \brief Pragma to suppress warnings arising from dummy definitions.
|
||||
*
|
||||
* Useful when you have function-like macros that returning constants
|
||||
* in cut-down builds. Can be fairly cavalier about disabling as we
|
||||
* do not expect every build to use this macro. Generic builds of
|
||||
* components should ensure this is not included by only using it in
|
||||
* a ifdef blocks providing dummy definitions.
|
||||
*/
|
||||
#ifdef __CC_ARM
|
||||
// statement is unreachable(111), controlling expression is constant(236), expression has no effect(174),
|
||||
// function was declared but never referenced(177), variable was set but never used(550)
|
||||
#define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=111,236,174,177,550")
|
||||
#elif defined __IAR_SYSTEMS_ICC__
|
||||
// controlling expression is constant
|
||||
#define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=Pe236")
|
||||
#else
|
||||
#define NS_DUMMY_DEFINITIONS_OK
|
||||
#endif
|
||||
|
||||
/** \brief Convert pointer to member to pointer to containing structure */
|
||||
#define NS_CONTAINER_OF(ptr, type, member) \
|
||||
((type *) ((char *) (ptr) - offsetof(type, member)))
|
||||
|
||||
/*
|
||||
* Inlining could cause problems when mixing with C++; provide a mechanism to
|
||||
* disable it. This could also be turned off for other reasons (although
|
||||
* this can usually be done through a compiler flag, eg -O0 on gcc).
|
||||
*/
|
||||
#ifndef __cplusplus
|
||||
#define NS_ALLOW_INLINING
|
||||
#endif
|
||||
|
||||
/* There is inlining problem in GCC version 4.1.x and we know it works in 4.6.3 */
|
||||
#if defined __GNUC__ && NS_GCC_VERSION < 40600
|
||||
#undef NS_ALLOW_INLINING
|
||||
#endif
|
||||
|
||||
/** \brief Mark a potentially-inlineable function.
|
||||
*
|
||||
* We follow C99 semantics, which requires precisely one external definition.
|
||||
* To also allow inlining to be totally bypassed under control of
|
||||
* NS_ALLOW_INLINING, code can be structured as per the example of ns_list:
|
||||
*
|
||||
* foo.h
|
||||
* -----
|
||||
* ~~~
|
||||
* NS_INLINE int my_func(int);
|
||||
*
|
||||
* #if defined NS_ALLOW_INLINING || defined FOO_FN
|
||||
* #ifndef FOO_FN
|
||||
* #define FOO_FN NS_INLINE
|
||||
* #endif
|
||||
* FOO_FN int my_func(int a)
|
||||
* {
|
||||
* definition;
|
||||
* }
|
||||
* #endif
|
||||
* ~~~
|
||||
* foo.c
|
||||
* -----
|
||||
* ~~~
|
||||
* #define FOO_FN extern
|
||||
* #include "foo.h"
|
||||
* ~~~
|
||||
* Which generates:
|
||||
* ~~~
|
||||
* NS_ALLOW_INLINING set NS_ALLOW_INLINING unset
|
||||
* ===================== =======================
|
||||
* Include foo.h Include foo.h
|
||||
* ------------- -------------
|
||||
* inline int my_func(int); int my_func(int);
|
||||
*
|
||||
* // inline definition
|
||||
* inline int my_func(int a)
|
||||
* {
|
||||
* definition;
|
||||
* }
|
||||
*
|
||||
* Compile foo.c Compile foo.c
|
||||
* ------------- -------------
|
||||
* (from .h) inline int my_func(int); int my_func(int);
|
||||
*
|
||||
* // external definition
|
||||
* // because of no "inline" // normal external definition
|
||||
* extern int my_func(int a) extern int my_func(int a)
|
||||
* { {
|
||||
* definition; definition;
|
||||
* } }
|
||||
* ~~~
|
||||
*
|
||||
* Note that even with inline keywords, whether the compiler inlines or not is
|
||||
* up to it. For example, gcc at "-O0" will not inline at all, and will always
|
||||
* call the real functions in foo.o, just as if NS_ALLOW_INLINING was unset.
|
||||
* At "-O2", gcc could potentially inline everything, meaning that foo.o is not
|
||||
* referenced at all.
|
||||
*
|
||||
* Alternatively, you could use "static inline", which gives every caller its
|
||||
* own internal definition. This is compatible with C++ inlining (which expects
|
||||
* the linker to eliminate duplicates), but in C it's less efficient if the code
|
||||
* ends up non-inlined, and it's harder to breakpoint. I don't recommend it
|
||||
* except for the most trivial functions (which could then probably be macros).
|
||||
*/
|
||||
#ifdef NS_ALLOW_INLINING
|
||||
#define NS_INLINE inline
|
||||
#else
|
||||
#define NS_INLINE
|
||||
#endif
|
||||
|
||||
#if defined __SDCC_mcs51 || defined __ICC8051__ || defined __C51__
|
||||
|
||||
/* The 8051 environments: SDCC (historic), IAR (current), Keil (future?) */
|
||||
|
||||
#define NS_LARGE __xdata
|
||||
#define NS_LARGE_PTR __xdata
|
||||
#ifdef __ICC8051__
|
||||
#define NS_REENTRANT
|
||||
#define NS_REENTRANT_PREFIX __idata_reentrant
|
||||
#else
|
||||
#define NS_REENTRANT __reentrant
|
||||
#define NS_REENTRANT_PREFIX
|
||||
#endif
|
||||
#define NS_NEAR_FUNC __near_func
|
||||
|
||||
#else
|
||||
|
||||
/* "Normal" systems. Define it all away. */
|
||||
#define NS_LARGE
|
||||
#define NS_LARGE_PTR
|
||||
#define NS_REENTRANT
|
||||
#define NS_REENTRANT_PREFIX
|
||||
#define NS_NEAR_FUNC
|
||||
|
||||
#endif
|
||||
|
||||
/** \brief Scatter-gather descriptor
|
||||
*
|
||||
* Slightly optimised for small platforms - we assume we won't need any
|
||||
* element bigger than 64K.
|
||||
*/
|
||||
typedef struct ns_iovec {
|
||||
void *iov_base;
|
||||
uint_fast16_t iov_len;
|
||||
} ns_iovec_t;
|
||||
|
||||
#endif /* NS_TYPES_H */
|
||||
126
lib/amb1_sdk/common/network/coap/include/sn_coap_ameba_port.h
Normal file
126
lib/amb1_sdk/common/network/coap/include/sn_coap_ameba_port.h
Normal file
@@ -0,0 +1,126 @@
|
||||
#ifndef SN_COAP_AMEBA_PORT
|
||||
#define SN_COAP_AMEBA_PORT
|
||||
|
||||
/** @addtogroup coap COAP
|
||||
* @ingroup network
|
||||
* @brief mbed CoAP APIs and Ameba wrappers
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "diag.h"
|
||||
#include "platform_stdlib.h"
|
||||
#include "osdep_service.h"
|
||||
#include "wifi_constants.h"
|
||||
#include "wifi_conf.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sn_coap_protocol.h"
|
||||
|
||||
#define randLIB_seed_random() NULL /*!< Not used */
|
||||
|
||||
#define COAP_DBG_EN 0 /*!< Flag to enable / disable CoAP debug message in function **tr_debug()** */
|
||||
#define COAP_DBG_DETAIL 0 /*!< Flage to enable / disable detialed log in CoAP debug message in function **tr_debug()** */
|
||||
|
||||
/**
|
||||
* \brief print CoAP debug message
|
||||
*/
|
||||
#define tr_debug(fmat,...) \
|
||||
do { \
|
||||
if(COAP_DBG_EN){ \
|
||||
printf(fmat "\n", ##__VA_ARGS__); \
|
||||
if(COAP_DBG_DETAIL){\
|
||||
printf("Function: %s :: Line: %d\n\n",__FUNCTION__,__LINE__);\
|
||||
}\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* \brief This function is called in **sn_coap_protocol_init()** for ramdom message ID
|
||||
* \return A random 16bit unsigned value
|
||||
*/
|
||||
uint16_t randLIB_get_16bit(void);
|
||||
|
||||
/**
|
||||
* \brief Ameba **malloc()** function wrapper
|
||||
* \param size: memory size to be allocated
|
||||
* \return NULL = if memory allocation failed
|
||||
* \return void* pointer to allocated memory = if allocation success
|
||||
*/
|
||||
void* coap_malloc(uint16_t size);
|
||||
|
||||
/**
|
||||
* \brief Ameba **free()** function wrapper
|
||||
* \param *addr: memory address to be freed
|
||||
*/
|
||||
void coap_free(void* addr);
|
||||
|
||||
/**
|
||||
* \brief Ameba **calloc()** function wrapper, the effective result is the allocation of a zero-initialized memory block of *size* bytes
|
||||
* \param size: memory size to be allocated
|
||||
* \return NULL = if memory allocation failed
|
||||
* \return void* pointer to the allocated memory = if memory allocation success
|
||||
*/
|
||||
void* coap_calloc(uint32_t size);
|
||||
|
||||
/**
|
||||
* \brief Ameba **socket()** function wrapper, creates a **Datagrams type** i.e. *SOCK_DGRAM* socket
|
||||
* \return Non-negative Integer (socket file descriptor) = if successfully completion
|
||||
* \return -1 = if failed to create socket
|
||||
*/
|
||||
int coap_sock_open(void);
|
||||
|
||||
/**
|
||||
* \brief Ameba **close()** function wrapper, closes a socket file descriptor
|
||||
* \param sock_fd: the socket file descriptor is going to be closed.
|
||||
* \return -1 = if close operation failed
|
||||
* \return 0 = if close operation success
|
||||
*/
|
||||
int coap_sock_close(int socket_fd);
|
||||
|
||||
/**
|
||||
* \brief Ameba **sn_coap_protocol_init()** function wrapper, initializes CoAP Protocol part.
|
||||
* \param *coap_tx_callback : function callback pointer to tx function for sending coap messages
|
||||
* \param *coap_rx_callback : function callback pointer to rx function, used to return CoAP header struct with status COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED
|
||||
* when re-sendings exceeded. If set to NULL, no error message is returned.
|
||||
* \return pointer to CoAP handle = if success
|
||||
* \return NULL = if failed
|
||||
*/
|
||||
struct coap_s * coap_protocol_init(uint8_t (*coap_tx_callback)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *), int8_t (*coap_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *));
|
||||
|
||||
/**
|
||||
* \brief Send the constructed CoAP message to designated host address on the specific port number
|
||||
* \param *to_address : the host / domain / ip address that the message is targeted to
|
||||
* \param port : port number that the host is used to receive the message
|
||||
* \param socket : socket file descriptor used to send the message
|
||||
* \param *coap_msg_hdr : constructed CoAP message pointer
|
||||
* \return The number of bytes sent = if fuccess
|
||||
* \return -1 = if failed
|
||||
*/
|
||||
int coap_send(char *to_address, uint16_t port, int socket, sn_coap_hdr_s *coap_msg_hdr);
|
||||
|
||||
/**
|
||||
* \brief Receive the constructed CoAP message from host
|
||||
* \param socket : socket file descriptor used to receive the message
|
||||
* \param *from_address : an internet address pointer, which the sender address is to be stored into
|
||||
* \param *buf : memory buffer that used to store the received message
|
||||
* \param buf_size : specifies the length in bytes of the buffer pointed to by the *buf* argument.
|
||||
* \return The length of the message in bytes : if successful completion
|
||||
* \return 0 = If no messages are available to be received
|
||||
* \return -1 = receive message failed
|
||||
*/
|
||||
int coap_recv(int socket, struct sockaddr_in *from_address, void *buf, uint32_t buf_size);
|
||||
|
||||
/**
|
||||
* \brief Print CoAP message header (for debug use)
|
||||
* \param *parsed_hdr : pointer to constructed CoAP message header
|
||||
*/
|
||||
void coap_print_hdr(sn_coap_hdr_s* parsed_hdr);
|
||||
|
||||
/*\@}*/
|
||||
|
||||
#endif //SN_COAP_AMEBA_PORT
|
||||
443
lib/amb1_sdk/common/network/coap/include/sn_coap_header.h
Normal file
443
lib/amb1_sdk/common/network/coap/include/sn_coap_header.h
Normal file
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* Copyright (c) 2011-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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file sn_coap_header.h
|
||||
*
|
||||
* \brief CoAP C-library User header interface header file
|
||||
*/
|
||||
|
||||
#ifndef SN_COAP_HEADER_H_
|
||||
#define SN_COAP_HEADER_H_
|
||||
|
||||
/** @addtogroup coap COAP
|
||||
* @ingroup network
|
||||
* @brief mbed CoAP APIs and Ameba wrappers
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Handle structure */
|
||||
struct coap_s;
|
||||
|
||||
/* * * * * * * * * * * * * * */
|
||||
/* * * * ENUMERATIONS * * * */
|
||||
/* * * * * * * * * * * * * * */
|
||||
|
||||
/**
|
||||
* \brief Enumeration for CoAP Version
|
||||
*/
|
||||
typedef enum coap_version_ {
|
||||
COAP_VERSION_1 = 0x40,
|
||||
COAP_VERSION_UNKNOWN = 0xFF
|
||||
} coap_version_e;
|
||||
|
||||
/**
|
||||
* \brief Enumeration for CoAP Message type, used in CoAP Header
|
||||
*/
|
||||
typedef enum sn_coap_msg_type_ {
|
||||
COAP_MSG_TYPE_CONFIRMABLE = 0x00, /**< Reliable Request messages */
|
||||
COAP_MSG_TYPE_NON_CONFIRMABLE = 0x10, /**< Non-reliable Request and Response messages */
|
||||
COAP_MSG_TYPE_ACKNOWLEDGEMENT = 0x20, /**< Response to a Confirmable Request */
|
||||
COAP_MSG_TYPE_RESET = 0x30 /**< Answer a Bad Request */
|
||||
} sn_coap_msg_type_e;
|
||||
|
||||
/**
|
||||
* \brief Enumeration for CoAP Message code, used in CoAP Header
|
||||
*/
|
||||
typedef enum sn_coap_msg_code_ {
|
||||
COAP_MSG_CODE_EMPTY = 0,
|
||||
COAP_MSG_CODE_REQUEST_GET = 1,
|
||||
COAP_MSG_CODE_REQUEST_POST = 2,
|
||||
COAP_MSG_CODE_REQUEST_PUT = 3,
|
||||
COAP_MSG_CODE_REQUEST_DELETE = 4,
|
||||
|
||||
COAP_MSG_CODE_RESPONSE_CREATED = 65,
|
||||
COAP_MSG_CODE_RESPONSE_DELETED = 66,
|
||||
COAP_MSG_CODE_RESPONSE_VALID = 67,
|
||||
COAP_MSG_CODE_RESPONSE_CHANGED = 68,
|
||||
COAP_MSG_CODE_RESPONSE_CONTENT = 69,
|
||||
COAP_MSG_CODE_RESPONSE_CONTINUE = 95,
|
||||
COAP_MSG_CODE_RESPONSE_BAD_REQUEST = 128,
|
||||
COAP_MSG_CODE_RESPONSE_UNAUTHORIZED = 129,
|
||||
COAP_MSG_CODE_RESPONSE_BAD_OPTION = 130,
|
||||
COAP_MSG_CODE_RESPONSE_FORBIDDEN = 131,
|
||||
COAP_MSG_CODE_RESPONSE_NOT_FOUND = 132,
|
||||
COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED = 133,
|
||||
COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE = 134,
|
||||
COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE = 136,
|
||||
COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED = 140,
|
||||
COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE = 141,
|
||||
COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT = 143,
|
||||
COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR = 160,
|
||||
COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED = 161,
|
||||
COAP_MSG_CODE_RESPONSE_BAD_GATEWAY = 162,
|
||||
COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE = 163,
|
||||
COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT = 164,
|
||||
COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED = 165
|
||||
} sn_coap_msg_code_e;
|
||||
|
||||
/**
|
||||
* \brief Enumeration for CoAP Option number, used in CoAP Header
|
||||
*/
|
||||
typedef enum sn_coap_option_numbers_ {
|
||||
COAP_OPTION_IF_MATCH = 1,
|
||||
COAP_OPTION_URI_HOST = 3,
|
||||
COAP_OPTION_ETAG = 4,
|
||||
COAP_OPTION_IF_NONE_MATCH = 5,
|
||||
COAP_OPTION_OBSERVE = 6,
|
||||
COAP_OPTION_URI_PORT = 7,
|
||||
COAP_OPTION_LOCATION_PATH = 8,
|
||||
COAP_OPTION_URI_PATH = 11,
|
||||
COAP_OPTION_CONTENT_FORMAT = 12,
|
||||
COAP_OPTION_MAX_AGE = 14,
|
||||
COAP_OPTION_URI_QUERY = 15,
|
||||
COAP_OPTION_ACCEPT = 17,
|
||||
COAP_OPTION_LOCATION_QUERY = 20,
|
||||
COAP_OPTION_BLOCK2 = 23,
|
||||
COAP_OPTION_BLOCK1 = 27,
|
||||
COAP_OPTION_SIZE2 = 28,
|
||||
COAP_OPTION_PROXY_URI = 35,
|
||||
COAP_OPTION_PROXY_SCHEME = 39,
|
||||
COAP_OPTION_SIZE1 = 60
|
||||
// 128 = (Reserved)
|
||||
// 132 = (Reserved)
|
||||
// 136 = (Reserved)
|
||||
} sn_coap_option_numbers_e;
|
||||
|
||||
/**
|
||||
* \brief Enumeration for CoAP Content Format codes
|
||||
*/
|
||||
typedef enum sn_coap_content_format_ {
|
||||
COAP_CT_NONE = -1, // internal
|
||||
COAP_CT_TEXT_PLAIN = 0,
|
||||
COAP_CT_LINK_FORMAT = 40,
|
||||
COAP_CT_XML = 41,
|
||||
COAP_CT_OCTET_STREAM = 42,
|
||||
COAP_CT_EXI = 47,
|
||||
COAP_CT_JSON = 50,
|
||||
COAP_CT__MAX = 0xffff
|
||||
} sn_coap_content_format_e;
|
||||
|
||||
/**
|
||||
* \brief Enumeration for CoAP Observe option values
|
||||
*
|
||||
* draft-ietf-core-observe-16
|
||||
*/
|
||||
typedef enum sn_coap_observe_ {
|
||||
COAP_OBSERVE_NONE = -1, // internal
|
||||
|
||||
// Values for GET requests
|
||||
COAP_OBSERVE_REGISTER = 0,
|
||||
COAP_OBSERVE_DEREGISTER = 1,
|
||||
|
||||
// In responses, value is a 24-bit opaque sequence number
|
||||
COAP_OBSERVE__MAX = 0xffffff
|
||||
} sn_coap_observe_e;
|
||||
|
||||
/**
|
||||
* \brief Enumeration for CoAP status, used in CoAP Header
|
||||
*/
|
||||
typedef enum sn_coap_status_ {
|
||||
COAP_STATUS_OK = 0, /**< Default value is OK */
|
||||
COAP_STATUS_PARSER_ERROR_IN_HEADER = 1, /**< CoAP will send Reset message to invalid message sender */
|
||||
COAP_STATUS_PARSER_DUPLICATED_MSG = 2, /**< CoAP will send Acknowledgement message to duplicated message sender */
|
||||
COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING = 3, /**< User will get whole message after all message blocks received.
|
||||
User must release messages with this status. */
|
||||
COAP_STATUS_PARSER_BLOCKWISE_ACK = 4, /**< Acknowledgement for sent Blockwise message received */
|
||||
COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED = 5, /**< Blockwise message received but not supported by compiling switch */
|
||||
COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED = 6, /**< Blockwise message fully received and returned to app.
|
||||
User must take care of releasing whole payload of the blockwise messages */
|
||||
COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED = 7 /**< When re-transmissions have been done and ACK not received, CoAP library calls
|
||||
RX callback with this status */
|
||||
} sn_coap_status_e;
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * */
|
||||
/* * * * STRUCTURES * * * */
|
||||
/* * * * * * * * * * * * * */
|
||||
|
||||
/**
|
||||
* \brief Structure for CoAP Options
|
||||
*/
|
||||
typedef struct sn_coap_options_list_ {
|
||||
uint8_t etag_len; /**< 1-8 bytes. Repeatable */
|
||||
unsigned int use_size1:1;
|
||||
unsigned int use_size2:1;
|
||||
|
||||
uint16_t proxy_uri_len; /**< 1-1034 bytes. */
|
||||
uint16_t uri_host_len; /**< 1-255 bytes. */
|
||||
uint16_t location_path_len; /**< 0-255 bytes. Repeatable */
|
||||
uint16_t location_query_len; /**< 0-255 bytes. Repeatable */
|
||||
uint16_t uri_query_len; /**< 1-255 bytes. Repeatable */
|
||||
|
||||
sn_coap_content_format_e accept; /**< Value 0-65535. COAP_CT_NONE if not used */
|
||||
|
||||
uint32_t max_age; /**< Value in seconds (default is 60) */
|
||||
uint32_t size1; /**< 0-4 bytes. */
|
||||
uint32_t size2; /**< 0-4 bytes. */
|
||||
int32_t uri_port; /**< Value 0-65535. -1 if not used */
|
||||
int32_t observe; /**< Value 0-0xffffff. -1 if not used */
|
||||
int32_t block1; /**< Value 0-0xffffff. -1 if not used. Not for user */
|
||||
int32_t block2; /**< Value 0-0xffffff. -1 if not used. Not for user */
|
||||
|
||||
uint8_t *proxy_uri_ptr; /**< Must be set to NULL if not used */
|
||||
uint8_t *etag_ptr; /**< Must be set to NULL if not used */
|
||||
uint8_t *uri_host_ptr; /**< Must be set to NULL if not used */
|
||||
uint8_t *location_path_ptr; /**< Must be set to NULL if not used */
|
||||
uint8_t *location_query_ptr; /**< Must be set to NULL if not used */
|
||||
uint8_t *uri_query_ptr; /**< Must be set to NULL if not used */
|
||||
} sn_coap_options_list_s;
|
||||
|
||||
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||
/* !!! Main CoAP message struct !!! */
|
||||
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||
|
||||
/**
|
||||
* \brief Main CoAP message struct
|
||||
*/
|
||||
typedef struct sn_coap_hdr_ {
|
||||
uint8_t token_len; /**< 1-8 bytes. */
|
||||
|
||||
sn_coap_status_e coap_status; /**< Used for telling to User special cases when parsing message */
|
||||
sn_coap_msg_code_e msg_code; /**< Empty: 0; Requests: 1-31; Responses: 64-191 */
|
||||
|
||||
sn_coap_msg_type_e msg_type; /**< Confirmable, Non-Confirmable, Acknowledgement or Reset */
|
||||
sn_coap_content_format_e content_format; /**< Set to COAP_CT_NONE if not used */
|
||||
|
||||
uint16_t msg_id; /**< Message ID. Parser sets parsed message ID, builder sets message ID of built coap message */
|
||||
uint16_t uri_path_len; /**< 0-255 bytes. Repeatable. */
|
||||
uint16_t payload_len; /**< Must be set to zero if not used */
|
||||
|
||||
uint8_t *token_ptr; /**< Must be set to NULL if not used */
|
||||
uint8_t *uri_path_ptr; /**< Must be set to NULL if not used. E.g: temp1/temp2 */
|
||||
uint8_t *payload_ptr; /**< Must be set to NULL if not used */
|
||||
|
||||
/* Here are not so often used Options */
|
||||
sn_coap_options_list_s *options_list_ptr; /**< Must be set to NULL if not used */
|
||||
} sn_coap_hdr_s;
|
||||
|
||||
/* * * * * * * * * * * * * * */
|
||||
/* * * * ENUMERATIONS * * * */
|
||||
/* * * * * * * * * * * * * * */
|
||||
|
||||
|
||||
/**
|
||||
* \brief Used protocol
|
||||
*/
|
||||
typedef enum sn_nsdl_capab_ {
|
||||
SN_NSDL_PROTOCOL_HTTP = 0x01, /**< Unsupported */
|
||||
SN_NSDL_PROTOCOL_HTTPS = 0x02, /**< Unsupported */
|
||||
SN_NSDL_PROTOCOL_COAP = 0x04 /**< Supported */
|
||||
} sn_nsdl_capab_e;
|
||||
|
||||
/* * * * * * * * * * * * * */
|
||||
/* * * * STRUCTURES * * * */
|
||||
/* * * * * * * * * * * * * */
|
||||
|
||||
|
||||
/**
|
||||
* \brief Used for creating manually registration message with sn_coap_register()
|
||||
*/
|
||||
typedef struct registration_info_ {
|
||||
uint8_t endpoint_len;
|
||||
uint8_t endpoint_type_len;
|
||||
uint16_t links_len;
|
||||
|
||||
uint8_t *endpoint_ptr; /**< Endpoint name */
|
||||
uint8_t *endpoint_type_ptr; /**< Endpoint type */
|
||||
uint8_t *links_ptr; /**< Resource registration string */
|
||||
} registration_info_t;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Address type of given address
|
||||
*/
|
||||
typedef enum sn_nsdl_addr_type_ {
|
||||
SN_NSDL_ADDRESS_TYPE_IPV6 = 0x01, /**< Supported */
|
||||
SN_NSDL_ADDRESS_TYPE_IPV4 = 0x02, /**< Supported */
|
||||
SN_NSDL_ADDRESS_TYPE_HOSTNAME = 0x03, /**< Unsupported */
|
||||
SN_NSDL_ADDRESS_TYPE_NONE = 0xFF
|
||||
} sn_nsdl_addr_type_e;
|
||||
|
||||
/**
|
||||
* \brief Address structure of Packet data
|
||||
*/
|
||||
typedef struct sn_nsdl_addr_ {
|
||||
uint8_t addr_len;
|
||||
sn_nsdl_addr_type_e type;
|
||||
uint16_t port;
|
||||
uint8_t *addr_ptr;
|
||||
} sn_nsdl_addr_s;
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* * * * EXTERNAL FUNCTION PROTOTYPES * * * */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * */
|
||||
/**
|
||||
* \fn sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr)
|
||||
*
|
||||
* \brief Parses CoAP message from given Packet data
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
*
|
||||
* \param packet_data_len is length of given Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param *packet_data_ptr is source for Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param *coap_version_ptr is destination for parsed CoAP specification version
|
||||
*
|
||||
* \return Return value is pointer to parsed CoAP message.\n
|
||||
* In following failure cases NULL is returned:\n
|
||||
* -Failure in given pointer (= NULL)\n
|
||||
* -Failure in memory allocation (malloc() returns NULL)
|
||||
*/
|
||||
extern sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr);
|
||||
|
||||
/**
|
||||
* \fn void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
|
||||
*
|
||||
* \brief Releases memory of given CoAP message
|
||||
*
|
||||
* \note Does not release Payload part
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
*
|
||||
* \param *freed_coap_msg_ptr is pointer to released CoAP message
|
||||
*/
|
||||
extern void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr);
|
||||
|
||||
/**
|
||||
* \fn int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
*
|
||||
* \brief Builds an outgoing message buffer from a CoAP header structure.
|
||||
*
|
||||
* \param *dst_packet_data_ptr is pointer to allocated destination to built CoAP packet
|
||||
*
|
||||
* \param *src_coap_msg_ptr is pointer to source structure for building Packet data
|
||||
*
|
||||
* \return Return value is byte count of built Packet data. In failure cases:\n
|
||||
* -1 = Failure in given CoAP header structure\n
|
||||
* -2 = Failure in given pointer (= NULL)
|
||||
*/
|
||||
extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
|
||||
/**
|
||||
* \fn uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr)
|
||||
*
|
||||
* \brief Calculates needed Packet data memory size for given CoAP message
|
||||
*
|
||||
* \param *src_coap_msg_ptr is pointer to data which needed Packet
|
||||
* data length is calculated
|
||||
*
|
||||
* \return Return value is count of needed memory as bytes for build Packet data
|
||||
* Null if failed
|
||||
*/
|
||||
extern uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr);
|
||||
|
||||
/**
|
||||
* \fn int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_size)
|
||||
*
|
||||
* \brief Builds an outgoing message buffer from a CoAP header structure.
|
||||
*
|
||||
* \param *dst_packet_data_ptr is pointer to allocated destination to built CoAP packet
|
||||
*
|
||||
* \param *src_coap_msg_ptr is pointer to source structure for building Packet data
|
||||
*
|
||||
* \param blockwise_payload_size Blockwise message maximum payload size
|
||||
*
|
||||
* \return Return value is byte count of built Packet data. In failure cases:\n
|
||||
* -1 = Failure in given CoAP header structure\n
|
||||
* -2 = Failure in given pointer (= NULL)
|
||||
*/
|
||||
extern int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
|
||||
|
||||
/**
|
||||
* \fn uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
|
||||
*
|
||||
* \brief Calculates needed Packet data memory size for given CoAP message
|
||||
*
|
||||
* \param *src_coap_msg_ptr is pointer to data which needed Packet
|
||||
* data length is calculated
|
||||
* \param blockwise_payload_size Blockwise message maximum payload size
|
||||
*
|
||||
* \return Return value is count of needed memory as bytes for build Packet data
|
||||
* Null if failed
|
||||
*/
|
||||
extern uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
|
||||
|
||||
/**
|
||||
* \fn sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
|
||||
*
|
||||
* \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
* \param *coap_packet_ptr The request packet pointer
|
||||
* \param msg_code response messages code
|
||||
*
|
||||
* \return *coap_packet_ptr The allocated and pre-filled response packet pointer
|
||||
* NULL Error in parsing the request
|
||||
*
|
||||
*/
|
||||
extern sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code);
|
||||
|
||||
/**
|
||||
* \brief Initialise a message structure to empty
|
||||
*
|
||||
* \param *coap_msg_ptr is pointer to CoAP message to initialise
|
||||
*
|
||||
* \return Return value is pointer passed in
|
||||
*/
|
||||
extern sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr);
|
||||
|
||||
/**
|
||||
* \brief Allocate an empty message structure
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
*
|
||||
* \return Return value is pointer to an empty CoAP message.\n
|
||||
* In following failure cases NULL is returned:\n
|
||||
* -Failure in given pointer (= NULL)\n
|
||||
* -Failure in memory allocation (malloc() returns NULL)
|
||||
*/
|
||||
extern sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle);
|
||||
|
||||
/**
|
||||
* \brief Allocates and initializes options list structure
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
* \param *coap_msg_ptr is pointer to CoAP message that will contain the options
|
||||
*
|
||||
* If the message already has a pointer to an option structure, that pointer
|
||||
* is returned, rather than a new structure being allocated.
|
||||
*
|
||||
* \return Return value is pointer to the CoAP options structure.\n
|
||||
* In following failure cases NULL is returned:\n
|
||||
* -Failure in given pointer (= NULL)\n
|
||||
* -Failure in memory allocation (malloc() returns NULL)
|
||||
*/
|
||||
extern sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*\@}*/
|
||||
|
||||
#endif /* SN_COAP_HEADER_H_ */
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2011-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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file sn_coap_header_internal.h
|
||||
*
|
||||
* \brief Header file for CoAP Header part
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef SN_COAP_HEADER_INTERNAL_H_
|
||||
#define SN_COAP_HEADER_INTERNAL_H_
|
||||
|
||||
|
||||
/* * * * * * * * * * * */
|
||||
/* * * * DEFINES * * * */
|
||||
/* * * * * * * * * * * */
|
||||
|
||||
#define COAP_VERSION COAP_VERSION_1 /* Tells which IETF CoAP specification version the CoAP message supports. */
|
||||
/* This value is written to CoAP message header part. */
|
||||
|
||||
/* CoAP Header defines */
|
||||
#define COAP_HEADER_LENGTH 4 /* Fixed Header length of CoAP message as bytes */
|
||||
#define COAP_HEADER_VERSION_MASK 0xC0
|
||||
#define COAP_HEADER_MSG_TYPE_MASK 0x30
|
||||
#define COAP_HEADER_TOKEN_LENGTH_MASK 0x0F
|
||||
#define COAP_HEADER_MSG_ID_MSB_SHIFT 8
|
||||
|
||||
/* CoAP Options defines */
|
||||
#define COAP_OPTIONS_OPTION_NUMBER_SHIFT 4
|
||||
|
||||
/* * * * * * * * * * * * * * */
|
||||
/* * * * ENUMERATIONS * * * */
|
||||
/* * * * * * * * * * * * * * */
|
||||
|
||||
/* * * * * * * * * * * * * */
|
||||
/* * * * STRUCTURES * * * */
|
||||
/* * * * * * * * * * * * * */
|
||||
|
||||
/**
|
||||
* \brief This structure is returned by sn_coap_exec() for sending
|
||||
*/
|
||||
typedef struct sn_nsdl_transmit_ {
|
||||
sn_nsdl_addr_s *dst_addr_ptr;
|
||||
|
||||
sn_nsdl_capab_e protocol;
|
||||
|
||||
uint16_t packet_len;
|
||||
uint8_t *packet_ptr;
|
||||
} sn_nsdl_transmit_s;
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* * * * EXTERNAL FUNCTION PROTOTYPES * * * */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * */
|
||||
extern int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version);
|
||||
|
||||
#endif /* SN_COAP_HEADER_INTERNAL_H_ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
231
lib/amb1_sdk/common/network/coap/include/sn_coap_protocol.h
Normal file
231
lib/amb1_sdk/common/network/coap/include/sn_coap_protocol.h
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 2011-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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file sn_coap_protocol.h
|
||||
*
|
||||
* \brief CoAP C-library User protocol interface header file
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef SN_COAP_PROTOCOL_H_
|
||||
#define SN_COAP_PROTOCOL_H_
|
||||
|
||||
/** @addtogroup coap COAP
|
||||
* @ingroup network
|
||||
* @brief mbed CoAP APIs and Ameba wrappers
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "sn_coap_header.h"
|
||||
|
||||
/**
|
||||
* \fn struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *), int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *));
|
||||
*
|
||||
* \brief Initializes CoAP Protocol part. When using libNsdl, sn_nsdl_init() calls this function.
|
||||
*
|
||||
* \param *used_malloc_func_ptr is function pointer for used memory allocation function.
|
||||
*
|
||||
* \param *used_free_func_ptr is function pointer for used memory free function.
|
||||
*
|
||||
* \param *used_tx_callback_ptr function callback pointer to tx function for sending coap messages
|
||||
*
|
||||
* \param *used_rx_callback_ptr used to return CoAP header struct with status COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED
|
||||
* when re-sendings exceeded. If set to NULL, no error message is returned.
|
||||
*
|
||||
* \return Pointer to handle when success\n
|
||||
* Null if failed
|
||||
*/
|
||||
|
||||
extern struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *),
|
||||
uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *),
|
||||
int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *));
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_protocol_destroy(struct coap_s *handle)
|
||||
*
|
||||
* \brief Frees all memory from CoAP protocol part
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
*
|
||||
* \return Return value is always 0
|
||||
*/
|
||||
extern int8_t sn_coap_protocol_destroy(struct coap_s *handle);
|
||||
|
||||
/**
|
||||
* \fn int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param)
|
||||
*
|
||||
* \brief Builds Packet data from given CoAP header structure to be sent
|
||||
*
|
||||
* \param *dst_addr_ptr is pointer to destination address where CoAP message
|
||||
* will be sent (CoAP builder needs that information for message resending purposes)
|
||||
*
|
||||
* \param *dst_packet_data_ptr is pointer to destination of built Packet data
|
||||
*
|
||||
* \param *src_coap_msg_ptr is pointer to source of built Packet data
|
||||
*
|
||||
* \param param void pointer that will be passed to tx/rx function callback when those are called.
|
||||
*
|
||||
* \note If message is blockwised, all payload is not sent at the same time
|
||||
*
|
||||
* \return Return value is byte count of built Packet data.\n
|
||||
* In failure cases:\n
|
||||
* -1 = Failure in CoAP header structure\n
|
||||
* -2 = Failure in given pointer (= NULL)\n
|
||||
* -3 = Failure in Reset message\n
|
||||
* -4 = Failure in Resending message store\n
|
||||
* If there is not enough memory (or User given limit exceeded) for storing
|
||||
* resending messages, situation is ignored.
|
||||
*/
|
||||
extern int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param);
|
||||
|
||||
/**
|
||||
* \fn sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *param)
|
||||
*
|
||||
* \brief Parses received CoAP message from given Packet data
|
||||
*
|
||||
* \param *src_addr_ptr is pointer to source address of received CoAP message
|
||||
* (CoAP parser needs that information for Message acknowledgement)
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
*
|
||||
* \param packet_data_len is length of given Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param *packet_data_ptr is pointer to source of Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param *param void pointer that will be passed to tx/rx function callback when those are called.
|
||||
*
|
||||
* \return Return value is pointer to parsed CoAP message structure. This structure includes also coap_status field.\n
|
||||
* In following failure cases NULL is returned:\n
|
||||
* -Given NULL pointer\n
|
||||
* -Failure in parsed header of non-confirmable message\n
|
||||
* -Out of memory (malloc() returns NULL)
|
||||
*/
|
||||
extern sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *param);
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time)
|
||||
*
|
||||
* \brief Sends CoAP messages from re-sending queue, if there is any.
|
||||
* Cleans also old messages from the duplication list and from block receiving list
|
||||
*
|
||||
* This function can be called e.g. once in a second but also more frequently.
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
*
|
||||
* \param current_time is System time in seconds. This time is
|
||||
* used for message re-sending timing and to identify old saved data.
|
||||
*
|
||||
* \return 0 = success\n
|
||||
* -1 = failed
|
||||
*/
|
||||
|
||||
extern int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time);
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size)
|
||||
*
|
||||
* \brief If block transfer is enabled, this function changes the block size.
|
||||
* \param handle Pointer to CoAP library handle
|
||||
* \param maximum size of CoAP payload. Valid sizes are 16, 32, 64, 128, 256, 512 and 1024 bytes
|
||||
* \return 0 = success\n
|
||||
* -1 = failure
|
||||
*/
|
||||
extern int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size);
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count)
|
||||
*
|
||||
* \brief If dublicate message detection is enabled, this function changes buffer size.
|
||||
* \param handle Pointer to CoAP library handle
|
||||
* \param message_count max number of messages saved for duplicate control
|
||||
* \return 0 = success\n
|
||||
* -1 = failure
|
||||
*/
|
||||
extern int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count);
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle, uint8_t resending_count, uint8_t resending_intervall)
|
||||
*
|
||||
* \brief If re-transmissions are enabled, this function changes resending count and interval.
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
* \param resending_count max number of resendings for message
|
||||
* \param resending_intervall message resending intervall in seconds
|
||||
* \return 0 = success\n
|
||||
* -1 = failure
|
||||
*/
|
||||
extern int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle,
|
||||
uint8_t resending_count, uint8_t resending_interval);
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle, uint8_t buffer_size_messages, uint16_t buffer_size_bytes)
|
||||
*
|
||||
* \brief If re-transmissions are enabled, this function changes message retransmission queue size.
|
||||
* Set size to '0' to disable feature. If both are set to '0', then re-sendings are disabled.
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
* \param buffer_size_messages queue size - maximum number of messages to be saved to queue
|
||||
* \param buffer_size_bytes queue size - maximum size of messages saved to queue
|
||||
* \return 0 = success\n
|
||||
* -1 = failure
|
||||
*/
|
||||
extern int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle,
|
||||
uint8_t buffer_size_messages, uint16_t buffer_size_bytes);
|
||||
|
||||
/**
|
||||
* \fn void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle)
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
*
|
||||
* \brief If re-transmissions are enabled, this function removes all messages from the retransmission queue.
|
||||
*/
|
||||
extern void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle);
|
||||
|
||||
/**
|
||||
* \fn sn_coap_protocol_block_remove(struct coap_s *handle, sn_nsdl_addr_s *source_address, uint16_t payload_length, void *payload)
|
||||
*
|
||||
* \brief Remove saved block data. Can be used to remove the data from RAM to enable storing it to other place.
|
||||
*
|
||||
* \param handle Pointer to CoAP library handle
|
||||
* \param source_address Addres from where the block has been received.
|
||||
* \param payload_length Length of the coap payload of the block.
|
||||
* \param payload Coap payload of the block.
|
||||
*
|
||||
*/
|
||||
extern void sn_coap_protocol_block_remove(struct coap_s *handle, sn_nsdl_addr_s *source_address, uint16_t payload_length, void *payload);
|
||||
|
||||
/**
|
||||
* \fn void sn_coap_protocol_delete_retransmission(struct coap_s *handle, uint16_t msg_id)
|
||||
*
|
||||
* \brief If re-transmissions are enabled, this function removes message from retransmission buffer.
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
* \param msg_id message ID to be removed
|
||||
* \return 0 = success\n
|
||||
* -1 = invalid parameter\n
|
||||
* -2 = message was not found
|
||||
*/
|
||||
extern int8_t sn_coap_protocol_delete_retransmission(struct coap_s *handle, uint16_t msg_id);
|
||||
|
||||
/*\@}*/
|
||||
|
||||
#endif /* SN_COAP_PROTOCOL_H_ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (c) 2011-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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file sn_coap_protocol_internal.h
|
||||
*
|
||||
* \brief Header file for CoAP Protocol part
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SN_COAP_PROTOCOL_INTERNAL_H_
|
||||
#define SN_COAP_PROTOCOL_INTERNAL_H_
|
||||
|
||||
#include "ns_list.h"
|
||||
#include "sn_coap_header_internal.h"
|
||||
#include "sn_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct sn_coap_hdr_;
|
||||
|
||||
/* * * * * * * * * * * */
|
||||
/* * * * DEFINES * * * */
|
||||
/* * * * * * * * * * * */
|
||||
|
||||
/* * For Message resending * */
|
||||
#define ENABLE_RESENDINGS 1 /**< Enable / Disable resending from library in building */
|
||||
|
||||
#define SN_COAP_RESENDING_MAX_COUNT 3 /**< Default number of re-sendings */
|
||||
|
||||
#ifdef YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_MSGS
|
||||
#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_MSGS
|
||||
#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_MSGS
|
||||
#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_MSGS
|
||||
#endif
|
||||
|
||||
#ifndef SN_COAP_RESENDING_QUEUE_SIZE_MSGS
|
||||
#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS 2 /**< Default re-sending queue size - defines how many messages can be stored. Setting this to 0 disables feature */
|
||||
#endif
|
||||
|
||||
#ifdef YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_BYTES
|
||||
#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_BYTES
|
||||
#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_BYTES
|
||||
#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_BYTES
|
||||
#endif
|
||||
|
||||
#ifndef SN_COAP_RESENDING_QUEUE_SIZE_BYTES
|
||||
#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES 0 /**< Default re-sending queue size - defines size of the re-sending buffer. Setting this to 0 disables feature */
|
||||
#endif
|
||||
|
||||
#define DEFAULT_RESPONSE_TIMEOUT 10 /**< Default re-sending timeout as seconds */
|
||||
|
||||
/* These parameters sets maximum values application can set with API */
|
||||
#define SN_COAP_MAX_ALLOWED_RESENDING_COUNT 6 /**< Maximum allowed count of re-sending */
|
||||
#define SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS 6 /**< Maximum allowed number of saved re-sending messages */
|
||||
#define SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES 512 /**< Maximum allowed size of re-sending buffer */
|
||||
#define SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT 40 /**< Maximum allowed re-sending timeout */
|
||||
|
||||
#define RESPONSE_RANDOM_FACTOR 1 /**< Resending random factor, value is specified in IETF CoAP specification */
|
||||
|
||||
/* * For Message duplication detecting * */
|
||||
|
||||
/* Init value for the maximum count of messages to be stored for duplication detection */
|
||||
/* Setting of this value to 0 will disable duplication check, also reduce use of ROM memory */
|
||||
|
||||
// Keep the old flag to maintain backward compatibility
|
||||
#ifndef SN_COAP_DUPLICATION_MAX_MSGS_COUNT
|
||||
#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT 0
|
||||
#endif
|
||||
|
||||
#ifdef YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT
|
||||
#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT
|
||||
#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_DUPLICATION_MAX_MSGS_COUNT
|
||||
#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT MBED_CONF_MBED_CLIENT_SN_COAP_DUPLICATION_MAX_MSGS_COUNT
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Maximum allowed number of saved messages for duplicate searching */
|
||||
#define SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT 6
|
||||
|
||||
/* Maximum time in seconds of messages to be stored for duplication detection */
|
||||
#define SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED 60 /* RESPONSE_TIMEOUT * RESPONSE_RANDOM_FACTOR * (2 ^ MAX_RETRANSMIT - 1) + the expected maximum round trip time */
|
||||
|
||||
/* * For Message blockwising * */
|
||||
|
||||
/* Init value for the maximum payload size to be sent and received at one blockwise message */
|
||||
/* Setting of this value to 0 will disable this feature, and also reduce use of ROM memory */
|
||||
/* Note: This define is common for both received and sent Blockwise messages */
|
||||
|
||||
#ifdef YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
|
||||
#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
|
||||
#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
|
||||
#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE MBED_CONF_MBED_CLIENT_SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
|
||||
#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE 0 /**< Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024 */
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED
|
||||
#define SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED 10 /**< Maximum time in seconds of data (messages and payload) to be stored for blockwising */
|
||||
#endif
|
||||
|
||||
#ifdef YOTTA_CFG_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE
|
||||
#define SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE YOTTA_CFG_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE
|
||||
#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_MAX_INCOMING_MESSAGE_SIZE
|
||||
#define SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE MBED_CONF_MBED_CLIENT_SN_COAP_MAX_INCOMING_MESSAGE_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE
|
||||
#define SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE UINT16_MAX
|
||||
#endif
|
||||
|
||||
/* * For Option handling * */
|
||||
#define COAP_OPTION_MAX_AGE_DEFAULT 60 /**< Default value of Max-Age if option not present */
|
||||
#define COAP_OPTION_URI_PORT_NONE (-1) /**< Internal value to represent no Uri-Port option */
|
||||
#define COAP_OPTION_BLOCK_NONE (-1) /**< Internal value to represent no Block1/2 option */
|
||||
|
||||
|
||||
#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */
|
||||
int8_t prepare_blockwise_message(struct coap_s *handle, struct sn_coap_hdr_ *coap_hdr_ptr);
|
||||
#endif
|
||||
|
||||
/* Structure which is stored to Linked list for message sending purposes */
|
||||
typedef struct coap_send_msg_ {
|
||||
uint8_t resending_counter; /* Tells how many times message is still tried to resend */
|
||||
uint32_t resending_time; /* Tells next resending time */
|
||||
|
||||
sn_nsdl_transmit_s *send_msg_ptr;
|
||||
|
||||
struct coap_s *coap; /* CoAP library handle */
|
||||
void *param; /* Extra parameter that will be passed to TX/RX callback functions */
|
||||
|
||||
ns_list_link_t link;
|
||||
} coap_send_msg_s;
|
||||
|
||||
typedef NS_LIST_HEAD(coap_send_msg_s, link) coap_send_msg_list_t;
|
||||
|
||||
/* Structure which is stored to Linked list for message duplication detection purposes */
|
||||
typedef struct coap_duplication_info_ {
|
||||
uint32_t timestamp; /* Tells when duplication information is stored to Linked list */
|
||||
|
||||
uint8_t addr_len;
|
||||
uint8_t *addr_ptr;
|
||||
uint16_t port;
|
||||
|
||||
uint16_t msg_id;
|
||||
|
||||
struct coap_s *coap; /* CoAP library handle */
|
||||
|
||||
ns_list_link_t link;
|
||||
} coap_duplication_info_s;
|
||||
|
||||
typedef NS_LIST_HEAD(coap_duplication_info_s, link) coap_duplication_info_list_t;
|
||||
|
||||
/* Structure which is stored to Linked list for blockwise messages sending purposes */
|
||||
typedef struct coap_blockwise_msg_ {
|
||||
uint32_t timestamp; /* Tells when Blockwise message is stored to Linked list */
|
||||
|
||||
sn_coap_hdr_s *coap_msg_ptr;
|
||||
struct coap_s *coap; /* CoAP library handle */
|
||||
|
||||
ns_list_link_t link;
|
||||
} coap_blockwise_msg_s;
|
||||
|
||||
typedef NS_LIST_HEAD(coap_blockwise_msg_s, link) coap_blockwise_msg_list_t;
|
||||
|
||||
/* Structure which is stored to Linked list for blockwise messages receiving purposes */
|
||||
typedef struct coap_blockwise_payload_ {
|
||||
uint32_t timestamp; /* Tells when Payload is stored to Linked list */
|
||||
|
||||
uint8_t addr_len;
|
||||
uint8_t *addr_ptr;
|
||||
uint16_t port;
|
||||
|
||||
uint16_t payload_len;
|
||||
uint8_t *payload_ptr;
|
||||
struct coap_s *coap; /* CoAP library handle */
|
||||
|
||||
ns_list_link_t link;
|
||||
} coap_blockwise_payload_s;
|
||||
|
||||
typedef NS_LIST_HEAD(coap_blockwise_payload_s, link) coap_blockwise_payload_list_t;
|
||||
|
||||
struct coap_s {
|
||||
void *(*sn_coap_protocol_malloc)(uint16_t);
|
||||
void (*sn_coap_protocol_free)(void *);
|
||||
|
||||
uint8_t (*sn_coap_tx_callback)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *);
|
||||
int8_t (*sn_coap_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *);
|
||||
|
||||
#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
|
||||
coap_send_msg_list_t linked_list_resent_msgs; /* Active resending messages are stored to this Linked list */
|
||||
uint16_t count_resent_msgs;
|
||||
#endif
|
||||
|
||||
#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */
|
||||
coap_duplication_info_list_t linked_list_duplication_msgs; /* Messages for duplicated messages detection is stored to this Linked list */
|
||||
uint16_t count_duplication_msgs;
|
||||
#endif
|
||||
|
||||
#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not used at all, this part of code will not be compiled */
|
||||
coap_blockwise_msg_list_t linked_list_blockwise_sent_msgs; /* Blockwise message to to be sent is stored to this Linked list */
|
||||
coap_blockwise_payload_list_t linked_list_blockwise_received_payloads; /* Blockwise payload to to be received is stored to this Linked list */
|
||||
#endif
|
||||
|
||||
uint32_t system_time; /* System time seconds */
|
||||
uint16_t sn_coap_block_data_size;
|
||||
uint8_t sn_coap_resending_queue_msgs;
|
||||
uint8_t sn_coap_resending_queue_bytes;
|
||||
uint8_t sn_coap_resending_count;
|
||||
uint8_t sn_coap_resending_intervall;
|
||||
uint8_t sn_coap_duplication_buffer_size;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SN_COAP_PROTOCOL_INTERNAL_H_ */
|
||||
|
||||
92
lib/amb1_sdk/common/network/coap/include/sn_config.h
Normal file
92
lib/amb1_sdk/common/network/coap/include/sn_config.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef SN_CONFIG_H
|
||||
#define SN_CONFIG_H
|
||||
|
||||
#include "sn_coap_ameba_port.h"
|
||||
|
||||
/**
|
||||
* \brief Configuration options (set of defines and values)
|
||||
*
|
||||
* This lists set of compile-time options that needs to be used to enable
|
||||
* or disable features selectively, and set the values for the mandatory
|
||||
* parameters.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def SN_COAP_DUPLICATION_MAX_MSGS_COUNT
|
||||
* \brief For Message duplication detection
|
||||
* Init value for the maximum count of messages to be stored for duplication detection
|
||||
* Setting of this value to 0 will disable duplication check, also reduce use of ROM memory
|
||||
* Default is set to 1.
|
||||
*/
|
||||
#undef SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* 1 */
|
||||
|
||||
/**
|
||||
* \def SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
|
||||
*
|
||||
* \brief For Message blockwising
|
||||
* Init value for the maximum payload size to be sent and received at one blockwise message
|
||||
* Setting of this value to 0 will disable this feature, and also reduce use of ROM memory
|
||||
* Note: This define is common for both received and sent Blockwise messages
|
||||
*/
|
||||
#undef SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* 0 */ // < Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024
|
||||
|
||||
/**
|
||||
* \def COAP_DISABLE_OBS_FEATURE
|
||||
*
|
||||
* \brief Disables CoAP 'obs' sending feature
|
||||
* as part of registration message, this might be
|
||||
* needed to be enabled for some strict LWM2M server implementation.
|
||||
* By default, this feature is disabled.
|
||||
*/
|
||||
#undef COAP_DISABLE_OBS_FEATURE
|
||||
|
||||
/**
|
||||
* \def SN_COAP_RESENDING_QUEUE_SIZE_MSGS
|
||||
*
|
||||
* \brief Sets the number of messages stored
|
||||
* in the resending queue. Default is 2
|
||||
*/
|
||||
#undef SN_COAP_RESENDING_QUEUE_SIZE_MSGS /* 2 */ // < Default re-sending queue size - defines how many messages can be stored. Setting this to 0 disables feature
|
||||
|
||||
/**
|
||||
* \def SN_COAP_RESENDING_QUEUE_SIZE_BYTES
|
||||
*
|
||||
* \brief Sets the size of the re-sending buffer.
|
||||
* Setting this to 0 disables this feature.
|
||||
* By default, this feature is disabled.
|
||||
*/
|
||||
#undef SN_COAP_RESENDING_QUEUE_SIZE_BYTES /* 0 */ // Default re-sending queue size - defines size of the re-sending buffer. Setting this to 0 disables feature
|
||||
|
||||
/**
|
||||
* \def SN_COAP_MAX_INCOMING_MESSAGE_SIZE
|
||||
*
|
||||
* \brief Sets the maximum size (in bytes) that
|
||||
* mbed Client will allow to be handled while
|
||||
* receiving big payload in blockwise mode.
|
||||
* Application can set this value based on their
|
||||
* available storage capability.
|
||||
* By default, maximum size is UINT16_MAX, 65535 bytes.
|
||||
*/
|
||||
#undef SN_COAP_MAX_INCOMING_MESSAGE_SIZE /* UINT16_MAX */
|
||||
|
||||
#ifdef MBED_CLIENT_USER_CONFIG_FILE
|
||||
#include MBED_CLIENT_USER_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#endif // SN_CONFIG_H
|
||||
368
lib/amb1_sdk/common/network/coap/sn_coap_ameba_port.c
Normal file
368
lib/amb1_sdk/common/network/coap/sn_coap_ameba_port.c
Normal file
@@ -0,0 +1,368 @@
|
||||
#include "sn_coap_ameba_port.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////ramdom function///////////////////////////////////////////
|
||||
uint16_t randLIB_get_16bit(){
|
||||
|
||||
unsigned char rnd[2];
|
||||
rtw_get_random_bytes(rnd,2);
|
||||
|
||||
return ( ((uint16_t)rnd[0] << 8) | ((uint16_t)rnd[1]) );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////memory allocation///////////////////////////////////////////
|
||||
|
||||
void* coap_malloc(uint16_t size) {
|
||||
return pvPortMalloc(size);
|
||||
}
|
||||
|
||||
void coap_free(void* addr) {
|
||||
vPortFree(addr);
|
||||
}
|
||||
|
||||
void* coap_calloc(uint32_t size){
|
||||
|
||||
if(size == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *p = pvPortMalloc(size);
|
||||
|
||||
if(p){
|
||||
memset(p,0,size);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////init CoAP protocol///////////////////////////////////////////
|
||||
struct coap_s * coap_protocol_init( uint8_t (*coap_tx_callback)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *),
|
||||
int8_t (*coap_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *)){
|
||||
return sn_coap_protocol_init(&coap_malloc, &coap_free, coap_tx_callback, coap_rx_callback);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////send and receive///////////////////////////////////////////
|
||||
|
||||
int coap_sock_open(){
|
||||
|
||||
int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
#if COAP_DBG_EN
|
||||
if(socket_fd < 0){
|
||||
tr_debug("ERROR: open socket");
|
||||
}
|
||||
#endif
|
||||
|
||||
return socket_fd;
|
||||
}
|
||||
|
||||
int coap_sock_close(int socket_fd){
|
||||
int r = close(socket_fd);
|
||||
|
||||
#if COAP_DBG_EN
|
||||
if (r < 0)
|
||||
{
|
||||
tr_debug("ERROR: close socket");
|
||||
}
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int coap_send(char *to_address, uint16_t port, int socket, sn_coap_hdr_s *coap_msg_hdr){
|
||||
|
||||
// Calculate the CoAP message size, allocate the memory and build the message
|
||||
|
||||
uint16_t message_len = sn_coap_builder_calc_needed_packet_data_size(coap_msg_hdr);
|
||||
|
||||
uint8_t* message_ptr = (uint8_t*)coap_malloc(message_len);
|
||||
|
||||
sn_coap_builder(message_ptr, coap_msg_hdr);
|
||||
|
||||
// Send CoAP message
|
||||
|
||||
struct sockaddr_in internet_address;
|
||||
|
||||
memset((char *) &internet_address,0,sizeof(internet_address));
|
||||
|
||||
internet_address.sin_family = AF_INET;
|
||||
internet_address.sin_port = htons(port);
|
||||
//internet_address.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
struct hostent *host_entry;
|
||||
|
||||
host_entry = gethostbyname(to_address);
|
||||
|
||||
memcpy((void *) &internet_address.sin_addr, (void *) host_entry->h_addr, host_entry->h_length);
|
||||
|
||||
int n = sendto(socket, message_ptr, message_len, 0, (struct sockaddr *)&internet_address, sizeof(internet_address));
|
||||
|
||||
#if COAP_DBG_EN
|
||||
if(n<0){
|
||||
tr_debug("ERROR: send message");
|
||||
}else{
|
||||
tr_debug("Send '%s' %d bytes",to_address,n);
|
||||
}
|
||||
#endif
|
||||
|
||||
coap_free(message_ptr);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int coap_recv(int socket, struct sockaddr_in *from_address, void *buf, uint32_t buf_size){
|
||||
|
||||
#if COAP_DBG_EN
|
||||
if(buf == NULL){
|
||||
tr_debug("ERROR: receive buffer == NULL");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t addr_len = sizeof(struct sockaddr_in);
|
||||
|
||||
return recvfrom(socket, buf, buf_size, 0, (struct sockaddr *) from_address, &addr_len);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////print header///////////////////////////////////////////
|
||||
void coap_print_hdr(sn_coap_hdr_s* parsed_hdr){
|
||||
|
||||
char code[] = "0.00";
|
||||
int cat = (parsed_hdr->msg_code & 0xe0) >> 5;
|
||||
int dd = parsed_hdr->msg_code & 0x1f;
|
||||
sprintf(code, "%d.%.2x", cat, dd);
|
||||
|
||||
printf("\ttoken_len: %d\n", parsed_hdr->token_len);
|
||||
printf("\ttoken_ptr: %s\n", parsed_hdr->token_ptr);
|
||||
|
||||
printf("\tcoap_status: %d ", parsed_hdr->coap_status);
|
||||
switch(parsed_hdr->coap_status){
|
||||
|
||||
case COAP_STATUS_OK:
|
||||
printf("COAP_STATUS_OK\n");
|
||||
break;
|
||||
|
||||
case COAP_STATUS_PARSER_ERROR_IN_HEADER:
|
||||
printf("COAP_STATUS_PARSER_ERROR_IN_HEADER\n");
|
||||
break;
|
||||
|
||||
case COAP_STATUS_PARSER_DUPLICATED_MSG:
|
||||
printf("COAP_STATUS_PARSER_DUPLICATED_MSG\n");
|
||||
break;
|
||||
|
||||
case COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING:
|
||||
printf("COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING\n");
|
||||
break;
|
||||
|
||||
case COAP_STATUS_PARSER_BLOCKWISE_ACK:
|
||||
printf("COAP_STATUS_PARSER_BLOCKWISE_ACK\n");
|
||||
break;
|
||||
|
||||
case COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED:
|
||||
printf("COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED\n");
|
||||
break;
|
||||
|
||||
case COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED:
|
||||
printf("COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED\n");
|
||||
break;
|
||||
|
||||
case COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED:
|
||||
printf("COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\tmsg_code: %s ", code);
|
||||
switch(parsed_hdr->msg_code){
|
||||
|
||||
case COAP_MSG_CODE_EMPTY:
|
||||
printf("COAP_MSG_CODE_EMPTY\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_REQUEST_GET:
|
||||
printf("COAP_MSG_CODE_REQUEST_GET\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_REQUEST_POST:
|
||||
printf("COAP_MSG_CODE_REQUEST_POST\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_REQUEST_PUT:
|
||||
printf("COAP_MSG_CODE_REQUEST_PUT\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_REQUEST_DELETE:
|
||||
printf("COAP_MSG_CODE_REQUEST_DELETE\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_CREATED:
|
||||
printf("COAP_MSG_CODE_RESPONSE_CREATED\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_DELETED:
|
||||
printf("COAP_MSG_CODE_RESPONSE_DELETED\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_VALID:
|
||||
printf("COAP_MSG_CODE_RESPONSE_VALID\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_CHANGED:
|
||||
printf("COAP_MSG_CODE_RESPONSE_CHANGED\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_CONTENT:
|
||||
printf("COAP_MSG_CODE_RESPONSE_CONTENT\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_CONTINUE:
|
||||
printf("COAP_MSG_CODE_RESPONSE_CONTINUE\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_BAD_REQUEST:
|
||||
printf("COAP_MSG_CODE_RESPONSE_BAD_REQUEST\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED:
|
||||
printf("COAP_MSG_CODE_RESPONSE_UNAUTHORIZED\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_BAD_OPTION:
|
||||
printf("COAP_MSG_CODE_RESPONSE_BAD_OPTION\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_FORBIDDEN:
|
||||
printf("COAP_MSG_CODE_RESPONSE_FORBIDDEN\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_NOT_FOUND:
|
||||
printf("COAP_MSG_CODE_RESPONSE_NOT_FOUND\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED:
|
||||
printf("COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE:
|
||||
printf("COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE:
|
||||
printf("COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED:
|
||||
printf("COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE:
|
||||
printf("COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT:
|
||||
printf("COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR:
|
||||
printf("COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED:
|
||||
printf("COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_BAD_GATEWAY:
|
||||
printf("COAP_MSG_CODE_RESPONSE_BAD_GATEWAY\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE:
|
||||
printf("COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT:
|
||||
printf("COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED:
|
||||
printf("COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\tmsg_type: %.2x ", parsed_hdr->msg_type);
|
||||
switch(parsed_hdr->msg_type){
|
||||
|
||||
case COAP_MSG_TYPE_CONFIRMABLE:
|
||||
printf("COAP_MSG_TYPE_CONFIRMABLE\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_TYPE_NON_CONFIRMABLE:
|
||||
printf("COAP_MSG_TYPE_NON_CONFIRMABLE\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_TYPE_ACKNOWLEDGEMENT:
|
||||
printf("COAP_MSG_TYPE_ACKNOWLEDGEMENT\n");
|
||||
break;
|
||||
|
||||
case COAP_MSG_TYPE_RESET:
|
||||
printf("COAP_MSG_TYPE_RESET\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
printf("\tcontent_format: %d ", parsed_hdr->content_format);
|
||||
switch(parsed_hdr->content_format){
|
||||
case COAP_CT_NONE:
|
||||
printf("COAP_CT_NONE\n");
|
||||
break;
|
||||
|
||||
case COAP_CT_TEXT_PLAIN:
|
||||
printf("COAP_CT_TEXT_PLAIN\n");
|
||||
break;
|
||||
|
||||
case COAP_CT_LINK_FORMAT:
|
||||
printf("COAP_CT_LINK_FORMAT\n");
|
||||
break;
|
||||
|
||||
case COAP_CT_XML:
|
||||
printf("COAP_CT_XML\n");
|
||||
break;
|
||||
|
||||
case COAP_CT_OCTET_STREAM:
|
||||
printf("COAP_CT_OCTET_STREAM\n");
|
||||
break;
|
||||
|
||||
case COAP_CT_EXI:
|
||||
printf("COAP_CT_EXI\n");
|
||||
break;
|
||||
|
||||
case COAP_CT_JSON:
|
||||
printf("COAP_CT_JSON\n");
|
||||
break;
|
||||
|
||||
case COAP_CT__MAX:
|
||||
printf("COAP_CT__MAX\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\tmsg_id: %d\n", parsed_hdr->msg_id);
|
||||
|
||||
printf("\turi_path_len: %d\n", parsed_hdr->uri_path_len);
|
||||
printf("\turi_path_ptr: %s\n", parsed_hdr->uri_path_ptr);
|
||||
|
||||
printf("\tpayload_len: %d\n", parsed_hdr->payload_len);
|
||||
printf("\tpayload_ptr: %s\n", parsed_hdr->payload_ptr);
|
||||
|
||||
//printf("\toptions_list_ptr: %p\n", parsed_hdr->options_list_ptr);
|
||||
}
|
||||
1069
lib/amb1_sdk/common/network/coap/sn_coap_builder.c
Normal file
1069
lib/amb1_sdk/common/network/coap/sn_coap_builder.c
Normal file
File diff suppressed because it is too large
Load Diff
99
lib/amb1_sdk/common/network/coap/sn_coap_header_check.c
Normal file
99
lib/amb1_sdk/common/network/coap/sn_coap_header_check.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2011-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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file sn_coap_header_check.c
|
||||
*
|
||||
* \brief CoAP Header validity checker
|
||||
*
|
||||
* Functionality: Checks validity of CoAP Header
|
||||
*
|
||||
*/
|
||||
|
||||
/* * * * INCLUDE FILES * * * */
|
||||
#include "ns_types.h"
|
||||
#include "sn_coap_header.h"
|
||||
#include "sn_coap_protocol.h"
|
||||
#include "sn_coap_header_internal.h"
|
||||
#include "sn_coap_protocol_internal.h"
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version)
|
||||
*
|
||||
* \brief Checks validity of given Header
|
||||
*
|
||||
* \param *src_coap_msg_ptr is source for building Packet data
|
||||
* \param coap_version is version of used CoAP specification
|
||||
*
|
||||
* \return Return value is status of validity check. In ok cases 0 and in
|
||||
* failure cases -1
|
||||
*/
|
||||
int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version)
|
||||
{
|
||||
/* * Check validity of CoAP Version * */
|
||||
if (coap_version != COAP_VERSION_1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* * Check validity of Message type * */
|
||||
switch (src_coap_msg_ptr->msg_type) {
|
||||
case COAP_MSG_TYPE_CONFIRMABLE:
|
||||
case COAP_MSG_TYPE_NON_CONFIRMABLE:
|
||||
case COAP_MSG_TYPE_ACKNOWLEDGEMENT:
|
||||
case COAP_MSG_TYPE_RESET:
|
||||
break; /* Ok cases */
|
||||
default:
|
||||
return -1; /* Failed case */
|
||||
}
|
||||
|
||||
/* * Check validity of Message code * */
|
||||
switch (src_coap_msg_ptr->msg_code) {
|
||||
case COAP_MSG_CODE_EMPTY:
|
||||
case COAP_MSG_CODE_REQUEST_GET:
|
||||
case COAP_MSG_CODE_REQUEST_POST:
|
||||
case COAP_MSG_CODE_REQUEST_PUT:
|
||||
case COAP_MSG_CODE_REQUEST_DELETE:
|
||||
case COAP_MSG_CODE_RESPONSE_CREATED:
|
||||
case COAP_MSG_CODE_RESPONSE_DELETED:
|
||||
case COAP_MSG_CODE_RESPONSE_VALID:
|
||||
case COAP_MSG_CODE_RESPONSE_CHANGED:
|
||||
case COAP_MSG_CODE_RESPONSE_CONTENT:
|
||||
case COAP_MSG_CODE_RESPONSE_BAD_REQUEST:
|
||||
case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED:
|
||||
case COAP_MSG_CODE_RESPONSE_BAD_OPTION:
|
||||
case COAP_MSG_CODE_RESPONSE_FORBIDDEN:
|
||||
case COAP_MSG_CODE_RESPONSE_NOT_FOUND:
|
||||
case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED:
|
||||
case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE:
|
||||
case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE:
|
||||
case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED:
|
||||
case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE:
|
||||
case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT:
|
||||
case COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR:
|
||||
case COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED:
|
||||
case COAP_MSG_CODE_RESPONSE_BAD_GATEWAY:
|
||||
case COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE:
|
||||
case COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT:
|
||||
case COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED:
|
||||
case COAP_MSG_CODE_RESPONSE_CONTINUE:
|
||||
break; /* Ok cases */
|
||||
default:
|
||||
return -1; /* Failed case */
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
762
lib/amb1_sdk/common/network/coap/sn_coap_parser.c
Normal file
762
lib/amb1_sdk/common/network/coap/sn_coap_parser.c
Normal file
@@ -0,0 +1,762 @@
|
||||
/*
|
||||
* Copyright (c) 2011-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.
|
||||
*/
|
||||
|
||||
/**
|
||||
*\file sn_coap_parser.c
|
||||
*
|
||||
* \brief CoAP Header parser
|
||||
*
|
||||
* Functionality: Parses CoAP Header
|
||||
*
|
||||
*/
|
||||
|
||||
/* * * * * * * * * * * * * * */
|
||||
/* * * * INCLUDE FILES * * * */
|
||||
/* * * * * * * * * * * * * * */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* For memset() and memcpy() */
|
||||
|
||||
#include "ns_types.h"
|
||||
#include "sn_coap_header.h"
|
||||
#include "sn_coap_protocol.h"
|
||||
#include "sn_coap_header_internal.h"
|
||||
#include "sn_coap_protocol_internal.h"
|
||||
/* * * * * * * * * * * * * * * * * * * * */
|
||||
/* * * * LOCAL FUNCTION PROTOTYPES * * * */
|
||||
/* * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr);
|
||||
static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len);
|
||||
static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len);
|
||||
static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len);
|
||||
static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr);
|
||||
|
||||
sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr)
|
||||
{
|
||||
/* * * * Check given pointer * * * */
|
||||
if (coap_msg_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX not technically legal to memset pointers to 0 */
|
||||
memset(coap_msg_ptr, 0x00, sizeof(sn_coap_hdr_s));
|
||||
|
||||
coap_msg_ptr->content_format = COAP_CT_NONE;
|
||||
|
||||
return coap_msg_ptr;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle)
|
||||
{
|
||||
sn_coap_hdr_s *returned_coap_msg_ptr;
|
||||
|
||||
/* * * * Check given pointer * * * */
|
||||
if (handle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* * * * Allocate memory for returned CoAP message and initialize allocated memory with with default values * * * */
|
||||
returned_coap_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_hdr_s));
|
||||
|
||||
return sn_coap_parser_init_message(returned_coap_msg_ptr);
|
||||
}
|
||||
|
||||
sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr)
|
||||
{
|
||||
/* * * * Check given pointers * * * */
|
||||
if (handle == NULL || coap_msg_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* * * * If the message already has options, return them * * * */
|
||||
if (coap_msg_ptr->options_list_ptr) {
|
||||
return coap_msg_ptr->options_list_ptr;
|
||||
}
|
||||
|
||||
/* * * * Allocate memory for options and initialize allocated memory with with default values * * * */
|
||||
coap_msg_ptr->options_list_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_options_list_s));
|
||||
|
||||
if (coap_msg_ptr->options_list_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX not technically legal to memset pointers to 0 */
|
||||
memset(coap_msg_ptr->options_list_ptr, 0x00, sizeof(sn_coap_options_list_s));
|
||||
|
||||
coap_msg_ptr->options_list_ptr->max_age = COAP_OPTION_MAX_AGE_DEFAULT;
|
||||
coap_msg_ptr->options_list_ptr->uri_port = COAP_OPTION_URI_PORT_NONE;
|
||||
coap_msg_ptr->options_list_ptr->observe = COAP_OBSERVE_NONE;
|
||||
coap_msg_ptr->options_list_ptr->accept = COAP_CT_NONE;
|
||||
coap_msg_ptr->options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
|
||||
coap_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
|
||||
|
||||
return coap_msg_ptr->options_list_ptr;
|
||||
}
|
||||
|
||||
sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr)
|
||||
{
|
||||
uint8_t *data_temp_ptr = packet_data_ptr;
|
||||
sn_coap_hdr_s *parsed_and_returned_coap_msg_ptr = NULL;
|
||||
|
||||
/* * * * Check given pointer * * * */
|
||||
if (packet_data_ptr == NULL || packet_data_len < 4 || handle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* * * * Allocate and initialize CoAP message * * * */
|
||||
parsed_and_returned_coap_msg_ptr = sn_coap_parser_alloc_message(handle);
|
||||
|
||||
if (parsed_and_returned_coap_msg_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* * * * Header parsing, move pointer over the header... * * * */
|
||||
sn_coap_parser_header_parse(&data_temp_ptr, parsed_and_returned_coap_msg_ptr, coap_version_ptr);
|
||||
|
||||
/* * * * Options parsing, move pointer over the options... * * * */
|
||||
if (sn_coap_parser_options_parse(handle, &data_temp_ptr, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len) != 0) {
|
||||
parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
|
||||
return parsed_and_returned_coap_msg_ptr;
|
||||
}
|
||||
|
||||
/* * * * Payload parsing * * * */
|
||||
if (sn_coap_parser_payload_parse(packet_data_len, packet_data_ptr, &data_temp_ptr, parsed_and_returned_coap_msg_ptr) == -1) {
|
||||
parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
|
||||
return parsed_and_returned_coap_msg_ptr;
|
||||
}
|
||||
|
||||
/* * * * Return parsed CoAP message * * * * */
|
||||
return parsed_and_returned_coap_msg_ptr;
|
||||
}
|
||||
|
||||
void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr != NULL) {
|
||||
if (freed_coap_msg_ptr->uri_path_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->uri_path_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->token_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->token_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr != NULL) {
|
||||
if (freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->etag_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_host_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_path_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_query_ptr);
|
||||
}
|
||||
|
||||
if (freed_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_query_ptr);
|
||||
}
|
||||
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr);
|
||||
}
|
||||
|
||||
handle->sn_coap_protocol_free(freed_coap_msg_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr)
|
||||
*
|
||||
* \brief Parses CoAP message's Header part from given Packet data
|
||||
*
|
||||
* \param **packet_data_ptr is source for Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param *dst_coap_msg_ptr is destination for parsed CoAP message
|
||||
*
|
||||
* \param *coap_version_ptr is destination for parsed CoAP specification version
|
||||
*/
|
||||
static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr)
|
||||
{
|
||||
/* Parse CoAP Version and message type*/
|
||||
*coap_version_ptr = (coap_version_e)(**packet_data_pptr & COAP_HEADER_VERSION_MASK);
|
||||
dst_coap_msg_ptr->msg_type = (sn_coap_msg_type_e)(**packet_data_pptr & COAP_HEADER_MSG_TYPE_MASK);
|
||||
(*packet_data_pptr) += 1;
|
||||
|
||||
/* Parse Message code */
|
||||
dst_coap_msg_ptr->msg_code = (sn_coap_msg_code_e) **packet_data_pptr;
|
||||
(*packet_data_pptr) += 1;
|
||||
|
||||
/* Parse Message ID */
|
||||
dst_coap_msg_ptr->msg_id = *(*packet_data_pptr + 1);
|
||||
dst_coap_msg_ptr->msg_id += **packet_data_pptr << COAP_HEADER_MSG_ID_MSB_SHIFT;
|
||||
(*packet_data_pptr) += 2;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Parses a variable-length uint value from an option
|
||||
*
|
||||
* \param **packet_data_pptr is source of option data to be parsed
|
||||
* \param option_len is length of option data (will be 0-4)
|
||||
*
|
||||
* \return Return value is value of uint
|
||||
*/
|
||||
static uint32_t sn_coap_parser_options_parse_uint(uint8_t **packet_data_pptr, uint8_t option_len)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
while (option_len--) {
|
||||
value <<= 8;
|
||||
value |= *(*packet_data_pptr)++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static uint8_t sn_coap_parser_options_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
|
||||
*
|
||||
* \brief Parses CoAP message's Options part from given Packet data
|
||||
*
|
||||
* \param **packet_data_pptr is source of Packet data to be parsed to CoAP message
|
||||
* \param *dst_coap_msg_ptr is destination for parsed CoAP message
|
||||
*
|
||||
* \return Return value is 0 in ok case and -1 in failure case
|
||||
*/
|
||||
static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len)
|
||||
{
|
||||
uint8_t previous_option_number = 0;
|
||||
uint8_t i = 0;
|
||||
int8_t ret_status = 0;
|
||||
uint16_t message_left = 0;
|
||||
|
||||
/* Parse token, if exists */
|
||||
dst_coap_msg_ptr->token_len = *packet_data_start_ptr & COAP_HEADER_TOKEN_LENGTH_MASK;
|
||||
|
||||
if (dst_coap_msg_ptr->token_len) {
|
||||
if ((dst_coap_msg_ptr->token_len > 8) || dst_coap_msg_ptr->token_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dst_coap_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(dst_coap_msg_ptr->token_len);
|
||||
|
||||
if (dst_coap_msg_ptr->token_ptr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(dst_coap_msg_ptr->token_ptr, *packet_data_pptr, dst_coap_msg_ptr->token_len);
|
||||
(*packet_data_pptr) += dst_coap_msg_ptr->token_len;
|
||||
}
|
||||
|
||||
message_left = packet_len - ((*packet_data_pptr) - packet_data_start_ptr);
|
||||
|
||||
/* Loop all Options */
|
||||
while (message_left && (**packet_data_pptr != 0xff)) {
|
||||
|
||||
/* Get option length WITHOUT extensions */
|
||||
uint16_t option_len = (**packet_data_pptr & 0x0F);
|
||||
|
||||
/* Option number length 15 is reserved for the future use - ERROR */
|
||||
if (option_len == 15) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Resolve option delta */
|
||||
uint16_t option_number = (**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT);
|
||||
|
||||
if (option_number == 13) {
|
||||
option_number = *(*packet_data_pptr + 1) + 13;
|
||||
(*packet_data_pptr)++;
|
||||
} else if (option_number == 14) {
|
||||
option_number = *(*packet_data_pptr + 2);
|
||||
option_number += (*(*packet_data_pptr + 1) << 8) + 269;
|
||||
(*packet_data_pptr) += 2;
|
||||
}
|
||||
/* Option number 15 reserved for payload marker. This is handled as a error! */
|
||||
else if (option_number == 15) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add previous option to option delta and get option number */
|
||||
option_number += previous_option_number;
|
||||
|
||||
/* Add possible option length extension to resolve full length of the option */
|
||||
if (option_len == 13) {
|
||||
option_len = *(*packet_data_pptr + 1) + 13;
|
||||
(*packet_data_pptr)++;
|
||||
} else if (option_len == 14) {
|
||||
option_len = *(*packet_data_pptr + 2);
|
||||
option_len += (*(*packet_data_pptr + 1) << 8) + 269;
|
||||
(*packet_data_pptr) += 2;
|
||||
}
|
||||
|
||||
message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr);
|
||||
|
||||
/* * * Parse option itself * * */
|
||||
/* Some options are handled independently in own functions */
|
||||
previous_option_number = option_number;
|
||||
/* Allocate options_list_ptr if needed */
|
||||
switch (option_number) {
|
||||
case COAP_OPTION_MAX_AGE:
|
||||
case COAP_OPTION_PROXY_URI:
|
||||
case COAP_OPTION_ETAG:
|
||||
case COAP_OPTION_URI_HOST:
|
||||
case COAP_OPTION_LOCATION_PATH:
|
||||
case COAP_OPTION_URI_PORT:
|
||||
case COAP_OPTION_LOCATION_QUERY:
|
||||
case COAP_OPTION_OBSERVE:
|
||||
case COAP_OPTION_URI_QUERY:
|
||||
case COAP_OPTION_BLOCK2:
|
||||
case COAP_OPTION_BLOCK1:
|
||||
case COAP_OPTION_ACCEPT:
|
||||
case COAP_OPTION_SIZE1:
|
||||
case COAP_OPTION_SIZE2:
|
||||
if (sn_coap_parser_alloc_options(handle, dst_coap_msg_ptr) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Parse option */
|
||||
switch (option_number) {
|
||||
case COAP_OPTION_CONTENT_FORMAT:
|
||||
if ((option_len > 2) || (dst_coap_msg_ptr->content_format != COAP_CT_NONE)) {
|
||||
return -1;
|
||||
}
|
||||
(*packet_data_pptr)++;
|
||||
dst_coap_msg_ptr->content_format = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
break;
|
||||
|
||||
case COAP_OPTION_MAX_AGE:
|
||||
if (option_len > 4) {
|
||||
return -1;
|
||||
}
|
||||
(*packet_data_pptr)++;
|
||||
dst_coap_msg_ptr->options_list_ptr->max_age = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
break;
|
||||
|
||||
case COAP_OPTION_PROXY_URI:
|
||||
if ((option_len > 1034) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr) {
|
||||
return -1;
|
||||
}
|
||||
dst_coap_msg_ptr->options_list_ptr->proxy_uri_len = option_len;
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(option_len);
|
||||
|
||||
if (dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, *packet_data_pptr, option_len);
|
||||
(*packet_data_pptr) += option_len;
|
||||
|
||||
break;
|
||||
|
||||
case COAP_OPTION_ETAG:
|
||||
/* This is managed independently because User gives this option in one character table */
|
||||
|
||||
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr,
|
||||
message_left,
|
||||
&dst_coap_msg_ptr->options_list_ptr->etag_ptr,
|
||||
(uint16_t *)&dst_coap_msg_ptr->options_list_ptr->etag_len,
|
||||
COAP_OPTION_ETAG, option_len);
|
||||
if (ret_status >= 0) {
|
||||
i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case COAP_OPTION_URI_HOST:
|
||||
if ((option_len > 255) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->uri_host_ptr) {
|
||||
return -1;
|
||||
}
|
||||
dst_coap_msg_ptr->options_list_ptr->uri_host_len = option_len;
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(option_len);
|
||||
|
||||
if (dst_coap_msg_ptr->options_list_ptr->uri_host_ptr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(dst_coap_msg_ptr->options_list_ptr->uri_host_ptr, *packet_data_pptr, option_len);
|
||||
(*packet_data_pptr) += option_len;
|
||||
|
||||
break;
|
||||
|
||||
case COAP_OPTION_LOCATION_PATH:
|
||||
if (dst_coap_msg_ptr->options_list_ptr->location_path_ptr) {
|
||||
return -1;
|
||||
}
|
||||
/* This is managed independently because User gives this option in one character table */
|
||||
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
|
||||
&dst_coap_msg_ptr->options_list_ptr->location_path_ptr, &dst_coap_msg_ptr->options_list_ptr->location_path_len,
|
||||
COAP_OPTION_LOCATION_PATH, option_len);
|
||||
if (ret_status >= 0) {
|
||||
i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case COAP_OPTION_URI_PORT:
|
||||
if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
|
||||
return -1;
|
||||
}
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->uri_port = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
break;
|
||||
|
||||
case COAP_OPTION_LOCATION_QUERY:
|
||||
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
|
||||
&dst_coap_msg_ptr->options_list_ptr->location_query_ptr, &dst_coap_msg_ptr->options_list_ptr->location_query_len,
|
||||
COAP_OPTION_LOCATION_QUERY, option_len);
|
||||
if (ret_status >= 0) {
|
||||
i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case COAP_OPTION_URI_PATH:
|
||||
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
|
||||
&dst_coap_msg_ptr->uri_path_ptr, &dst_coap_msg_ptr->uri_path_len,
|
||||
COAP_OPTION_URI_PATH, option_len);
|
||||
if (ret_status >= 0) {
|
||||
i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case COAP_OPTION_OBSERVE:
|
||||
if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->observe = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
|
||||
break;
|
||||
|
||||
case COAP_OPTION_URI_QUERY:
|
||||
ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
|
||||
&dst_coap_msg_ptr->options_list_ptr->uri_query_ptr, &dst_coap_msg_ptr->options_list_ptr->uri_query_len,
|
||||
COAP_OPTION_URI_QUERY, option_len);
|
||||
if (ret_status >= 0) {
|
||||
i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case COAP_OPTION_BLOCK2:
|
||||
if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
|
||||
return -1;
|
||||
}
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->block2 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
|
||||
break;
|
||||
|
||||
case COAP_OPTION_BLOCK1:
|
||||
if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
|
||||
return -1;
|
||||
}
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->block1 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
|
||||
break;
|
||||
|
||||
case COAP_OPTION_ACCEPT:
|
||||
if ((option_len > 2) || (dst_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
dst_coap_msg_ptr->options_list_ptr->accept = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
break;
|
||||
|
||||
case COAP_OPTION_SIZE1:
|
||||
if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size1) {
|
||||
return -1;
|
||||
}
|
||||
dst_coap_msg_ptr->options_list_ptr->use_size1 = true;
|
||||
(*packet_data_pptr)++;
|
||||
dst_coap_msg_ptr->options_list_ptr->size1 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
break;
|
||||
|
||||
case COAP_OPTION_SIZE2:
|
||||
if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size2) {
|
||||
return -1;
|
||||
}
|
||||
dst_coap_msg_ptr->options_list_ptr->use_size2 = true;
|
||||
(*packet_data_pptr)++;
|
||||
dst_coap_msg_ptr->options_list_ptr->size2 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check for overflow */
|
||||
if ((*packet_data_pptr - packet_data_start_ptr) > packet_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \fn static int8_t sn_coap_parser_options_parse_multiple_options(uint8_t **packet_data_pptr, uint8_t options_count_left, uint8_t *previous_option_number_ptr, uint8_t **dst_pptr,
|
||||
* uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
|
||||
*
|
||||
* \brief Parses CoAP message's Uri-query options
|
||||
*
|
||||
* \param **packet_data_pptr is source for Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param *dst_coap_msg_ptr is destination for parsed CoAP message
|
||||
*
|
||||
* \param options_count_left tells how many options are unhandled in Packet data
|
||||
*
|
||||
* \param *previous_option_number_ptr is pointer to used and returned previous Option number
|
||||
*
|
||||
* \return Return value is count of Uri-query optios parsed. In failure case -1 is returned.
|
||||
*/
|
||||
static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
|
||||
{
|
||||
int16_t uri_query_needed_heap = sn_coap_parser_options_count_needed_memory_multiple_option(*packet_data_pptr, packet_left_len, option, option_number_len);
|
||||
uint8_t *temp_parsed_uri_query_ptr = NULL;
|
||||
uint8_t returned_option_counter = 0;
|
||||
|
||||
if (uri_query_needed_heap == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uri_query_needed_heap) {
|
||||
*dst_pptr = (uint8_t *) handle->sn_coap_protocol_malloc(uri_query_needed_heap);
|
||||
|
||||
if (*dst_pptr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*dst_len_ptr = uri_query_needed_heap;
|
||||
|
||||
temp_parsed_uri_query_ptr = *dst_pptr;
|
||||
|
||||
/* Loop all Uri-Query options */
|
||||
while ((temp_parsed_uri_query_ptr - *dst_pptr) < uri_query_needed_heap) {
|
||||
/* Check if this is first Uri-Query option */
|
||||
if (returned_option_counter > 0) {
|
||||
/* Uri-Query is modified to following format: temp1'\0'temp2'\0'temp3 i.e. */
|
||||
/* Uri-Path is modified to following format: temp1\temp2\temp3 i.e. */
|
||||
if (option == COAP_OPTION_URI_QUERY || option == COAP_OPTION_LOCATION_QUERY || option == COAP_OPTION_ETAG || option == COAP_OPTION_ACCEPT) {
|
||||
memset(temp_parsed_uri_query_ptr, '&', 1);
|
||||
} else if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
|
||||
memset(temp_parsed_uri_query_ptr, '/', 1);
|
||||
}
|
||||
|
||||
temp_parsed_uri_query_ptr++;
|
||||
}
|
||||
|
||||
returned_option_counter++;
|
||||
|
||||
(*packet_data_pptr)++;
|
||||
|
||||
if (((temp_parsed_uri_query_ptr - *dst_pptr) + option_number_len) > uri_query_needed_heap) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(temp_parsed_uri_query_ptr, *packet_data_pptr, option_number_len);
|
||||
|
||||
(*packet_data_pptr) += option_number_len;
|
||||
temp_parsed_uri_query_ptr += option_number_len;
|
||||
|
||||
if ((temp_parsed_uri_query_ptr - *dst_pptr) >= uri_query_needed_heap || ((**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0)) {
|
||||
return returned_option_counter;
|
||||
}
|
||||
|
||||
option_number_len = (**packet_data_pptr & 0x0F);
|
||||
if (option_number_len == 13) {
|
||||
option_number_len = *(*packet_data_pptr + 1) + 13;
|
||||
(*packet_data_pptr)++;
|
||||
} else if (option_number_len == 14) {
|
||||
option_number_len = *(*packet_data_pptr + 2);
|
||||
option_number_len += (*(*packet_data_pptr + 1) << 8) + 269;
|
||||
(*packet_data_pptr) += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return returned_option_counter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \fn static uint16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint8_t options_count_left, uint8_t previous_option_number, sn_coap_option_numbers_e option, uint16_t option_number_len)
|
||||
*
|
||||
* \brief Counts needed memory for uri query option
|
||||
*
|
||||
* \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param options_count_left tells how many options are unhandled in Packet data
|
||||
*
|
||||
* \param previous_option_number is previous Option number
|
||||
*
|
||||
* \param sn_coap_option_numbers_e option option number to be calculated
|
||||
*
|
||||
* \param uint16_t option_number_len length of the first option part
|
||||
*/
|
||||
static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len)
|
||||
{
|
||||
uint16_t ret_value = 0;
|
||||
uint16_t i = 1;
|
||||
|
||||
/* Loop all Uri-Query options */
|
||||
while (i <= packet_left_len) {
|
||||
if (option == COAP_OPTION_LOCATION_PATH && option_number_len > 255) {
|
||||
return -1;
|
||||
}
|
||||
if (option == COAP_OPTION_URI_PATH && option_number_len > 255) {
|
||||
return -1;
|
||||
}
|
||||
if (option == COAP_OPTION_URI_QUERY && option_number_len > 255) {
|
||||
return -1;
|
||||
}
|
||||
if (option == COAP_OPTION_LOCATION_QUERY && option_number_len > 255) {
|
||||
return -1;
|
||||
}
|
||||
if (option == COAP_OPTION_ACCEPT && option_number_len > 2) {
|
||||
return -1;
|
||||
}
|
||||
if (option == COAP_OPTION_ETAG && option_number_len > 8) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
i += option_number_len;
|
||||
ret_value += option_number_len + 1; /* + 1 is for separator */
|
||||
|
||||
if( i == packet_left_len ) {
|
||||
break;
|
||||
}
|
||||
else if( i > packet_left_len ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((*(packet_data_ptr + i) >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0) {
|
||||
return (ret_value - 1); /* -1 because last Part path does not include separator */
|
||||
}
|
||||
|
||||
option_number_len = (*(packet_data_ptr + i) & 0x0F);
|
||||
|
||||
if (option_number_len == 13) {
|
||||
|
||||
if(i + 1 >= packet_left_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
i++;
|
||||
option_number_len = *(packet_data_ptr + i) + 13;
|
||||
} else if (option_number_len == 14) {
|
||||
|
||||
if(i + 2 >= packet_left_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
option_number_len = *(packet_data_ptr + i + 2);
|
||||
option_number_len += (*(packet_data_ptr + i + 1) << 8) + 269;
|
||||
i += 2;
|
||||
} else if (option_number_len == 15) {
|
||||
return -1;
|
||||
}
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
if (ret_value != 0) {
|
||||
return (ret_value - 1); /* -1 because last Part path does not include separator */
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static void sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
|
||||
*
|
||||
* \brief Parses CoAP message's Payload part from given Packet data
|
||||
*
|
||||
* \param packet_data_len is length of given Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param **packet_data_pptr is source for Packet data to be parsed to CoAP message
|
||||
*
|
||||
* \param *dst_coap_msg_ptr is destination for parsed CoAP message
|
||||
*****************************************************************************/
|
||||
static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
|
||||
{
|
||||
/* If there is payload */
|
||||
if ((*packet_data_pptr - packet_data_start_ptr) < packet_data_len) {
|
||||
if (**packet_data_pptr == 0xff) {
|
||||
(*packet_data_pptr)++;
|
||||
/* Parse Payload length */
|
||||
dst_coap_msg_ptr->payload_len = packet_data_len - (*packet_data_pptr - packet_data_start_ptr);
|
||||
|
||||
/* The presence of a marker followed by a zero-length payload MUST be processed as a message format error */
|
||||
if (dst_coap_msg_ptr->payload_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse Payload by setting CoAP message's payload_ptr to point Payload in Packet data */
|
||||
dst_coap_msg_ptr->payload_ptr = *packet_data_pptr;
|
||||
}
|
||||
/* No payload marker.. */
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
2080
lib/amb1_sdk/common/network/coap/sn_coap_protocol.c
Normal file
2080
lib/amb1_sdk/common/network/coap/sn_coap_protocol.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user