This is an automated email from the ASF dual-hosted git repository. ccollins pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-mcumgr.git
commit 9308d50cf57f97b2f57069133115b362fd4fdf53 Author: Christopher Collins <ccoll...@apache.org> AuthorDate: Wed Dec 20 14:55:10 2017 -0800 Rename newtmgr -> smp (simple management protocol) Also add some comments. --- mgmt/include/mgmt/mgmt.h | 18 +- mgmt/src/mgmt.c | 14 + newtmgr/src/newtmgr.c | 354 ------------------ .../newtmgr/newtmgr.h => smp/include/smp/smp.h | 30 +- {newtmgr => smp}/pkg.yml | 12 +- .../port/mynewt/include/mynewt_smp/mynewt_smp.h | 30 +- {newtmgr => smp}/port/mynewt/pkg.yml | 5 +- .../port/mynewt/src/mynewt_smp.c | 130 +++---- smp/src/smp.c | 404 +++++++++++++++++++++ 9 files changed, 535 insertions(+), 462 deletions(-) diff --git a/mgmt/include/mgmt/mgmt.h b/mgmt/include/mgmt/mgmt.h index 5ed55d3..568d8b2 100644 --- a/mgmt/include/mgmt/mgmt.h +++ b/mgmt/include/mgmt/mgmt.h @@ -21,15 +21,14 @@ #define H_MGMT_MGMT_ #include <inttypes.h> - -#include "tinycbor/cbor.h" +#include "cbor.h" #ifdef __cplusplus extern "C" { #endif /* MTU for newtmgr responses */ -#define MGMT_MAX_MTU 1024 +#define MGMT_MAX_MTU (1024) #define MGMT_OP_READ (0) #define MGMT_OP_READ_RSP (1) @@ -63,7 +62,7 @@ extern "C" { #define MGMT_ERR_EMSGSIZE (7) /* Response too large. */ #define MGMT_ERR_EPERUSER (256) -#define NMGR_HDR_SIZE (8) +#define MGMT_HDR_SIZE (8) struct mgmt_hdr { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ @@ -102,7 +101,7 @@ struct mgmt_streamer_cfg { mgmt_free_buf_fn *free_buf; }; -/** Decodes requests and encodes responses. */ +/** Decodes requests and encodes responses for any mgmt protocol. */ struct mgmt_streamer { const struct mgmt_streamer_cfg *cfg; void *cb_arg; @@ -130,10 +129,15 @@ struct mgmt_handler { /** A collection of handlers for every command in a single group. */ struct mgmt_group { + /** Points to the next group in the list. */ + struct mgmt_group *mg_next; + + /** Array of handlers; one entry per command ID. */ const struct mgmt_handler *mg_handlers; uint16_t mg_handlers_count; + + /* The numeric ID of this group. */ uint16_t mg_group_id; - struct mgmt_group *mg_next; }; #define MGMT_GROUP_SET_HANDLERS(group__, handlers__) do { \ @@ -158,6 +162,8 @@ const struct mgmt_handler *mgmt_find_handler(uint16_t group_id, uint16_t command_id); int mgmt_err_from_cbor(int cbor_status); int mgmt_cbuf_init(struct mgmt_cbuf *cbuf, struct mgmt_streamer *streamer); +void mgmt_ntoh_hdr(struct mgmt_hdr *hdr); +void mgmt_hton_hdr(struct mgmt_hdr *hdr); #ifdef __cplusplus } diff --git a/mgmt/src/mgmt.c b/mgmt/src/mgmt.c index 1acb60f..f12fc98 100644 --- a/mgmt/src/mgmt.c +++ b/mgmt/src/mgmt.c @@ -154,3 +154,17 @@ mgmt_cbuf_init(struct mgmt_cbuf *cbuf, struct mgmt_streamer *streamer) return 0; } + +void +mgmt_ntoh_hdr(struct mgmt_hdr *hdr) +{ + hdr->nh_len = ntohs(hdr->nh_len); + hdr->nh_group = ntohs(hdr->nh_group); +} + +void +mgmt_hton_hdr(struct mgmt_hdr *hdr) +{ + hdr->nh_len = htons(hdr->nh_len); + hdr->nh_group = htons(hdr->nh_group); +} diff --git a/newtmgr/src/newtmgr.c b/newtmgr/src/newtmgr.c deleted file mode 100644 index 7f12f76..0000000 --- a/newtmgr/src/newtmgr.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -#include <assert.h> -#include <string.h> - -#include "mgmt/mgmt.h" -#include "newtmgr/newtmgr.h" -#include "tinycbor/cbor.h" -#include "tinycbor/cbor_mbuf_writer.h" -#include "tinycbor/cbor_mbuf_reader.h" - -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - -#ifndef ntohs -#define ntohs(x) (x) -#endif - -#ifndef htons -#define htons(x) (x) -#endif - -#else -/* Little endian. */ - -#ifndef ntohs -#define ntohs(x) ((uint16_t) \ - ((((x) & 0xff00) >> 8) | \ - (((x) & 0x00ff) << 8))) -#endif - -#ifndef htons -#define htons(x) (ntohs(x)) -#endif - -#endif - -static int -nmgr_align4(int x) -{ - int rem; - - rem = x % 4; - if (rem == 0) { - return x; - } else { - return x - rem + 4; - } -} - -static uint8_t -nmgr_rsp_op(uint8_t req_op) -{ - if (req_op == MGMT_OP_READ) { - return MGMT_OP_READ_RSP; - } else { - return MGMT_OP_WRITE_RSP; - } -} - -void -nmgr_ntoh_hdr(struct mgmt_hdr *hdr) -{ - hdr->nh_len = ntohs(hdr->nh_len); - hdr->nh_group = ntohs(hdr->nh_group); -} - -static void -nmgr_hton_hdr(struct mgmt_hdr *hdr) -{ - hdr->nh_len = htons(hdr->nh_len); - hdr->nh_group = htons(hdr->nh_group); -} - -static void -nmgr_init_rsp_hdr(const struct mgmt_hdr *req_hdr, struct mgmt_hdr *rsp_hdr) -{ - *rsp_hdr = (struct mgmt_hdr) { - .nh_len = 0, - .nh_flags = 0, - .nh_op = nmgr_rsp_op(req_hdr->nh_op), - .nh_group = req_hdr->nh_group, - .nh_seq = req_hdr->nh_seq, - .nh_id = req_hdr->nh_id, - }; -} - -static int -nmgr_read_hdr(struct nmgr_streamer *streamer, struct mgmt_hdr *hdr) -{ - struct mgmt_streamer *base; - - base = &streamer->ns_base; - - if (base->reader->message_size < sizeof *hdr) { - return MGMT_ERR_EINVAL; - } - - base->reader->cpy(base->reader, (char *)hdr, 0, sizeof *hdr); - return 0; -} - -static int -nmgr_write_hdr(struct nmgr_streamer *streamer, const struct mgmt_hdr *hdr) -{ - int rc; - - rc = mgmt_streamer_write_at(&streamer->ns_base, 0, hdr, sizeof *hdr); - return mgmt_err_from_cbor(rc); -} - -static int -nmgr_build_err_rsp(struct nmgr_streamer *streamer, - const struct mgmt_hdr *req_hdr, - int status) -{ - struct CborEncoder map; - struct mgmt_cbuf cbuf; - struct mgmt_hdr rsp_hdr; - int rc; - - rc = mgmt_cbuf_init(&cbuf, &streamer->ns_base); - if (rc != 0) { - return rc; - } - - nmgr_init_rsp_hdr(req_hdr, &rsp_hdr); - rc = nmgr_write_hdr(streamer, &rsp_hdr); - if (rc != 0) { - return rc; - } - - rc = cbor_encoder_create_map(&cbuf.encoder, &map, CborIndefiniteLength); - if (rc != 0) { - return rc; - } - - rc = mgmt_cbuf_setoerr(&cbuf, status); - if (rc != 0) { - return rc; - } - - rc = cbor_encoder_close_container(&cbuf.encoder, &map); - if (rc != 0) { - return rc; - } - - rsp_hdr.nh_len = cbor_encode_bytes_written(&cbuf.encoder) - MGMT_HDR_SIZE; - nmgr_hton_hdr(&rsp_hdr); - rc = nmgr_write_hdr(streamer, &rsp_hdr); - if (rc != 0) { - return rc; - } - - return 0; -} - -int -nmgr_handle_single_payload(struct mgmt_cbuf *cbuf, - const struct mgmt_hdr *req_hdr) -{ - const struct mgmt_handler *handler; - struct CborEncoder payload_encoder; - int rc; - - handler = mgmt_find_handler(req_hdr->nh_group, req_hdr->nh_id); - if (!handler) { - return MGMT_ERR_ENOENT; - } - - /* Begin response payload. Response fields are inserted into the root - * map as key value pairs. - */ - rc = cbor_encoder_create_map(&cbuf->encoder, &payload_encoder, - CborIndefiniteLength); - rc = mgmt_err_from_cbor(rc); - if (rc != 0) { - return rc; - } - - if (req_hdr->nh_op == MGMT_OP_READ) { - if (handler->mh_read) { - rc = handler->mh_read(cbuf); - } else { - rc = MGMT_ERR_ENOENT; - } - } else if (req_hdr->nh_op == MGMT_OP_WRITE) { - if (handler->mh_write) { - rc = handler->mh_write(cbuf); - } else { - rc = MGMT_ERR_ENOENT; - } - } else { - rc = MGMT_ERR_EINVAL; - } - if (rc != 0) { - return rc; - } - - /* End response payload. */ - rc = cbor_encoder_close_container(&cbuf->encoder, &payload_encoder); - rc = mgmt_err_from_cbor(rc); - if (rc != 0) { - return rc; - } - - return 0; -} - - -static int -nmgr_handle_single_req(struct nmgr_streamer *streamer, - const struct mgmt_hdr *req_hdr) -{ - struct mgmt_cbuf cbuf; - struct mgmt_hdr rsp_hdr; - int rc; - - rc = mgmt_cbuf_init(&cbuf, &streamer->ns_base); - if (rc != 0) { - return rc; - } - - /* Build response header a priori, then pass to the handlers to fill out - * the response data and adjust length and flags. - */ - nmgr_init_rsp_hdr(req_hdr, &rsp_hdr); - rc = nmgr_write_hdr(streamer, &rsp_hdr); - if (rc != 0) { - return rc; - } - - rc = nmgr_handle_single_payload(&cbuf, req_hdr); - if (rc != 0) { - return rc; - } - - rsp_hdr.nh_len = cbor_encode_bytes_written(&cbuf.encoder) - MGMT_HDR_SIZE; - nmgr_hton_hdr(&rsp_hdr); - rc = nmgr_write_hdr(streamer, &rsp_hdr); - if (rc != 0) { - return rc; - } - - return 0; -} - -static void -nmgr_on_err(struct nmgr_streamer *streamer, - const struct mgmt_hdr *req_hdr, - void *req, - void *rsp, - int status) -{ - int rc; - - if (rsp == NULL) { - rsp = req; - req = NULL; - } - - mgmt_streamer_reset_buf(&streamer->ns_base, rsp); - mgmt_streamer_init_writer(&streamer->ns_base, rsp); - - rc = nmgr_build_err_rsp(streamer, req_hdr, status); - if (rc == 0) { - streamer->ns_tx_rsp(streamer, rsp, streamer->ns_base.cb_arg); - rsp = NULL; - } - - mgmt_streamer_free_buf(&streamer->ns_base, req); - mgmt_streamer_free_buf(&streamer->ns_base, rsp); -} - -int -nmgr_process_single_packet(struct nmgr_streamer *streamer, void *req) -{ - struct mgmt_hdr req_hdr; - void *rsp; - bool valid_hdr; - int rc; - - rsp = NULL; - valid_hdr = true; - - while (1) { - rc = mgmt_streamer_init_reader(&streamer->ns_base, req); - if (rc != 0) { - valid_hdr = false; - break; - } - - rc = nmgr_read_hdr(streamer, &req_hdr); - if (rc != 0) { - valid_hdr = false; - break; - } - nmgr_ntoh_hdr(&req_hdr); - rc = mgmt_streamer_trim_front(&streamer->ns_base, req, MGMT_HDR_SIZE); - assert(rc == 0); - - rsp = mgmt_streamer_alloc_rsp(&streamer->ns_base, req); - if (rsp == NULL) { - rc = MGMT_ERR_ENOMEM; - break; - } - - rc = mgmt_streamer_init_writer(&streamer->ns_base, rsp); - if (rc != 0) { - break; - } - - rc = nmgr_handle_single_req(streamer, &req_hdr); - if (rc != 0) { - break; - } - - rc = streamer->ns_tx_rsp(streamer, rsp, streamer->ns_base.cb_arg); - rsp = NULL; - if (rc != 0) { - break; - } - - /* Trim processed request to free up space for subsequent responses. */ - rc = mgmt_streamer_trim_front(&streamer->ns_base, req, - nmgr_align4(req_hdr.nh_len)); - assert(rc == 0); - } - - if (rc != 0 && valid_hdr) { - nmgr_on_err(streamer, &req_hdr, req, rsp, rc); - return rc; - } - - mgmt_streamer_free_buf(&streamer->ns_base, req); - mgmt_streamer_free_buf(&streamer->ns_base, rsp); - return 0; -} diff --git a/newtmgr/include/newtmgr/newtmgr.h b/smp/include/smp/smp.h similarity index 61% rename from newtmgr/include/newtmgr/newtmgr.h rename to smp/include/smp/smp.h index c6b3806..2feaa47 100644 --- a/newtmgr/include/newtmgr/newtmgr.h +++ b/smp/include/smp/smp.h @@ -17,8 +17,10 @@ * under the License. */ -#ifndef _NEWTMGR_H_ -#define _NEWTMGR_H_ +/** SMP - Simple Management Protocol. */ + +#ifndef H_SMP_ +#define H_SMP_ #include "mgmt/mgmt.h" @@ -26,23 +28,25 @@ extern "C" { #endif -struct mynewt_nmgr_transport; -struct nmgr_streamer; +struct mynewt_smp_transport; +struct smp_streamer; struct mgmt_hdr; -typedef int nmgr_tx_rsp_fn(struct nmgr_streamer *ns, void *buf, void *arg); -struct nmgr_streamer { - struct mgmt_streamer ns_base; - nmgr_tx_rsp_fn *ns_tx_rsp; +typedef int smp_tx_rsp_fn(struct smp_streamer *ss, void *buf, void *arg); + +/** Decodes, encodes, and transmits SMP packets. */ +struct smp_streamer { + struct mgmt_streamer ss_base; + smp_tx_rsp_fn *ss_tx_rsp; }; -void nmgr_ntoh_hdr(struct mgmt_hdr *hdr); -int nmgr_handle_single_payload(struct mgmt_cbuf *cbuf, - const struct mgmt_hdr *req_hdr); -int nmgr_process_single_packet(struct nmgr_streamer *streamer, void *req); +void smp_ntoh_hdr(struct mgmt_hdr *hdr); +int smp_handle_single_payload(struct mgmt_cbuf *cbuf, + const struct mgmt_hdr *req_hdr); +int smp_process_single_packet(struct smp_streamer *streamer, void *req); #ifdef __cplusplus } #endif -#endif /* _NETMGR_H */ +#endif /* H_SMP_ */ diff --git a/newtmgr/pkg.yml b/smp/pkg.yml similarity index 86% rename from newtmgr/pkg.yml rename to smp/pkg.yml index 2d48007..bf165cb 100644 --- a/newtmgr/pkg.yml +++ b/smp/pkg.yml @@ -17,8 +17,8 @@ # under the License. # -pkg.name: mgmt/newtmgr -pkg.description: Server-side newtmgr functionality. +pkg.name: smp +pkg.description: Server-side simple management protocol (SMP) functionality. pkg.author: "Apache Mynewt <d...@mynewt.apache.org>" pkg.homepage: "http://mynewt.apache.org/" pkg.keywords: @@ -26,16 +26,16 @@ pkg.keywords: pkg.deps: - encoding/cborattr - kernel/os - - mgmt/mgmt - - mgmt/newtmgr/nmgr_os - - mgmt/newtmgr/port/mynewt + - mgmt + - smp/port/mynewt - util/mem pkg.deps.NEWTMGR_BLE_HOST: + # XXX: Inaccurate path. - mgmt/newtmgr/transport/ble pkg.apis: - - newtmgr + - smp pkg.init: nmgr_pkg_init: 500 diff --git a/newtmgr/port/mynewt/include/mynewt_newtmgr/mynewt_newtmgr.h b/smp/port/mynewt/include/mynewt_smp/mynewt_smp.h similarity index 65% rename from newtmgr/port/mynewt/include/mynewt_newtmgr/mynewt_newtmgr.h rename to smp/port/mynewt/include/mynewt_smp/mynewt_smp.h index 0317ef5..02883c5 100644 --- a/newtmgr/port/mynewt/include/mynewt_newtmgr/mynewt_newtmgr.h +++ b/smp/port/mynewt/include/mynewt_smp/mynewt_smp.h @@ -17,13 +17,13 @@ * under the License. */ -#ifndef H_MYNEWT_NEWTMGR_ -#define H_MYNEWT_NEWTMGR_ +#ifndef H_MYNEWT_SMP_ +#define H_MYNEWT_SMP_ #include <inttypes.h> #include "mgmt/mgmt.h" #include "os/os_mbuf.h" -struct mynewt_nmgr_transport; +struct mynewt_smp_transport; #ifdef __cplusplus extern "C" { @@ -33,8 +33,8 @@ extern "C" { * Transmit function. The supplied mbuf is always consumed, regardless of * return code. */ -typedef int mynewt_nmgr_transport_out_fn(struct mynewt_nmgr_transport *mnt, - struct os_mbuf *m); +typedef int mynewt_smp_transport_out_fn(struct mynewt_smp_transport *mnt, + struct os_mbuf *m); /** * MTU query function. The supplied mbuf should contain a request received @@ -45,22 +45,22 @@ typedef int mynewt_nmgr_transport_out_fn(struct mynewt_nmgr_transport *mnt, * @return The transport's MTU; * 0 if transmission is currently not possible. */ -typedef uint16_t mynewt_nmgr_transport_get_mtu_fn(struct os_mbuf *m); +typedef uint16_t mynewt_smp_transport_get_mtu_fn(struct os_mbuf *m); -struct mynewt_nmgr_transport { - struct os_mqueue mnt_imq; - mynewt_nmgr_transport_out_fn *mnt_output; - mynewt_nmgr_transport_get_mtu_fn *mnt_get_mtu; +struct mynewt_smp_transport { + struct os_mqueue msp_imq; + mynewt_smp_transport_out_fn *msp_output; + mynewt_smp_transport_get_mtu_fn *msp_get_mtu; }; -int mynewt_nmgr_transport_init(struct mynewt_nmgr_transport *mnt, - mynewt_nmgr_transport_out_fn *output_func, - mynewt_nmgr_transport_get_mtu_fn *get_mtu_func); +int mynewt_smp_transport_init(struct mynewt_smp_transport *mnt, + mynewt_smp_transport_out_fn *output_func, + mynewt_smp_transport_get_mtu_fn *get_mtu_func); -int mynewt_nmgr_rx_req(struct mynewt_nmgr_transport *mnt, struct os_mbuf *req); +int mynewt_smp_rx_req(struct mynewt_smp_transport *mnt, struct os_mbuf *req); #ifdef __cplusplus } #endif -#endif /* H_MYNEWT_NETMGR_ */ +#endif /* H_MYNEWT_SMP_ */ diff --git a/newtmgr/port/mynewt/pkg.yml b/smp/port/mynewt/pkg.yml similarity index 93% rename from newtmgr/port/mynewt/pkg.yml rename to smp/port/mynewt/pkg.yml index bb90250..ae71ebf 100644 --- a/newtmgr/port/mynewt/pkg.yml +++ b/smp/port/mynewt/pkg.yml @@ -17,7 +17,7 @@ # under the License. # -pkg.name: mgmt/newtmgr/port/mynewt +pkg.name: smp/port/mynewt pkg.description: Server-side newtmgr functionality. pkg.author: "Apache Mynewt <d...@mynewt.apache.org>" pkg.homepage: "http://mynewt.apache.org/" @@ -25,6 +25,5 @@ pkg.keywords: pkg.deps: - kernel/os - - mgmt/mgmt - - mgmt/mgmt_os + - mgmt - util/mem diff --git a/newtmgr/port/mynewt/src/mynewt_nmgr.c b/smp/port/mynewt/src/mynewt_smp.c similarity index 54% rename from newtmgr/port/mynewt/src/mynewt_nmgr.c rename to smp/port/mynewt/src/mynewt_smp.c index 0aa4c9b..f5f2950 100644 --- a/newtmgr/port/mynewt/src/mynewt_nmgr.c +++ b/smp/port/mynewt/src/mynewt_smp.c @@ -2,40 +2,40 @@ #include "os/os.h" #include "mynewt_mgmt/mynewt_mgmt.h" -#include "newtmgr/newtmgr.h" +#include "smp/smp.h" #include "mgmt_os/mgmt_os.h" #include "mem/mem.h" -#include "tinycbor/cbor_mbuf_reader.h" -#include "tinycbor/cbor_mbuf_writer.h" -#include "mynewt_newtmgr/mynewt_newtmgr.h" - -/* Shared queue that newtmgr uses for work items. */ -struct os_eventq *nmgr_evq; - -static mgmt_alloc_rsp_fn mynewt_nmgr_alloc_rsp; -static mgmt_trim_front_fn mynewt_nmgr_trim_front; -static mgmt_reset_buf_fn mynewt_nmgr_reset_buf; -static mgmt_write_at_fn mynewt_nmgr_write_at; -static mgmt_init_reader_fn mynewt_nmgr_init_reader; -static mgmt_init_writer_fn mynewt_nmgr_init_writer; -static mgmt_free_buf_fn mynewt_nmgr_free_buf; -static nmgr_tx_rsp_fn mynewt_nmgr_tx_rsp; - -static const struct mgmt_streamer_cfg mynewt_nmgr_cbor_cfg = { - .alloc_rsp = mynewt_nmgr_alloc_rsp, - .trim_front = mynewt_nmgr_trim_front, - .reset_buf = mynewt_nmgr_reset_buf, - .write_at = mynewt_nmgr_write_at, - .init_reader = mynewt_nmgr_init_reader, - .init_writer = mynewt_nmgr_init_writer, - .free_buf = mynewt_nmgr_free_buf, +#include "cbor_mbuf_reader.h" +#include "cbor_mbuf_writer.h" +#include "mynewt_smp/mynewt_smp.h" + +/* Shared queue that smp uses for work items. */ +struct os_eventq *smp_evq; + +static mgmt_alloc_rsp_fn mynewt_smp_alloc_rsp; +static mgmt_trim_front_fn mynewt_smp_trim_front; +static mgmt_reset_buf_fn mynewt_smp_reset_buf; +static mgmt_write_at_fn mynewt_smp_write_at; +static mgmt_init_reader_fn mynewt_smp_init_reader; +static mgmt_init_writer_fn mynewt_smp_init_writer; +static mgmt_free_buf_fn mynewt_smp_free_buf; +static smp_tx_rsp_fn mynewt_smp_tx_rsp; + +static const struct mgmt_streamer_cfg mynewt_smp_cbor_cfg = { + .alloc_rsp = mynewt_smp_alloc_rsp, + .trim_front = mynewt_smp_trim_front, + .reset_buf = mynewt_smp_reset_buf, + .write_at = mynewt_smp_write_at, + .init_reader = mynewt_smp_init_reader, + .init_writer = mynewt_smp_init_writer, + .free_buf = mynewt_smp_free_buf, }; /** * Allocates an mbuf to contain an outgoing response fragment. */ static struct os_mbuf * -mynewt_nmgr_rsp_frag_alloc(uint16_t frag_size, void *arg) +mynewt_smp_rsp_frag_alloc(uint16_t frag_size, void *arg) { struct os_mbuf *src_rsp; struct os_mbuf *frag; @@ -56,7 +56,7 @@ mynewt_nmgr_rsp_frag_alloc(uint16_t frag_size, void *arg) } static void * -mynewt_nmgr_alloc_rsp(const void *req, void *arg) +mynewt_smp_alloc_rsp(const void *req, void *arg) { const struct os_mbuf *om_req; struct os_mbuf *om_rsp; @@ -76,7 +76,7 @@ mynewt_nmgr_alloc_rsp(const void *req, void *arg) } static int -mynewt_nmgr_trim_front(void *buf, int len, void *arg) +mynewt_smp_trim_front(void *buf, int len, void *arg) { struct os_mbuf *om; @@ -86,7 +86,7 @@ mynewt_nmgr_trim_front(void *buf, int len, void *arg) } static void -mynewt_nmgr_reset_buf(void *buf, void *arg) +mynewt_smp_reset_buf(void *buf, void *arg) { struct os_mbuf *om; @@ -95,8 +95,8 @@ mynewt_nmgr_reset_buf(void *buf, void *arg) } static int -mynewt_nmgr_write_at(struct cbor_encoder_writer *writer, int offset, - const void *data, int len, void *arg) +mynewt_smp_write_at(struct cbor_encoder_writer *writer, int offset, + const void *data, int len, void *arg) { struct cbor_mbuf_writer *mw; int rc; @@ -113,8 +113,8 @@ mynewt_nmgr_write_at(struct cbor_encoder_writer *writer, int offset, } static int -mynewt_nmgr_init_reader(struct cbor_decoder_reader *reader, void *buf, - void *arg) +mynewt_smp_init_reader(struct cbor_decoder_reader *reader, void *buf, + void *arg) { struct cbor_mbuf_reader *mr; @@ -125,8 +125,8 @@ mynewt_nmgr_init_reader(struct cbor_decoder_reader *reader, void *buf, } static int -mynewt_nmgr_init_writer(struct cbor_encoder_writer *writer, void *buf, - void *arg) +mynewt_smp_init_writer(struct cbor_encoder_writer *writer, void *buf, + void *arg) { struct cbor_mbuf_writer *mw; @@ -137,31 +137,31 @@ mynewt_nmgr_init_writer(struct cbor_encoder_writer *writer, void *buf, } static int -mynewt_nmgr_tx_rsp(struct nmgr_streamer *ns, void *rsp, void *arg) +mynewt_smp_tx_rsp(struct smp_streamer *ss, void *rsp, void *arg) { - struct mynewt_nmgr_transport *mnt; + struct mynewt_smp_transport *msp; struct os_mbuf *om_rsp; struct os_mbuf *frag; uint16_t mtu; int rc; - mnt = arg; + msp = arg; om_rsp = rsp; - mtu = mnt->mnt_get_mtu(rsp); + mtu = msp->msp_get_mtu(rsp); if (mtu == 0) { /* The transport cannot support a transmission right now. */ return MGMT_ERR_EUNKNOWN; } while (om_rsp != NULL) { - frag = mem_split_frag(&om_rsp, mtu, mynewt_nmgr_rsp_frag_alloc, + frag = mem_split_frag(&om_rsp, mtu, mynewt_smp_rsp_frag_alloc, om_rsp); if (frag == NULL) { return MGMT_ERR_ENOMEM; } - rc = mnt->mnt_output(mnt, frag); + rc = msp->msp_output(msp, frag); if (rc != 0) { /* Output function already freed mbuf. */ return MGMT_ERR_EUNKNOWN; @@ -172,37 +172,37 @@ mynewt_nmgr_tx_rsp(struct nmgr_streamer *ns, void *rsp, void *arg) } static void -mynewt_nmgr_free_buf(void *buf, void *arg) +mynewt_smp_free_buf(void *buf, void *arg) { os_mbuf_free_chain(buf); } static void -mynewt_nmgr_process(struct mynewt_nmgr_transport *mnt) +mynewt_smp_process(struct mynewt_smp_transport *msp) { struct cbor_mbuf_reader reader; struct cbor_mbuf_writer writer; - struct nmgr_streamer streamer; + struct smp_streamer streamer; struct os_mbuf *req; int rc; - streamer = (struct nmgr_streamer) { - .ns_base = { - .cfg = &mynewt_nmgr_cbor_cfg, + streamer = (struct smp_streamer) { + .ss_base = { + .cfg = &mynewt_smp_cbor_cfg, .reader = &reader.r, .writer = &writer.enc, - .cb_arg = mnt, + .cb_arg = msp, }, - .ns_tx_rsp = mynewt_nmgr_tx_rsp, + .ss_tx_rsp = mynewt_smp_tx_rsp, }; while (1) { - req = os_mqueue_get(&mnt->mnt_imq); + req = os_mqueue_get(&msp->msp_imq); if (req == NULL) { break; } - rc = nmgr_process_single_packet(&streamer, req); + rc = smp_process_single_packet(&streamer, req); if (rc != 0) { break; } @@ -210,24 +210,24 @@ mynewt_nmgr_process(struct mynewt_nmgr_transport *mnt) } static void -mynewt_nmgr_event_data_in(struct os_event *ev) +mynewt_smp_event_data_in(struct os_event *ev) { - mynewt_nmgr_process(ev->ev_arg); + mynewt_smp_process(ev->ev_arg); } int -mynewt_nmgr_transport_init(struct mynewt_nmgr_transport *mnt, - mynewt_nmgr_transport_out_fn *output_func, - mynewt_nmgr_transport_get_mtu_fn *get_mtu_func) +mynewt_smp_transport_init(struct mynewt_smp_transport *msp, + mynewt_smp_transport_out_fn *output_func, + mynewt_smp_transport_get_mtu_fn *get_mtu_func) { int rc; - *mnt = (struct mynewt_nmgr_transport) { - .mnt_output = output_func, - .mnt_get_mtu = get_mtu_func, + *msp = (struct mynewt_smp_transport) { + .msp_output = output_func, + .msp_get_mtu = get_mtu_func, }; - rc = os_mqueue_init(&mnt->mnt_imq, mynewt_nmgr_event_data_in, mnt); + rc = os_mqueue_init(&msp->msp_imq, mynewt_smp_event_data_in, msp); if (rc != 0) { return rc; } @@ -236,11 +236,11 @@ mynewt_nmgr_transport_init(struct mynewt_nmgr_transport *mnt, } int -mynewt_nmgr_rx_req(struct mynewt_nmgr_transport *mnt, struct os_mbuf *req) +mynewt_smp_rx_req(struct mynewt_smp_transport *msp, struct os_mbuf *req) { int rc; - rc = os_mqueue_put(&mnt->mnt_imq, mgmt_evq_get(), req); + rc = os_mqueue_put(&msp->msp_imq, mgmt_evq_get(), req); if (rc != 0) { os_mbuf_free_chain(req); } @@ -251,17 +251,17 @@ mynewt_nmgr_rx_req(struct mynewt_nmgr_transport *mnt, struct os_mbuf *req) struct os_eventq * mgmt_evq_get(void) { - return nmgr_evq; + return smp_evq; } void mgmt_evq_set(struct os_eventq *evq) { - nmgr_evq = evq; + smp_evq = evq; } void -nmgr_pkg_init(void) +smp_pkg_init(void) { int rc; diff --git a/smp/src/smp.c b/smp/src/smp.c new file mode 100644 index 0000000..6caf653 --- /dev/null +++ b/smp/src/smp.c @@ -0,0 +1,404 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +/** SMP - Simple Management Protocol. */ + +#include <assert.h> +#include <string.h> + +#include "mgmt/mgmt.h" +#include "smp/smp.h" +#include "tinycbor/cbor.h" +#include "tinycbor/cbor_mbuf_writer.h" +#include "tinycbor/cbor_mbuf_reader.h" + +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +#ifndef ntohs +#define ntohs(x) (x) +#endif + +#ifndef htons +#define htons(x) (x) +#endif + +#else +/* Little endian. */ + +#ifndef ntohs +#define ntohs(x) ((uint16_t) \ + ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8))) +#endif + +#ifndef htons +#define htons(x) (ntohs(x)) +#endif + +#endif + +static int +smp_align4(int x) +{ + int rem; + + rem = x % 4; + if (rem == 0) { + return x; + } else { + return x - rem + 4; + } +} + +static uint8_t +smp_rsp_op(uint8_t req_op) +{ + if (req_op == MGMT_OP_READ) { + return MGMT_OP_READ_RSP; + } else { + return MGMT_OP_WRITE_RSP; + } +} + +static void +smp_init_rsp_hdr(const struct mgmt_hdr *req_hdr, struct mgmt_hdr *rsp_hdr) +{ + *rsp_hdr = (struct mgmt_hdr) { + .nh_len = 0, + .nh_flags = 0, + .nh_op = smp_rsp_op(req_hdr->nh_op), + .nh_group = req_hdr->nh_group, + .nh_seq = req_hdr->nh_seq, + .nh_id = req_hdr->nh_id, + }; +} + +static int +smp_read_hdr(struct smp_streamer *streamer, struct mgmt_hdr *dst_hdr) +{ + struct cbor_decoder_reader *reader; + + reader = streamer->ss_base.reader; + + if (reader->message_size < sizeof *hdr) { + return MGMT_ERR_EINVAL; + } + + reader->cpy(reader, (char *)hdr, 0, sizeof *hdr); + return 0; +} + +static int +smp_write_hdr(struct smp_streamer *streamer, const struct mgmt_hdr *src_hdr) +{ + int rc; + + rc = mgmt_streamer_write_at(&streamer->ss_base, 0, src_hdr, + sizeof *src_hdr); + return mgmt_err_from_cbor(rc); +} + +static int +smp_build_err_rsp(struct smp_streamer *streamer, + const struct mgmt_hdr *req_hdr, + int status) +{ + struct CborEncoder map; + struct mgmt_cbuf cbuf; + struct mgmt_hdr rsp_hdr; + int rc; + + rc = mgmt_cbuf_init(&cbuf, &streamer->ss_base); + if (rc != 0) { + return rc; + } + + smp_init_rsp_hdr(req_hdr, &rsp_hdr); + rc = smp_write_hdr(streamer, &rsp_hdr); + if (rc != 0) { + return rc; + } + + rc = cbor_encoder_create_map(&cbuf.encoder, &map, CborIndefiniteLength); + if (rc != 0) { + return rc; + } + + rc = mgmt_cbuf_setoerr(&cbuf, status); + if (rc != 0) { + return rc; + } + + rc = cbor_encoder_close_container(&cbuf.encoder, &map); + if (rc != 0) { + return rc; + } + + rsp_hdr.nh_len = cbor_encode_bytes_written(&cbuf.encoder) - MGMT_HDR_SIZE; + mgmt_hton_hdr(&rsp_hdr); + rc = smp_write_hdr(streamer, &rsp_hdr); + if (rc != 0) { + return rc; + } + + return 0; +} + +/** + * Processes a single SMP request and generates a response payload (i.e., + * everything after the management header). On success, the response payload + * is written to the supplied cbuf but not transmitted. On failure, no error + * response gets written; the caller is expected to build an error response + * from the return code. + * + * @param cbuf A cbuf containing the request and response + * buffer. + * @param req_hdr The management header belonging to the incoming + * request (host-byte order). + * + * @return A MGMT_ERR_[...] error code. + */ +int +smp_handle_single_payload(struct mgmt_cbuf *cbuf, + const struct mgmt_hdr *req_hdr) +{ + const struct mgmt_handler *handler; + struct CborEncoder payload_encoder; + int rc; + + handler = mgmt_find_handler(req_hdr->nh_group, req_hdr->nh_id); + if (handler == NULL) { + return MGMT_ERR_ENOENT; + } + + /* Begin response payload. Response fields are inserted into the root + * map as key value pairs. + */ + rc = cbor_encoder_create_map(&cbuf->encoder, &payload_encoder, + CborIndefiniteLength); + rc = mgmt_err_from_cbor(rc); + if (rc != 0) { + return rc; + } + + switch (req_hdr->nh_op) { + case MGMT_OP_READ: + if (handler->mh_read != NULL) { + rc = handler->mh_read(cbuf); + } else { + rc = MGMT_ERR_ENOENT; + } + break; + + case MGMT_OP_WRITE: + if (handler->mh_write != NULL) { + rc = handler->mh_write(cbuf); + } else { + rc = MGMT_ERR_ENOENT; + } + break; + + default: + rc = MGMT_ERR_EINVAL; + break; + } + if (rc != 0) { + return rc; + } + + /* End response payload. */ + rc = cbor_encoder_close_container(&cbuf->encoder, &payload_encoder); + return mgmt_err_from_cbor(rc); +} + +/** + * Processes a single SMP request and generates a complete response (i.e., + * header and payload). On success, the response is written using the supplied + * streamer but not transmitted. On failure, no error response gets written; + * the caller is expected to build an error response from the return code. + * + * @param streamer The SMP streamer to use for reading the request + * and writing the response. + * @param req_hdr The management header belonging to the incoming + * request (host-byte order). + * + * @return A MGMT_ERR_[...] error code. + */ +static int +smp_handle_single_req(struct smp_streamer *streamer, + const struct mgmt_hdr *req_hdr) +{ + struct mgmt_cbuf cbuf; + struct mgmt_hdr rsp_hdr; + int rc; + + rc = mgmt_cbuf_init(&cbuf, &streamer->ss_base); + if (rc != 0) { + return rc; + } + + /* Write a dummy header to the beginning of the response buffer. Some + * fields will need to be fixed up later. + */ + smp_init_rsp_hdr(req_hdr, &rsp_hdr); + rc = smp_write_hdr(streamer, &rsp_hdr); + if (rc != 0) { + return rc; + } + + /* Process the request and write the response payload. */ + rc = smp_handle_single_payload(&cbuf, req_hdr); + if (rc != 0) { + return rc; + } + + /* Fix up the response header with the correct length. */ + rsp_hdr.nh_len = cbor_encode_bytes_written(&cbuf.encoder) - MGMT_HDR_SIZE; + mgmt_hton_hdr(&rsp_hdr); + rc = smp_write_hdr(streamer, &rsp_hdr); + if (rc != 0) { + return rc; + } + + return 0; +} + +/** + * Attempts to transmit an SMP error response. This function consumes both + * supplied buffers. + * + * @param streamer The SMP streamer for building and transmitting + * the response. + * @param req_hdr The header of the request which elicited the + * error. + * @param req The buffer holding the request. + * @param rsp The buffer holding the response, or NULL if + * none was allocated. + * @param status The status to indicate in the error response. + */ +static void +smp_on_err(struct smp_streamer *streamer, const struct mgmt_hdr *req_hdr, + void *req, void *rsp, int status) +{ + int rc; + + /* Prefer the response buffer for holding the error response. If no + * response buffer was allocated, use the request buffer instead. + */ + if (rsp == NULL) { + rsp = req; + req = NULL; + } + + /* Clear the partial response from the buffer, if any. */ + mgmt_streamer_reset_buf(&streamer->ss_base, rsp); + mgmt_streamer_init_writer(&streamer->ss_base, rsp); + + /* Build and transmit the error response. */ + rc = smp_build_err_rsp(streamer, req_hdr, status); + if (rc == 0) { + streamer->ss_tx_rsp(streamer, rsp, streamer->ss_base.cb_arg); + rsp = NULL; + } + + /* Free any extra buffers. */ + mgmt_streamer_free_buf(&streamer->ss_base, req); + mgmt_streamer_free_buf(&streamer->ss_base, rsp); +} + +/** + * Processes all SMP requests in an incoming packet. Requests are processed + * sequentially from the start of the packet to the end. Each response is sent + * individually in its own packet. If a request elicits an error response, + * processing of the packet is aborted. This function consumes the supplied + * request buffer regardless of the outcome. + * + * @param streamer The streamer to use for reading, writing, and + * transmitting. + * @param req A buffer containing the request packet. + * + * @return A MGMT_ERR_[...] error code. + */ +int +smp_process_single_packet(struct smp_streamer *streamer, void *req) +{ + struct mgmt_hdr req_hdr; + void *rsp; + bool valid_hdr; + int rc; + + rsp = NULL; + valid_hdr = true; + + while (1) { + rc = mgmt_streamer_init_reader(&streamer->ss_base, req); + if (rc != 0) { + valid_hdr = false; + break; + } + + /* Read the management header and strip it from the request. */ + rc = smp_read_hdr(streamer, &req_hdr); + if (rc != 0) { + valid_hdr = false; + break; + } + mgmt_ntoh_hdr(&req_hdr); + rc = mgmt_streamer_trim_front(&streamer->ss_base, req, MGMT_HDR_SIZE); + assert(rc == 0); + + rsp = mgmt_streamer_alloc_rsp(&streamer->ss_base, req); + if (rsp == NULL) { + rc = MGMT_ERR_ENOMEM; + break; + } + + rc = mgmt_streamer_init_writer(&streamer->ss_base, rsp); + if (rc != 0) { + break; + } + + /* Process the request payload and build the response. */ + rc = smp_handle_single_req(streamer, &req_hdr); + if (rc != 0) { + break; + } + + /* Send the response. */ + rc = streamer->ss_tx_rsp(streamer, rsp, streamer->ss_base.cb_arg); + rsp = NULL; + if (rc != 0) { + break; + } + + /* Trim processed request to free up space for subsequent responses. */ + rc = mgmt_streamer_trim_front(&streamer->ss_base, req, + smp_align4(req_hdr.nh_len)); + assert(rc == 0); + } + + if (rc != 0 && valid_hdr) { + smp_on_err(streamer, &req_hdr, req, rsp, rc); + return rc; + } + + mgmt_streamer_free_buf(&streamer->ss_base, req); + mgmt_streamer_free_buf(&streamer->ss_base, rsp); + return 0; +} -- To stop receiving notification emails like this one, please contact "commits@mynewt.apache.org" <commits@mynewt.apache.org>.