blob: 5643274007edf851b11bfffa85519a4ed2c4a2a7 [file] [log] [blame]
/*
* 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 "os/mynewt.h"
#include "mem/mem.h"
#include "mgmt/mgmt.h"
#include "omp/omp.h"
#include "tinycbor/cbor.h"
#include "tinycbor/cbor_mbuf_writer.h"
#include "tinycbor/cbor_mbuf_reader.h"
#include "cborattr/cborattr.h"
#include "omp/omp.h"
#include "oic/oc_api.h"
static struct omp_state omgr_state;
static mgmt_alloc_rsp_fn omgr_alloc_rsp;
static mgmt_trim_front_fn omgr_trim_front;
static mgmt_reset_buf_fn omgr_reset_buf;
static mgmt_write_at_fn omgr_write_at;
static mgmt_init_reader_fn omgr_init_reader;
static mgmt_init_writer_fn omgr_init_writer;
static mgmt_free_buf_fn omgr_free_buf;
const struct mgmt_streamer_cfg g_omgr_cbor_cfg = {
.alloc_rsp = omgr_alloc_rsp,
.trim_front = omgr_trim_front,
.reset_buf = omgr_reset_buf,
.write_at = omgr_write_at,
.init_reader = omgr_init_reader,
.init_writer = omgr_init_writer,
.free_buf = omgr_free_buf,
};
static void*
omgr_alloc_rsp(const void *src_buf, void *req)
{
struct os_mbuf *m;
struct os_mbuf *rsp;
if (!req) {
return NULL;
}
m = (struct os_mbuf *)req;
rsp = os_msys_get_pkthdr(0, OS_MBUF_USRHDR_LEN(m));
if (!rsp) {
return NULL;
}
memcpy(OS_MBUF_USRHDR(rsp), OS_MBUF_USRHDR(m), OS_MBUF_USRHDR_LEN(m));
return req;
}
static void
omgr_trim_front(void *m, size_t len, void *arg)
{
os_mbuf_adj(m, len);
}
static void
omgr_reset_buf(void *m, void *arg)
{
if (!m) {
return;
}
/* We need to trim from the back because the head
* contains useful information which we do not want
* to get rid of
*/
os_mbuf_adj(m, -1 * OS_MBUF_PKTLEN((struct os_mbuf *)m));
}
static int
omgr_write_at(struct cbor_encoder_writer *writer, size_t offset,
const void *data, size_t len, void *arg)
{
struct cbor_mbuf_writer *cmw;
struct os_mbuf *m;
int rc;
if (!writer) {
return MGMT_ERR_EINVAL;
}
cmw = (struct cbor_mbuf_writer *)writer;
m = cmw->m;
if (offset > OS_MBUF_PKTLEN(m)) {
return MGMT_ERR_EINVAL;
}
rc = os_mbuf_copyinto(m, offset, data, len);
if (rc) {
return MGMT_ERR_ENOMEM;
}
writer->bytes_written = OS_MBUF_PKTLEN(m);
return 0;
}
static void
omgr_free_buf(void *m, void *arg)
{
if (!m) {
return;
}
os_mbuf_free_chain(m);
}
/*
* Inits a reader the mgmt_ctxt's parser.
**/
static int
omgr_init_reader(struct cbor_decoder_reader *reader, void *m, void *off)
{
struct cbor_mbuf_reader *cmr;
uint16_t *data_off;
if (!reader) {
return MGMT_ERR_EINVAL;
}
cmr = (struct cbor_mbuf_reader *) reader;
data_off = (uint16_t *) off;
cbor_mbuf_reader_init(cmr, m, *data_off);
cbor_parser_init(reader,
0,
&omgr_state.m_ctxt->parser,
&omgr_state.m_ctxt->it);
return 0;
}
/*
* Inits a writer, unused
**/
static int
omgr_init_writer(struct cbor_encoder_writer *writer,
void *m,
void *unused)
{
struct cbor_mbuf_writer *cmw;
if (!writer) {
return MGMT_ERR_EINVAL;
}
cmw = (struct cbor_mbuf_writer *) writer;
cbor_mbuf_writer_init(cmw, m);
return 0;
}
static void
oic_tx_rsp(struct omp_streamer *stmr, int retval, void *unused)
{
oc_send_response((oc_request_t *) omgr_state.request, retval);
}
/**
* Processes a single OMP request and sends the corresponding response(s).
*/
void
omgr_process_request(oc_request_t *req, oc_interface_mask_t mask)
{
struct cbor_mbuf_reader reader;
struct cbor_mbuf_writer writer;
struct os_mbuf *m_req;
uint16_t req_data_off;
int rc = 0;
if (!req) {
rc = MGMT_ERR_EINVAL;
goto done;
}
coap_get_payload(req->packet, &m_req, &req_data_off);
omgr_state = (struct omp_state) {
.omp_stmr = {
.mgmt_stmr = {
.cfg = &g_omgr_cbor_cfg,
.reader = &reader.r,
.writer = &writer.enc,
.cb_arg = &req_data_off,
},
.rsp_encoder = &g_encoder,
.tx_rsp_cb = oic_tx_rsp,
},
.request = req,
};
switch (mask) {
case OC_IF_BASELINE:
oc_process_baseline_interface(req->resource);
/* Fallthrough */
case OC_IF_RW:
rc = omp_impl_process_request_packet(&omgr_state, m_req);
break;
default:
rc = OC_STATUS_BAD_REQUEST;
}
done:
switch (rc) {
case 0:
break;
case MGMT_ERR_ENOMEM:
rc = OC_STATUS_INTERNAL_SERVER_ERROR;
break;
default:
rc = OC_STATUS_BAD_REQUEST;
break;
}
if (rc != 0) {
oc_send_response(req, rc);
}
}
int
omgr_pkg_init(void)
{
/* Ensure this function only gets called by sysinit. */
SYSINIT_ASSERT_ACTIVE();
uint8_t mode;
oc_resource_t *res = NULL;
/*
* net/oic must be initialized before now.
*/
res = oc_new_resource("/omgr", 1, 0);
oc_resource_bind_resource_type(res, MYNEWT_VAL(OICMGR_OIC_RESOURCE_NAME));
mode = OC_IF_RW;
oc_resource_bind_resource_interface(res, mode);
oc_resource_set_default_interface(res, mode);
oc_resource_set_discoverable(res);
oc_resource_set_request_handler(res, OC_PUT, omgr_process_request);
res->properties |= MYNEWT_VAL(OICMGR_TRANS_SECURITY);
oc_add_resource(res);
return 0;
}
int
omgr_extract_req_hdr(oc_request_t *req, struct nmgr_hdr *out_hdr)
{
uint16_t data_off;
struct os_mbuf *m;
int rc;
struct cbor_mbuf_reader reader;
CborParser parser;
CborValue it;
coap_get_payload(req->packet, &m, &data_off);
cbor_mbuf_reader_init(&reader, m, data_off);
cbor_parser_init(&reader.r, 0, &parser,
&it);
rc = omp_read_hdr(&it, out_hdr);
if (rc != 0) {
return MGMT_ERR_EINVAL;
}
return 0;
}