You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2017/12/21 02:55:44 UTC
[mynewt-mcumgr] 02/02: Rename newtmgr -> smp (simple management
protocol)
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 <cc...@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 <de...@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 <de...@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" <co...@mynewt.apache.org>.