mirror of
https://github.com/espressif/openthread.git
synced 2026-07-29 07:07:47 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
0.5
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
*.a
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.log
|
||||
*.o
|
||||
*.pyc
|
||||
*.trs
|
||||
*~
|
||||
.deps
|
||||
.dirstamp
|
||||
.DS_Store
|
||||
.local-version
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
configure
|
||||
config.log
|
||||
config.status
|
||||
doc/Doxyfile
|
||||
doc/html
|
||||
include/openthread-config.h
|
||||
include/openthread-config.h.in
|
||||
include/stamp-h1
|
||||
libtool
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -0,0 +1,8 @@
|
||||
language: cpp
|
||||
|
||||
before_install:
|
||||
- sudo apt-get install python-pexpect
|
||||
|
||||
script:
|
||||
- ./bootstrap-configure --enable-minimum-set-of-tests
|
||||
- make check
|
||||
@@ -0,0 +1,28 @@
|
||||
Want to contribute? Great! First, read this page (including the small print at the end).
|
||||
|
||||
### Before you contribute
|
||||
Before we can use your code, you must sign the
|
||||
[Google Individual Contributor License Agreement]
|
||||
(https://cla.developers.google.com/about/google-individual)
|
||||
(CLA), which you can do online. The CLA is necessary mainly because you own the
|
||||
copyright to your changes, even after your contribution becomes part of our
|
||||
codebase, so we need your permission to use and distribute your code. We also
|
||||
need to be sure of various other things—for instance that you'll tell us if you
|
||||
know that your code infringes on other people's patents. You don't have to sign
|
||||
the CLA until after you've submitted your code for review and a member has
|
||||
approved it, but you must do it before we can put your code into our codebase.
|
||||
Before you start working on a larger contribution, you should get in touch with
|
||||
us first through the issue tracker with your idea so that we can help out and
|
||||
possibly guide you. Coordinating up front makes it much easier to avoid
|
||||
frustration later on.
|
||||
|
||||
### Code reviews
|
||||
All submissions, including submissions by project members, require review. We
|
||||
use Github pull requests for this purpose.
|
||||
|
||||
### The small print
|
||||
Contributions made by corporations are covered by a different agreement than
|
||||
the one above, the
|
||||
[Software Grant and Corporate Contributor License Agreement]
|
||||
(https://cla.developers.google.com/about/google-corporate).
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2016, Nest Labs, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
AM_MAKEFLAGS = --no-print-directory
|
||||
|
||||
SUBDIRS = \
|
||||
src \
|
||||
third_party \
|
||||
examples \
|
||||
tests \
|
||||
doc \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = \
|
||||
.default-version \
|
||||
bootstrap \
|
||||
bootstrap-configure \
|
||||
$(srcdir)/third_party \
|
||||
$(NULL)
|
||||
|
||||
BUILT_SOURCES = \
|
||||
.local-version \
|
||||
$(NULL)
|
||||
|
||||
dist_doc_DATA = \
|
||||
$(NULL)
|
||||
|
||||
DISTCLEANFILES = \
|
||||
.local-version \
|
||||
$(NULL)
|
||||
|
||||
#
|
||||
# Package version files:
|
||||
#
|
||||
# .default-version - The default package version. This file is ALWAYS checked
|
||||
# in and should always represent the current baseline
|
||||
# version of the package.
|
||||
#
|
||||
# .dist-version - The distributed package version. This file is NEVER
|
||||
# checked in within the upstream repository, is auto-
|
||||
# generated, and is only found in the package distribution.
|
||||
#
|
||||
# .local-version - The current source code controlled package version. This
|
||||
# file is NEVER checked in within the upstream repository,
|
||||
# is auto-generated, and can always be found in both the
|
||||
# build tree and distribution.
|
||||
#
|
||||
# When present, the .local-version file is preferred first, the
|
||||
# .dist-version second, and the .default-version last.
|
||||
#
|
||||
|
||||
VERSION_FILE := $(if $(wildcard $(builddir)/.local-version),$(builddir)/.local-version,$(if $(wildcard $(srcdir)/.dist-version),$(srcdir)/.dist-version,$(srcdir)/.default-version))
|
||||
|
||||
#
|
||||
# Override autotool's default notion of the package version variables.
|
||||
# This ensures that when we create a source distribution that the
|
||||
# version is always the current version, not the version when the
|
||||
# package was bootstrapped.
|
||||
#
|
||||
|
||||
OPENTHREAD_VERSION ?= $(shell cat $(VERSION_FILE) 2> /dev/null)
|
||||
|
||||
PACKAGE_VERSION = $(OPENTHREAD_VERSION)
|
||||
VERSION = $(PACKAGE_VERSION)
|
||||
|
||||
#
|
||||
# check-file-.local-version
|
||||
#
|
||||
# Speculatively regenerate .local-version and check to see if it needs
|
||||
# to be updated.
|
||||
#
|
||||
# If OPENTHREAD_VERSION has been supplied anywhere other than in this file
|
||||
# (which is implicitly the contents of .local-version), then use that;
|
||||
# otherwise, attempt to generate it from the SCM system.
|
||||
#
|
||||
# This is called from $(call check-file,.local-version).
|
||||
#
|
||||
define check-file-.local-version
|
||||
if [ "$(origin OPENTHREAD_VERSION)" != "file" ]; then \
|
||||
echo "$(OPENTHREAD_VERSION)" > "$(2)"; \
|
||||
else \
|
||||
$(abs_top_nlbuild_autotools_dir)/scripts/mkversion \
|
||||
-b "$(OPENTHREAD_VERSION)" "$(top_srcdir)" \
|
||||
> "$(2)"; \
|
||||
fi
|
||||
endef
|
||||
|
||||
#
|
||||
# check-file-.dist-version
|
||||
#
|
||||
# Speculatively regenerate .dist-version and check to see if it needs
|
||||
# to be updated.
|
||||
#
|
||||
# This is called from $(call check-file,.dist-version).
|
||||
#
|
||||
define check-file-.dist-version
|
||||
cat "$(1)" > "$(2)"
|
||||
endef
|
||||
|
||||
#
|
||||
# A convenience target to allow package users to easily rerun the
|
||||
# package configuration according to the current configuration.
|
||||
#
|
||||
.PHONY: reconfigure
|
||||
reconfigure: $(builddir)/config.status
|
||||
$(AM_V_at)$(<) --recheck
|
||||
|
||||
#
|
||||
# Version file regeneration rules.
|
||||
#
|
||||
.PHONY: force
|
||||
|
||||
$(builddir)/.local-version: $(srcdir)/.default-version force
|
||||
|
||||
$(distdir)/.dist-version: $(builddir)/.local-version force
|
||||
|
||||
$(distdir)/.dist-version $(builddir)/.local-version:
|
||||
$(call check-file,$(@F))
|
||||
|
||||
dist distcheck: $(BUILT_SOURCES)
|
||||
|
||||
dist-hook: $(distdir)/.dist-version
|
||||
|
||||
#
|
||||
# Top-level convenience target for making a documentation-only
|
||||
# distribution whose results appear at the top level of the build tree
|
||||
# in the same fashion that the distribution would be for 'make dist'.
|
||||
#
|
||||
|
||||
.PHONY: docdist
|
||||
docdist: $(BUILT_SOURCES)
|
||||
$(MAKE) -C doc docdistdir=$(abs_builddir) $(@)
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,19 @@
|
||||
OpenThread is an open source implementation of the Thread 1.0.1 Final Specification.
|
||||
The Thread 1.0.1 Final Specification is promulgated by the Thread Group. The Thread
|
||||
Group is a non-profit organization formed for the purposes of defining one or
|
||||
more specifications, best practices, reference architectures, implementation
|
||||
guidelines and certification programs to promote the availability of compliant
|
||||
implementations of the Thread protocol. Information on becoming a Member, including
|
||||
information about the benefits thereof, can be found at http://threadgroup.org.
|
||||
|
||||
OpenThread is not affiliated with or endorsed by the Thread Group. Implementation
|
||||
of this OpenThread code does not assure compliance with the Thread 1.0.1 Final
|
||||
Specification and does not convey the right to identify any final product as Thread
|
||||
certified. Members of the Thread Group may hold patents and other intellectual
|
||||
property rights relating to the Thread 1.0.1 Final Specification, ownership and
|
||||
licenses of which are subject to the Thread Group’s IP Policies, and not this license.
|
||||
|
||||
The included copyright to the OpenThread code is subject to the license in the
|
||||
LICENSE file, and all other rights and licenses are expressly reserved.
|
||||
No warranty or assurance is made with respect to additional rights that may be
|
||||
required to implement this code.
|
||||
@@ -0,0 +1,65 @@
|
||||
<a href="https://github.com/openthread/openthread"></a>
|
||||
|
||||
[](https://travis-ci.com/openthread/openthread)
|
||||
|
||||
OpenThread is an open-source implementation of the [Thread](http://threadgroup.org/technology/ourtechnology) networking protocol. With OpenThread, Nest is making the technology used in Nest products more broadly available to accelerate the development of products for the connected home.
|
||||
|
||||
The Thread specification defines an IPv6-based reliable, secure and low-power wireless device-to-device communication protocol for home applications. More information about Thread can be found on [threadgroup.org](http://www.threadgroup.org/).
|
||||
|
||||
## Features
|
||||
- Highly portable: OS and platform agnostic, with a radio abstraction layer
|
||||
- Implements the End Device, Router, Leader & Border Router roles
|
||||
- Small memory footprint
|
||||
|
||||
OpenThread implements all Thread networking layers, including IPv6, 6LoWPAN, IEEE 802.15.4 with MAC security, Mesh Link Establishment, and Mesh Routing.
|
||||
|
||||
|
||||
# Who is behind OpenThread
|
||||
|
||||

|
||||
|
||||
Nest, along with ARM, Atmel, a subsidiary of Microchip Technology, Dialog Semiconductor, Qualcomm Technologies, Inc., a subsidiary of Qualcomm Incorporated and Texas Instruments Incorporated are contributing to the ongoing development of OpenThread.
|
||||
|
||||
|
||||
# Getting Started
|
||||
|
||||
The easiest way to get started is to run the CLI example in `/examples/cli`. See the [CLI example README](examples/cli/README.md) for more details.
|
||||
|
||||
|
||||
## What's included
|
||||
|
||||
In the repo you'll find the following directories and files
|
||||
|
||||
File/Folder | Provides
|
||||
-------|--------
|
||||
doc | Doxygen docs
|
||||
examples | Sample applications demonstrating various parts of OpenThread
|
||||
include | Includes header files for OpenThread API
|
||||
src | The core implementation of the Thread standard
|
||||
tests | Unit and Thread conformance tests
|
||||
third_party | Third-party code used by OpenThread
|
||||
|
||||
|
||||
# Getting Help
|
||||
|
||||
Submit bugs and feature requests to [issue tracker](https://github.com/openthread/openthread/issues). Usage questions? Post questions to [Stack Overflow](http://stackoverflow.com/) using the [[openthread] tag](http://stackoverflow.com/questions/tagged/openthread). We also use Google Groups for discussion and announcements:
|
||||
|
||||
* [openthread-announce](https://groups.google.com/forum/#!forum/openthread-announce) - subscribe for release notes and new updates on OpenThread
|
||||
* [openthread-users](https://groups.google.com/forum/#!forum/openthread-users) - the best place for users to discuss OpenThread and interact with the OpenThread team
|
||||
* [openthread-devel](https://groups.google.com/forum/#!forum/openthread-devel) - team members discuss the on-going development of OpenThread
|
||||
|
||||
|
||||
# Versioning
|
||||
|
||||
OpenThread follows [the Semantic Versioning guidelines](http://semver.org/) for release cycle transparency and to maintain backwards compatibility. OpenThread's versioning is independent of the Thread protocol specification version but will clearly indicate which version of the specification it currently supports.
|
||||
|
||||
|
||||
# Contributing
|
||||
|
||||
See the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information.
|
||||
|
||||
|
||||
# License
|
||||
|
||||
OpenThread is released under the [BSD 3-Clause license](LICENSE).
|
||||
See the [LICENSE](LICENSE) file for more information.
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Description:
|
||||
# This file is a trampoline script to the nlbuild-autotools
|
||||
# bootstrap script and augments it by providing the path to the
|
||||
# nlbuild-autotools repository for this project.
|
||||
#
|
||||
|
||||
# Set this to the relative location of nlbuild-autotools to this script
|
||||
|
||||
nlbuild_autotools_stem="third_party/nlbuild-autotools/repo"
|
||||
|
||||
# Establish some key directories
|
||||
|
||||
srcdir=`dirname ${0}`
|
||||
abs_srcdir=`pwd`
|
||||
abs_top_srcdir="${abs_srcdir}"
|
||||
|
||||
exec ${srcdir}/${nlbuild_autotools_stem}/scripts/bootstrap -I "${abs_top_srcdir}/${nlbuild_autotools_stem}" $*
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2014-2016 Nest Labs Inc. All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Description:
|
||||
# This file implements a script which, when run from a project
|
||||
# build directory (either disparate or colocated with the
|
||||
# source), will attempt to clean the build directory, rebootstrap
|
||||
# the package, and then rerun the configuration script for the
|
||||
# package with the provided arguments.
|
||||
#
|
||||
# This script is particularly useful when you are changing the
|
||||
# configuration script and testing those changes.
|
||||
#
|
||||
|
||||
srcdir=`dirname ${0}`
|
||||
builddir=.
|
||||
|
||||
# Bring the package build back to a pristine state.
|
||||
|
||||
if [ -f config.status ]; then
|
||||
make maintainer-clean
|
||||
fi
|
||||
|
||||
# Change directories to the package source and rebootstrap the package.
|
||||
|
||||
pushd ${srcdir}
|
||||
|
||||
./bootstrap
|
||||
bootstrap_status=$?
|
||||
|
||||
popd
|
||||
|
||||
# If the package was successfully bootstrapped, configure it.
|
||||
|
||||
if [ ${bootstrap_status} -eq 0 ]; then
|
||||
${srcdir}/configure $*
|
||||
else
|
||||
exit ${bootstrap_status}
|
||||
fi
|
||||
+487
@@ -0,0 +1,487 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
#
|
||||
# Declare autoconf version requirements
|
||||
#
|
||||
AC_PREREQ([2.68])
|
||||
|
||||
#
|
||||
# Initialize autoconf for the package
|
||||
#
|
||||
AC_INIT([OPENTHREAD],
|
||||
m4_esyscmd([third_party/nlbuild-autotools/repo/scripts/mkversion -b `cat .default-version` .]),
|
||||
[[email protected]],
|
||||
[openthread],
|
||||
[http://github.com/openthread/openthread])
|
||||
|
||||
# Tell the rest of the build system the absolute path where the
|
||||
# nlbuild-autotools repository is rooted at.
|
||||
|
||||
AC_SUBST(nlbuild_autotools_stem,[third_party/nlbuild-autotools/repo])
|
||||
AC_SUBST(abs_top_nlbuild_autotools_dir,[\${abs_top_srcdir}/\${nlbuild_autotools_stem}])
|
||||
|
||||
#
|
||||
# OPENTHREAD interface current, revision, and age versions.
|
||||
#
|
||||
# Maintainters: Please manage these fields as follows:
|
||||
#
|
||||
# Interfaces removed: CURRENT++, AGE = 0, REVISION = 0
|
||||
# Interfaces added: CURRENT++, AGE++, REVISION = 0
|
||||
# No interfaces changed: REVISION++
|
||||
#
|
||||
#
|
||||
AC_SUBST(LIBOPENTHREAD_VERSION_CURRENT, [0])
|
||||
AC_SUBST(LIBOPENTHREAD_VERSION_AGE, [5])
|
||||
AC_SUBST(LIBOPENTHREAD_VERSION_REVISION, [0])
|
||||
AC_SUBST(LIBOPENTHREAD_VERSION_INFO, [${LIBOPENTHREAD_VERSION_CURRENT}:${LIBOPENTHREAD_VERSION_REVISION}:${LIBOPENTHREAD_VERSION_AGE}])
|
||||
|
||||
#
|
||||
# Check the sanity of the source directory by checking for the
|
||||
# presence of a key watch file
|
||||
#
|
||||
AC_CONFIG_SRCDIR([include/openthread.h])
|
||||
|
||||
#
|
||||
# Tell autoconf where to find auxilliary build tools (e.g. config.guess,
|
||||
# install-sh, missing, etc.)
|
||||
#
|
||||
AC_CONFIG_AUX_DIR([third_party/nlbuild-autotools/repo/autoconf])
|
||||
|
||||
#
|
||||
# Tell autoconf where to find auxilliary M4 macros
|
||||
#
|
||||
AC_CONFIG_MACRO_DIR([third_party/nlbuild-autotools/repo/autoconf/m4])
|
||||
|
||||
#
|
||||
# Tell autoconf what file the package is using to aggregate C preprocessor
|
||||
# defines.
|
||||
#
|
||||
AC_CONFIG_HEADERS([include/openthread-config.h])
|
||||
|
||||
#
|
||||
# Figure out what the canonical build, host and target tuples are.
|
||||
#
|
||||
AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
#
|
||||
# Mac OS X / Darwin ends up putting some versioning cruft on the end of its
|
||||
# tuple that we don't care about in this script. Create "clean" variables
|
||||
# devoid of it.
|
||||
#
|
||||
|
||||
NL_FILTERED_CANONICAL_BUILD
|
||||
NL_FILTERED_CANONICAL_HOST
|
||||
NL_FILTERED_CANONICAL_TARGET
|
||||
|
||||
#
|
||||
# Configure automake with the desired options, indicating that this is not
|
||||
# a native GNU package, that we want "silent" build rules, and that we want
|
||||
# objects built in the same subdirectory as their source rather than collapsed
|
||||
# together at the top-level directory.
|
||||
#
|
||||
# Disable silent build rules by either passing --disable-silent-rules to
|
||||
# configure or passing V=1 to make
|
||||
#
|
||||
AM_INIT_AUTOMAKE([1.14 foreign silent-rules subdir-objects tar-pax])
|
||||
|
||||
#
|
||||
# Silent build rules requires at least automake-1.11. Employ
|
||||
# techniques for not breaking earlier versions of automake.
|
||||
#
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
#
|
||||
# Enable maintainer mode to prevent the package from constantly trying
|
||||
# to rebuild configure, Makefile.in, etc. Rebuilding such files rarely,
|
||||
# if ever, needs to be done "in the field".
|
||||
#
|
||||
# Use the included 'bootstrap' script instead when necessary.
|
||||
#
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
#
|
||||
# Check for target
|
||||
#
|
||||
|
||||
case ${target_os} in
|
||||
|
||||
*darwin*)
|
||||
OPENTHREAD_TARGET=darwin
|
||||
OPENTHREAD_TARGET_DEFINES="-DOPENTHREAD_TARGET_DARWIN"
|
||||
;;
|
||||
|
||||
*linux*)
|
||||
OPENTHREAD_TARGET=linux
|
||||
OPENTHREAD_TARGET_DEFINES="-DOPENTHREAD_TARGET_LINUX"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
AC_SUBST(OPENTHREAD_TARGET_DARWIN)
|
||||
AM_CONDITIONAL([OPENTHREAD_TARGET_DARWIN], [test "${OPENTHREAD_TARGET}" = "darwin"])
|
||||
|
||||
AC_SUBST(OPENTHREAD_TARGET_LINUX)
|
||||
AM_CONDITIONAL([OPENTHREAD_TARGET_LINUX], [test "${OPENTHREAD_TARGET}" = "linux"])
|
||||
|
||||
AC_SUBST(OPENTHREAD_TARGET_DEFINES)
|
||||
|
||||
#
|
||||
# Checks for build host programs
|
||||
#
|
||||
|
||||
# If we are cross-compiling and we are on an embedded target that
|
||||
# doesn't support independent, standalone executables, then all
|
||||
# compiler tests that attempt to create an executable will fail. In
|
||||
# such circumstances, set AC_NO_EXECUTABLES (see http://sourceware.org/
|
||||
# ml/newlib/2006/msg00353.html).
|
||||
|
||||
AC_MSG_CHECKING([whether to disable executable checking])
|
||||
if test "$cross_compiling" = yes; then
|
||||
AC_NO_EXECUTABLES
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
# Passing -Werror to GCC-based or -compatible compilers breaks some
|
||||
# autoconf tests (see
|
||||
# http://lists.gnu.org/archive/html/autoconf-patches/2008-09/msg00014.html).
|
||||
#
|
||||
# If -Werror has been passed transform it into -Wno-error. We'll
|
||||
# transform it back later with NL_RESTORE_WERROR.
|
||||
|
||||
NL_SAVE_WERROR
|
||||
|
||||
# Check for compilers.
|
||||
#
|
||||
# These should be checked BEFORE we check for and, implicitly,
|
||||
# initialize libtool such that libtool knows what languages it has to
|
||||
# work with.
|
||||
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CPP_WERROR
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_C_O
|
||||
|
||||
AC_PROG_CXXCPP
|
||||
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CXX_C_O
|
||||
|
||||
# Check for other compiler toolchain tools.
|
||||
|
||||
AC_CHECK_TOOL(AR, ar)
|
||||
AC_CHECK_TOOL(RANLIB, ranlib)
|
||||
AC_CHECK_TOOL(OBJCOPY, objcopy)
|
||||
AC_CHECK_TOOL(STRIP, strip)
|
||||
|
||||
# Check for other host tools.
|
||||
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
|
||||
#
|
||||
# Checks for specific compiler characteristics
|
||||
#
|
||||
|
||||
#
|
||||
# Common compiler flags we would like to have.
|
||||
#
|
||||
# -Wall CC, CXX
|
||||
#
|
||||
|
||||
PROSPECTIVE_CFLAGS="-Wall"
|
||||
PROSPECTIVE_CXXFLAGS=""
|
||||
|
||||
AX_CHECK_COMPILER_OPTIONS([C], ${PROSPECTIVE_CFLAGS})
|
||||
AX_CHECK_COMPILER_OPTIONS([C++], ${PROSPECTIVE_CFLAGS} ${PROSPECTIVE_CXXFLAGS})
|
||||
|
||||
# Check for and initialize libtool
|
||||
|
||||
LT_INIT
|
||||
|
||||
#
|
||||
# Debug instances
|
||||
#
|
||||
AC_MSG_NOTICE([checking whether to build debug instances])
|
||||
|
||||
# Debug
|
||||
|
||||
NL_ENABLE_DEBUG([no])
|
||||
|
||||
AM_CONDITIONAL([OPENTHREAD_BUILD_DEBUG], [test "${nl_cv_build_debug}" = "yes"])
|
||||
|
||||
#
|
||||
# Code coverage and compiler optimization
|
||||
#
|
||||
|
||||
# Coverage
|
||||
|
||||
NL_ENABLE_COVERAGE([no])
|
||||
|
||||
AM_CONDITIONAL([OPENTHREAD_BUILD_COVERAGE], [test "${nl_cv_build_coverage}" = "yes"])
|
||||
|
||||
NL_ENABLE_COVERAGE_REPORTS([auto])
|
||||
|
||||
AM_CONDITIONAL([OPENTHREAD_BUILD_COVERAGE_REPORTS], [test "${nl_cv_build_coverage_reports}" = "yes"])
|
||||
|
||||
# Optimization
|
||||
|
||||
NL_ENABLE_OPTIMIZATION([yes])
|
||||
|
||||
AM_CONDITIONAL([OPENTHREAD_BUILD_OPTIMIZED], [test "${nl_cv_build_optimized}" = "yes"])
|
||||
|
||||
#
|
||||
# Tests
|
||||
#
|
||||
AC_MSG_NOTICE([checking whether to build tests])
|
||||
|
||||
# Tests
|
||||
|
||||
NL_ENABLE_TESTS([yes])
|
||||
|
||||
AM_CONDITIONAL([OPENTHREAD_BUILD_TESTS], [test "${nl_cv_build_tests}" = "yes"])
|
||||
|
||||
# Check whether to run only the minimum set of tests.
|
||||
|
||||
AC_MSG_CHECKING([whether to run only the minimum set of tests.])
|
||||
AC_ARG_ENABLE(minimum-set-of-tests,
|
||||
[AS_HELP_STRING([--enable-minimum-set-of-tests],[Run only the most essential tests. @<:@default=no@:>@.])],
|
||||
[
|
||||
case "${enableval}" in
|
||||
|
||||
no|yes)
|
||||
enable_minimum_set_of_tests=${enableval}
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_ERROR([Invalid value ${enableval} for --enable-minimum-set-of-tests])
|
||||
;;
|
||||
|
||||
esac
|
||||
],
|
||||
[enable_minimum_set_of_tests=no])
|
||||
AC_MSG_RESULT(${enable_minimum_set_of_tests})
|
||||
|
||||
AM_CONDITIONAL([OPENTHREAD_WITH_MINIMUM_SET_OF_TESTS], [test "${enable_minimum_set_of_tests}" = "yes"])
|
||||
|
||||
if test "${enable_minimum_set_of_tests}" = "yes"; then
|
||||
if test "${nl_cv_build_coverage}" = "yes"; then
|
||||
AC_MSG_ERROR(["Do not run code coverage only with the minimum set of tests."])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for Python and Python libraries used in the tests
|
||||
if test "${nl_cv_build_tests}" = "yes"; then
|
||||
AC_MSG_CHECKING([checking for Python and Python libraries used in tests.])
|
||||
|
||||
# Check for Python
|
||||
python --version 2> /dev/null
|
||||
if test $? != 0; then
|
||||
AC_MSG_ERROR(["Cannot run tests: missing Python."])
|
||||
fi
|
||||
|
||||
# Check for Python pexpect library
|
||||
python -c 'import pexpect' 2> /dev/null
|
||||
if test $? != 0; then
|
||||
AC_MSG_ERROR(["Cannot run tests: missing Python pexpect library."])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([ok])
|
||||
fi
|
||||
|
||||
#
|
||||
# Tools
|
||||
#
|
||||
|
||||
AC_MSG_CHECKING([whether to build tools])
|
||||
AC_ARG_ENABLE(tools,
|
||||
[AS_HELP_STRING([--disable-tools],[Disable building of tools @<:@default=no@:>@.])],
|
||||
[
|
||||
case "${enableval}" in
|
||||
|
||||
no|yes)
|
||||
build_tools=${enableval}
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_ERROR([Invalid value ${enableval} for --enable-tools])
|
||||
;;
|
||||
|
||||
esac
|
||||
],
|
||||
[build_tools=yes])
|
||||
AC_MSG_RESULT(${build_tools})
|
||||
AM_CONDITIONAL([OPENTHREAD_BUILD_TOOLS], [test "${build_tools}" = "yes"])
|
||||
|
||||
#
|
||||
# Documentation
|
||||
#
|
||||
|
||||
# Determine whether or not documentation (via Doxygen) should be built
|
||||
# or not, with 'auto' as the default and establish a default support
|
||||
# value for GraphViz 'dot' support.
|
||||
|
||||
NL_ENABLE_DOCS([auto],[NO])
|
||||
|
||||
AM_CONDITIONAL(OPENTHREAD_BUILD_DOCS, [test "${nl_cv_build_docs}" = "yes"])
|
||||
|
||||
#
|
||||
# Checks for libraries and packages.
|
||||
#
|
||||
# At minimum, the following packages are optional, depending on
|
||||
# configuration:
|
||||
#
|
||||
# * TBD
|
||||
#
|
||||
AC_MSG_NOTICE([checking required package dependencies])
|
||||
|
||||
# NL_WITH_PACKAGE(...)
|
||||
|
||||
#
|
||||
# Check for headers
|
||||
#
|
||||
AC_HEADER_STDBOOL
|
||||
AC_HEADER_STDC
|
||||
|
||||
AC_CHECK_HEADERS([stdint.h])
|
||||
AC_CHECK_HEADERS([string.h])
|
||||
|
||||
#
|
||||
# Check for types and structures
|
||||
#
|
||||
AC_TYPE_INT8_T
|
||||
AC_TYPE_INT16_T
|
||||
AC_TYPE_INT32_T
|
||||
AC_TYPE_INT64_T
|
||||
AC_TYPE_UINT8_T
|
||||
AC_TYPE_UINT16_T
|
||||
AC_TYPE_UINT32_T
|
||||
AC_TYPE_UINT64_T
|
||||
|
||||
#
|
||||
# Checks for library functions
|
||||
#
|
||||
|
||||
if test "${ac_no_link}" != "yes"; then
|
||||
AC_CHECK_FUNCS([memcpy])
|
||||
fi
|
||||
|
||||
# Add any code coverage CPPFLAGS and LDFLAGS
|
||||
|
||||
CPPFLAGS="${CPPFLAGS} ${NL_COVERAGE_CPPFLAGS}"
|
||||
LDFLAGS="${LDFLAGS} ${NL_COVERAGE_LDFLAGS}"
|
||||
|
||||
# At this point, we can restore the compiler flags to whatever the
|
||||
# user passed in, now that we're clear of an -Werror issues by
|
||||
# transforming -Wno-error back to -Werror.
|
||||
|
||||
NL_RESTORE_WERROR
|
||||
|
||||
#
|
||||
# Identify the various makefiles and auto-generated files for the package
|
||||
#
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
src/cli/Makefile
|
||||
src/core/Makefile
|
||||
third_party/Makefile
|
||||
third_party/mbedtls/Makefile
|
||||
examples/Makefile
|
||||
examples/platform/Makefile
|
||||
examples/platform/posix/Makefile
|
||||
examples/cli/Makefile
|
||||
tests/Makefile
|
||||
tests/scripts/Makefile
|
||||
tests/unit/Makefile
|
||||
doc/Makefile
|
||||
])
|
||||
|
||||
#
|
||||
# Generate the auto-generated files for the package
|
||||
#
|
||||
AC_OUTPUT
|
||||
|
||||
#
|
||||
# Summarize the package configuration
|
||||
#
|
||||
|
||||
AC_MSG_NOTICE([
|
||||
|
||||
Configuration Summary
|
||||
---------------------
|
||||
Package : ${PACKAGE_NAME}
|
||||
Version : ${PACKAGE_VERSION}
|
||||
Interface : ${LIBOPENTHREAD_VERSION_INFO//:/.}
|
||||
Build system : ${build}
|
||||
Host system : ${host}
|
||||
Target system : ${target}
|
||||
Target architecture : ${target_cpu}
|
||||
Target OS : ${target_os}
|
||||
Cross compiling : ${cross_compiling}
|
||||
Build shared libraries : ${enable_shared}
|
||||
Build static libraries : ${enable_static}
|
||||
Build debug libraries : ${nl_cv_build_debug}
|
||||
Build optimized libraries : ${nl_cv_build_optimized}
|
||||
Build coverage libraries : ${nl_cv_build_coverage}
|
||||
Build coverage reports : ${nl_cv_build_coverage_reports}
|
||||
Lcov : ${LCOV:--}
|
||||
Genhtml : ${GENHTML:--}
|
||||
Build tests : ${nl_cv_build_tests}
|
||||
Build tools : ${build_tools}
|
||||
Minimum set of tests : ${enable_minimum_set_of_tests}
|
||||
Prefix : ${prefix}
|
||||
Documentation support : ${nl_cv_build_docs}
|
||||
Doxygen : ${DOXYGEN:--}
|
||||
GraphViz dot : ${DOT:--}
|
||||
C Preprocessor : ${CPP}
|
||||
C Compiler : ${CC}
|
||||
C++ Preprocessor : ${CXXCPP}
|
||||
C++ Compiler : ${CXX}
|
||||
Archiver : ${AR}
|
||||
Archive Indexer : ${RANLIB}
|
||||
Symbol Stripper : ${STRIP}
|
||||
Object Copier : ${OBJCOPY}
|
||||
C Preprocessor flags : ${CPPFLAGS:--}
|
||||
C Compile flags : ${CFLAGS:--}
|
||||
C++ Compile flags : ${CXXFLAGS:--}
|
||||
Link flags : ${LDFLAGS:--}
|
||||
Link libraries : ${LIBS}
|
||||
|
||||
])
|
||||
|
||||
|
||||
|
||||
+2383
File diff suppressed because it is too large
Load Diff
+108
@@ -0,0 +1,108 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(srcdir)/Doxyfile.in \
|
||||
$(srcdir)/index.dox \
|
||||
$(NULL)
|
||||
|
||||
#
|
||||
# Override autotool's default notion of the package version variables.
|
||||
# This ensures that when we create a doc distribution that the
|
||||
# version is always the current version, not the version when the
|
||||
# package was bootstrapped.
|
||||
#
|
||||
PACKAGE_VERSION = $(shell cat $(top_builddir)/.local-version)
|
||||
VERSION = $(PACKAGE_VERSION)
|
||||
|
||||
|
||||
docdistdir ?= .
|
||||
|
||||
openthread_docdist_alias = \
|
||||
$(PACKAGE_TARNAME)-docs
|
||||
|
||||
openthread_docdist_name = \
|
||||
$(openthread_docdist_alias)-$(VERSION)
|
||||
|
||||
openthread_docdist_archive = \
|
||||
$(docdistdir)/$(openthread_docdist_name).tar.gz
|
||||
|
||||
CLEANFILES = \
|
||||
Doxyfile \
|
||||
$(openthread_docdist_archive) \
|
||||
$(NULL)
|
||||
|
||||
if OPENTHREAD_BUILD_DOCS
|
||||
|
||||
all-local: html/index.html
|
||||
|
||||
#
|
||||
# We choose to manually transform Doxyfile.in into Doxyfile here in
|
||||
# the makefile rather than in the configure script so that we can take
|
||||
# advantage of live, at build time (rather than at configure time),
|
||||
# updating of the package version number.
|
||||
#
|
||||
|
||||
Doxyfile: $(srcdir)/Doxyfile.in Makefile
|
||||
$(AM_V_GEN)$(SED) \
|
||||
-e "s,\@DOXYGEN_USE_DOT\@,$(DOXYGEN_USE_DOT),g" \
|
||||
-e "s,\@PACKAGE_NAME\@,$(PACKAGE_NAME),g" \
|
||||
-e "s,\@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g" \
|
||||
-e "s,\@PERL\@,$(PERL),g" \
|
||||
-e "s,\@abs_builddir\@,$(abs_builddir),g" \
|
||||
-e "s,\@abs_srcdir\@,$(abs_srcdir),g" \
|
||||
-e "s,\@abs_top_builddir\@,$(abs_top_builddir),g" \
|
||||
-e "s,\@abs_top_srcdir\@,$(abs_top_srcdir),g" \
|
||||
< "$(srcdir)/Doxyfile.in" > "$(@)"
|
||||
|
||||
html/index.html: Doxyfile
|
||||
$(AM_V_GEN)$(DOXYGEN) $(<)
|
||||
|
||||
#
|
||||
# Addition rules and commands to create a documentation-only
|
||||
# distribution of openthread
|
||||
#
|
||||
|
||||
$(openthread_docdist_name): html/index.html
|
||||
$(AM_V_at)rm -f -r $(@)
|
||||
$(call create-directory)
|
||||
$(AM_V_at)cp -R html $(@)
|
||||
|
||||
$(openthread_docdist_archive): $(openthread_docdist_name)
|
||||
$(AM_V_at)echo " TAR $(@)"
|
||||
$(AM_V_at)tardir="$(<)" && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c > "$(@)" && rm -rf $(<)
|
||||
|
||||
docdist $(openthread_docdist_alias): $(openthread_docdist_archive)
|
||||
|
||||
clean-local:
|
||||
$(AM_V_at)rm -f -r html
|
||||
|
||||
endif # OPENTHREAD_BUILD_DOCS
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,55 @@
|
||||
<!-- HTML header for doxygen 1.8.9.1-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
<body>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
||||
<!--BEGIN TITLEAREA-->
|
||||
<div id="titlearea">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
<!--BEGIN PROJECT_NAME-->
|
||||
<td style="padding-left: 0.5em;">
|
||||
<div id="projectname">
|
||||
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
|
||||
</div>
|
||||
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
||||
</td>
|
||||
<!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME-->
|
||||
<!--BEGIN PROJECT_BRIEF-->
|
||||
<td style="padding-left: 0.5em;">
|
||||
<div id="projectbrief">$projectbrief</div>
|
||||
</td>
|
||||
<!--END PROJECT_BRIEF-->
|
||||
<!--END !PROJECT_NAME-->
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
<td>$searchbox</td>
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--END TITLEAREA-->
|
||||
<!-- end header part -->
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
# Always package (e.g. for 'make dist') these subdirectories.
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
platform \
|
||||
cli \
|
||||
$(NULL)
|
||||
|
||||
# Always build (e.g. for 'make all') these subdirectories.
|
||||
|
||||
SUBDIRS = \
|
||||
platform \
|
||||
cli \
|
||||
$(NULL)
|
||||
|
||||
all:
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
bin_PROGRAMS = soc
|
||||
|
||||
soc_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/core \
|
||||
-I$(top_srcdir)/examples \
|
||||
-I$(top_srcdir)/examples/platform/posix \
|
||||
$(OPENTHREAD_TARGET_DEFINES) \
|
||||
$(NULL)
|
||||
|
||||
soc_LDADD = \
|
||||
$(top_srcdir)/src/core/libopenthread.a \
|
||||
$(top_srcdir)/src/cli/libopenthread-cli.a \
|
||||
$(top_srcdir)/examples/platform/posix/libopenthread-posix.a \
|
||||
$(top_srcdir)/third_party/mbedtls/libmbedcrypto.a \
|
||||
-lpthread \
|
||||
$(NULL)
|
||||
|
||||
soc_SOURCES = \
|
||||
main.cpp \
|
||||
$(NULL)
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,85 @@
|
||||
# OpenThread CLI Example
|
||||
|
||||
This example application demonstrates a minimal OpenThread application
|
||||
that exposes the OpenThread configuration and management interfaces
|
||||
via a basic command-line interface. The steps below take you through
|
||||
the minimal steps required to ping one (emulated) Thread device from
|
||||
another (emulated) Thread device.
|
||||
|
||||
## 1. Build
|
||||
|
||||
```bash
|
||||
$ cd openthread
|
||||
$ ./bootstrap-configure
|
||||
$ make
|
||||
```
|
||||
|
||||
## 2. Start Node 1
|
||||
|
||||
Spawn the process:
|
||||
|
||||
```bash
|
||||
$ cd openthread/examples/cli
|
||||
$ ./soc --nodeid=1 -S
|
||||
```
|
||||
|
||||
Start OpenThread:
|
||||
|
||||
```bash
|
||||
$ start
|
||||
Done
|
||||
```
|
||||
|
||||
Wait a few seconds and verify that the device has become a Thread Leader:
|
||||
|
||||
```bash
|
||||
$ state
|
||||
leader
|
||||
Done
|
||||
```
|
||||
|
||||
View IPv6 addresses assigned to Node 1's Thread interface:
|
||||
|
||||
```bash
|
||||
$ ipaddr
|
||||
fdde:ad00:beef:0:0:ff:fe00:0
|
||||
fe80:0:0:0:0:ff:fe00:0
|
||||
fdde:ad00:beef:0:558:f56b:d688:799
|
||||
fe80:0:0:0:f3d9:2a82:c8d8:fe43
|
||||
Done
|
||||
```
|
||||
|
||||
## 2. Start Node 2
|
||||
|
||||
Spawn the process:
|
||||
|
||||
```bash
|
||||
$ cd openthread/examples/cli
|
||||
$ ./soc --nodeid=2 -S
|
||||
```
|
||||
|
||||
Start OpenThread:
|
||||
|
||||
```bash
|
||||
$ start
|
||||
Done
|
||||
```
|
||||
|
||||
Wait a few seconds and verify that the device has become a Thread Router:
|
||||
|
||||
```bash
|
||||
$ state
|
||||
leader
|
||||
Done
|
||||
```
|
||||
|
||||
## 3. Ping Node 1 from Node 2
|
||||
|
||||
```bash
|
||||
$ ping fdde:ad00:beef:0:558:f56b:d688:799
|
||||
16 bytes from fdde:ad00:beef:0:558:f56b:d688:799: icmp_seq=1 hlim=64
|
||||
```
|
||||
|
||||
## 4. Ready for More?
|
||||
|
||||
See the [OpenThread CLI Reference README.md](../../src/cli/README.md) to explore more.
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <platform/posix/cmdline.h>
|
||||
|
||||
#include <openthread.h>
|
||||
#include <cli/cli_serial.hpp>
|
||||
#include <platform/atomic.h>
|
||||
#include <platform.h>
|
||||
|
||||
struct gengetopt_args_info args_info;
|
||||
|
||||
Thread::Cli::Serial sCliServer;
|
||||
|
||||
void otSignalTaskletPending(void)
|
||||
{
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint32_t atomic_state;
|
||||
|
||||
memset(&args_info, 0, sizeof(args_info));
|
||||
|
||||
if (cmdline_parser(argc, argv, &args_info) != 0)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hwAlarmInit();
|
||||
hwRadioInit();
|
||||
hwRandomInit();
|
||||
|
||||
otInit();
|
||||
sCliServer.Start();
|
||||
|
||||
while (1)
|
||||
{
|
||||
otProcessNextTasklet();
|
||||
|
||||
atomic_state = otPlatAtomicBegin();
|
||||
|
||||
if (!otAreTaskletsPending())
|
||||
{
|
||||
hwSleep();
|
||||
}
|
||||
|
||||
otPlatAtomicEnd(atomic_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
# Always package (e.g. for 'make dist') these subdirectories.
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
posix \
|
||||
$(NULL)
|
||||
|
||||
# Always build (e.g. for 'make all') these subdirectories.
|
||||
|
||||
SUBDIRS = \
|
||||
posix \
|
||||
$(NULL)
|
||||
|
||||
all:
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
lib_LIBRARIES = libopenthread-posix.a
|
||||
|
||||
libopenthread_posix_a_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/core \
|
||||
-I$(top_srcdir)/examples \
|
||||
-I$(top_srcdir)/examples/platform/posix \
|
||||
$(OPENTHREAD_TARGET_DEFINES) \
|
||||
-D_BSD_SOURCE \
|
||||
-D_GNU_SOURCE \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_posix_a_CXXFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/core \
|
||||
-I$(top_srcdir)/examplse \
|
||||
-I$(top_srcdir)/examples/platform/posix \
|
||||
$(OPENTHREAD_TARGET_DEFINES) \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_posix_a_SOURCES = \
|
||||
alarm.c \
|
||||
atomic.c \
|
||||
cmdline.c \
|
||||
logging.c \
|
||||
radio.cpp \
|
||||
random.c \
|
||||
serial.c \
|
||||
$(NULL)
|
||||
|
||||
include_HEADERS = \
|
||||
$(NULL)
|
||||
|
||||
install-headers: install-includeHEADERS
|
||||
|
||||
if OPENTHREAD_BUILD_COVERAGE
|
||||
CLEANFILES = $(wildcard *.gcda *.gcno)
|
||||
endif # OPENTHREAD_BUILD_COVERAGE
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <platform/alarm.h>
|
||||
|
||||
static void *alarm_thread(void *arg);
|
||||
|
||||
static bool s_is_running = false;
|
||||
static uint32_t s_alarm = 0;
|
||||
static struct timeval s_start;
|
||||
|
||||
static pthread_t s_thread;
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
void hwAlarmInit(void)
|
||||
{
|
||||
gettimeofday(&s_start, NULL);
|
||||
pthread_create(&s_thread, NULL, alarm_thread, NULL);
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmGetNow(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
timersub(&tv, &s_start, &tv);
|
||||
|
||||
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
||||
}
|
||||
|
||||
void otPlatAlarmStartAt(uint32_t t0, uint32_t dt)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_alarm = t0 + dt;
|
||||
s_is_running = true;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_cond_signal(&s_cond);
|
||||
}
|
||||
|
||||
void otPlatAlarmStop(void)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_is_running = false;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
|
||||
void *alarm_thread(void *arg)
|
||||
{
|
||||
int32_t remaining;
|
||||
struct timeval tva;
|
||||
struct timeval tvb;
|
||||
struct timespec ts;
|
||||
|
||||
while (1)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
if (!s_is_running)
|
||||
{
|
||||
// alarm is not running, wait indefinitely
|
||||
pthread_cond_wait(&s_cond, &s_mutex);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// alarm is running
|
||||
remaining = s_alarm - otPlatAlarmGetNow();
|
||||
|
||||
if (remaining > 0)
|
||||
{
|
||||
// alarm has not passed, wait
|
||||
gettimeofday(&tva, NULL);
|
||||
tvb.tv_sec = remaining / 1000;
|
||||
tvb.tv_usec = (remaining % 1000) * 1000;
|
||||
timeradd(&tva, &tvb, &tva);
|
||||
|
||||
ts.tv_sec = tva.tv_sec;
|
||||
ts.tv_nsec = tva.tv_usec * 1000;
|
||||
|
||||
pthread_cond_timedwait(&s_cond, &s_mutex, &ts);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// alarm has passed, signal
|
||||
s_is_running = false;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
otPlatAlarmSignalFired();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <platform/atomic.h>
|
||||
#include <platform/posix/platform.h>
|
||||
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
uint32_t otPlatAtomicBegin(void)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void otPlatAtomicEnd(uint32_t state)
|
||||
{
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_cond_signal(&s_cond);
|
||||
}
|
||||
|
||||
void hwSleep(void)
|
||||
{
|
||||
pthread_cond_wait(&s_cond, &s_mutex);
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
File autogenerated by gengetopt version 2.22.6
|
||||
generated with the following command:
|
||||
gengetopt -i cmdline.ggo
|
||||
|
||||
The developers of gengetopt consider the fixed text that goes in all
|
||||
gengetopt output files to be in the public domain:
|
||||
we make no copyright claims on it.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef FIX_UNUSED
|
||||
#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
|
||||
#endif
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
const char *gengetopt_args_info_purpose = "";
|
||||
|
||||
const char *gengetopt_args_info_usage = "Usage: thread [OPTIONS]...";
|
||||
|
||||
const char *gengetopt_args_info_versiontext = "";
|
||||
|
||||
const char *gengetopt_args_info_description = "";
|
||||
|
||||
const char *gengetopt_args_info_help[] = {
|
||||
" -h, --help Print help and exit",
|
||||
" -V, --version Print version and exit",
|
||||
" --nodeid=INT Node ID",
|
||||
" -S, --stdserial Use stdin/stdout for serial (default=on)",
|
||||
0
|
||||
};
|
||||
|
||||
typedef enum {ARG_NO
|
||||
, ARG_FLAG
|
||||
, ARG_INT
|
||||
} cmdline_parser_arg_type;
|
||||
|
||||
static
|
||||
void clear_given (struct gengetopt_args_info *args_info);
|
||||
static
|
||||
void clear_args (struct gengetopt_args_info *args_info);
|
||||
|
||||
static int
|
||||
cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params, const char *additional_error);
|
||||
|
||||
static int
|
||||
cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
|
||||
|
||||
static char *
|
||||
gengetopt_strdup (const char *s);
|
||||
|
||||
static
|
||||
void clear_given (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
args_info->help_given = 0 ;
|
||||
args_info->version_given = 0 ;
|
||||
args_info->nodeid_given = 0 ;
|
||||
args_info->stdserial_given = 0 ;
|
||||
}
|
||||
|
||||
static
|
||||
void clear_args (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
FIX_UNUSED (args_info);
|
||||
args_info->nodeid_orig = NULL;
|
||||
args_info->stdserial_flag = 1;
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
void init_args_info(struct gengetopt_args_info *args_info)
|
||||
{
|
||||
|
||||
|
||||
args_info->help_help = gengetopt_args_info_help[0] ;
|
||||
args_info->version_help = gengetopt_args_info_help[1] ;
|
||||
args_info->nodeid_help = gengetopt_args_info_help[2] ;
|
||||
args_info->stdserial_help = gengetopt_args_info_help[3] ;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_print_version (void)
|
||||
{
|
||||
printf ("%s %s\n",
|
||||
(strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),
|
||||
CMDLINE_PARSER_VERSION);
|
||||
|
||||
if (strlen(gengetopt_args_info_versiontext) > 0)
|
||||
printf("\n%s\n", gengetopt_args_info_versiontext);
|
||||
}
|
||||
|
||||
static void print_help_common(void) {
|
||||
cmdline_parser_print_version ();
|
||||
|
||||
if (strlen(gengetopt_args_info_purpose) > 0)
|
||||
printf("\n%s\n", gengetopt_args_info_purpose);
|
||||
|
||||
if (strlen(gengetopt_args_info_usage) > 0)
|
||||
printf("\n%s\n", gengetopt_args_info_usage);
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (strlen(gengetopt_args_info_description) > 0)
|
||||
printf("%s\n\n", gengetopt_args_info_description);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_print_help (void)
|
||||
{
|
||||
int i = 0;
|
||||
print_help_common();
|
||||
while (gengetopt_args_info_help[i])
|
||||
printf("%s\n", gengetopt_args_info_help[i++]);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_init (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
clear_given (args_info);
|
||||
clear_args (args_info);
|
||||
init_args_info (args_info);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_params_init(struct cmdline_parser_params *params)
|
||||
{
|
||||
if (params)
|
||||
{
|
||||
params->override = 0;
|
||||
params->initialize = 1;
|
||||
params->check_required = 1;
|
||||
params->check_ambiguity = 0;
|
||||
params->print_errors = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct cmdline_parser_params *
|
||||
cmdline_parser_params_create(void)
|
||||
{
|
||||
struct cmdline_parser_params *params =
|
||||
(struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
|
||||
cmdline_parser_params_init(params);
|
||||
return params;
|
||||
}
|
||||
|
||||
static void
|
||||
free_string_field (char **s)
|
||||
{
|
||||
if (*s)
|
||||
{
|
||||
free (*s);
|
||||
*s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmdline_parser_release (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
|
||||
free_string_field (&(args_info->nodeid_orig));
|
||||
|
||||
|
||||
|
||||
clear_given (args_info);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
|
||||
{
|
||||
FIX_UNUSED (values);
|
||||
if (arg) {
|
||||
fprintf(outfile, "%s=\"%s\"\n", opt, arg);
|
||||
} else {
|
||||
fprintf(outfile, "%s\n", opt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (args_info->help_given)
|
||||
write_into_file(outfile, "help", 0, 0 );
|
||||
if (args_info->version_given)
|
||||
write_into_file(outfile, "version", 0, 0 );
|
||||
if (args_info->nodeid_given)
|
||||
write_into_file(outfile, "nodeid", args_info->nodeid_orig, 0);
|
||||
if (args_info->stdserial_given)
|
||||
write_into_file(outfile, "stdserial", 0, 0 );
|
||||
|
||||
|
||||
i = EXIT_SUCCESS;
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
FILE *outfile;
|
||||
int i = 0;
|
||||
|
||||
outfile = fopen(filename, "w");
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
i = cmdline_parser_dump(outfile, args_info);
|
||||
fclose (outfile);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_free (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
cmdline_parser_release (args_info);
|
||||
}
|
||||
|
||||
/** @brief replacement of strdup, which is not standard */
|
||||
char *
|
||||
gengetopt_strdup (const char *s)
|
||||
{
|
||||
char *result = 0;
|
||||
if (!s)
|
||||
return result;
|
||||
|
||||
result = (char*)malloc(strlen(s) + 1);
|
||||
if (result == (char*)0)
|
||||
return (char*)0;
|
||||
strcpy(result, s);
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params)
|
||||
{
|
||||
int result;
|
||||
result = cmdline_parser_internal (argc, argv, args_info, params, 0);
|
||||
|
||||
if (result == EXIT_FAILURE)
|
||||
{
|
||||
cmdline_parser_free (args_info);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
|
||||
{
|
||||
int result;
|
||||
struct cmdline_parser_params params;
|
||||
|
||||
params.override = override;
|
||||
params.initialize = initialize;
|
||||
params.check_required = check_required;
|
||||
params.check_ambiguity = 0;
|
||||
params.print_errors = 1;
|
||||
|
||||
result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0);
|
||||
|
||||
if (result == EXIT_FAILURE)
|
||||
{
|
||||
cmdline_parser_free (args_info);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
|
||||
{
|
||||
int result = EXIT_SUCCESS;
|
||||
|
||||
if (cmdline_parser_required2(args_info, prog_name, 0) > 0)
|
||||
result = EXIT_FAILURE;
|
||||
|
||||
if (result == EXIT_FAILURE)
|
||||
{
|
||||
cmdline_parser_free (args_info);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error)
|
||||
{
|
||||
int error_occurred = 0;
|
||||
FIX_UNUSED (additional_error);
|
||||
|
||||
/* checks for required options */
|
||||
if (! args_info->nodeid_given)
|
||||
{
|
||||
fprintf (stderr, "%s: '--nodeid' option required%s\n", prog_name, (additional_error ? additional_error : ""));
|
||||
error_occurred = 1;
|
||||
}
|
||||
|
||||
|
||||
/* checks for dependences among options */
|
||||
|
||||
return error_occurred;
|
||||
}
|
||||
|
||||
|
||||
static char *package_name = 0;
|
||||
|
||||
/**
|
||||
* @brief updates an option
|
||||
* @param field the generic pointer to the field to update
|
||||
* @param orig_field the pointer to the orig field
|
||||
* @param field_given the pointer to the number of occurrence of this option
|
||||
* @param prev_given the pointer to the number of occurrence already seen
|
||||
* @param value the argument for this option (if null no arg was specified)
|
||||
* @param possible_values the possible values for this option (if specified)
|
||||
* @param default_value the default value (in case the option only accepts fixed values)
|
||||
* @param arg_type the type of this option
|
||||
* @param check_ambiguity @see cmdline_parser_params.check_ambiguity
|
||||
* @param override @see cmdline_parser_params.override
|
||||
* @param no_free whether to free a possible previous value
|
||||
* @param multiple_option whether this is a multiple option
|
||||
* @param long_opt the corresponding long option
|
||||
* @param short_opt the corresponding short option (or '-' if none)
|
||||
* @param additional_error possible further error specification
|
||||
*/
|
||||
static
|
||||
int update_arg(void *field, char **orig_field,
|
||||
unsigned int *field_given, unsigned int *prev_given,
|
||||
char *value, const char *possible_values[],
|
||||
const char *default_value,
|
||||
cmdline_parser_arg_type arg_type,
|
||||
int check_ambiguity, int override,
|
||||
int no_free, int multiple_option,
|
||||
const char *long_opt, char short_opt,
|
||||
const char *additional_error)
|
||||
{
|
||||
char *stop_char = 0;
|
||||
const char *val = value;
|
||||
int found;
|
||||
FIX_UNUSED (field);
|
||||
|
||||
stop_char = 0;
|
||||
found = 0;
|
||||
|
||||
if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
|
||||
{
|
||||
if (short_opt != '-')
|
||||
fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
|
||||
package_name, long_opt, short_opt,
|
||||
(additional_error ? additional_error : ""));
|
||||
else
|
||||
fprintf (stderr, "%s: `--%s' option given more than once%s\n",
|
||||
package_name, long_opt,
|
||||
(additional_error ? additional_error : ""));
|
||||
return 1; /* failure */
|
||||
}
|
||||
|
||||
FIX_UNUSED (default_value);
|
||||
|
||||
if (field_given && *field_given && ! override)
|
||||
return 0;
|
||||
if (prev_given)
|
||||
(*prev_given)++;
|
||||
if (field_given)
|
||||
(*field_given)++;
|
||||
if (possible_values)
|
||||
val = possible_values[found];
|
||||
|
||||
switch(arg_type) {
|
||||
case ARG_FLAG:
|
||||
*((int *)field) = !*((int *)field);
|
||||
break;
|
||||
case ARG_INT:
|
||||
if (val) *((int *)field) = strtol (val, &stop_char, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
/* check numeric conversion */
|
||||
switch(arg_type) {
|
||||
case ARG_INT:
|
||||
if (val && !(stop_char && *stop_char == '\0')) {
|
||||
fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
|
||||
return 1; /* failure */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
};
|
||||
|
||||
/* store the original value */
|
||||
switch(arg_type) {
|
||||
case ARG_NO:
|
||||
case ARG_FLAG:
|
||||
break;
|
||||
default:
|
||||
if (value && orig_field) {
|
||||
if (no_free) {
|
||||
*orig_field = value;
|
||||
} else {
|
||||
if (*orig_field)
|
||||
free (*orig_field); /* free previous string */
|
||||
*orig_field = gengetopt_strdup (value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return 0; /* OK */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cmdline_parser_internal (
|
||||
int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params, const char *additional_error)
|
||||
{
|
||||
int c; /* Character of the parsed option. */
|
||||
|
||||
int error_occurred = 0;
|
||||
struct gengetopt_args_info local_args_info;
|
||||
|
||||
int override;
|
||||
int initialize;
|
||||
int check_required;
|
||||
int check_ambiguity;
|
||||
|
||||
package_name = argv[0];
|
||||
|
||||
override = params->override;
|
||||
initialize = params->initialize;
|
||||
check_required = params->check_required;
|
||||
check_ambiguity = params->check_ambiguity;
|
||||
|
||||
if (initialize)
|
||||
cmdline_parser_init (args_info);
|
||||
|
||||
cmdline_parser_init (&local_args_info);
|
||||
|
||||
optarg = 0;
|
||||
optind = 0;
|
||||
opterr = params->print_errors;
|
||||
optopt = '?';
|
||||
|
||||
while (1)
|
||||
{
|
||||
int option_index = 0;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ "nodeid", 1, NULL, 0 },
|
||||
{ "stdserial", 0, NULL, 'S' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "hVS", long_options, &option_index);
|
||||
|
||||
if (c == -1) break; /* Exit from `while (1)' loop. */
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'h': /* Print help and exit. */
|
||||
cmdline_parser_print_help ();
|
||||
cmdline_parser_free (&local_args_info);
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
case 'V': /* Print version and exit. */
|
||||
cmdline_parser_print_version ();
|
||||
cmdline_parser_free (&local_args_info);
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
case 'S': /* Use stdin/stdout for serial. */
|
||||
|
||||
|
||||
if (update_arg((void *)&(args_info->stdserial_flag), 0, &(args_info->stdserial_given),
|
||||
&(local_args_info.stdserial_given), optarg, 0, 0, ARG_FLAG,
|
||||
check_ambiguity, override, 1, 0, "stdserial", 'S',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
|
||||
case 0: /* Long option with no short option */
|
||||
/* Node ID. */
|
||||
if (strcmp (long_options[option_index].name, "nodeid") == 0)
|
||||
{
|
||||
|
||||
|
||||
if (update_arg( (void *)&(args_info->nodeid_arg),
|
||||
&(args_info->nodeid_orig), &(args_info->nodeid_given),
|
||||
&(local_args_info.nodeid_given), optarg, 0, 0, ARG_INT,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"nodeid", '-',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case '?': /* Invalid option. */
|
||||
/* `getopt_long' already printed an error message. */
|
||||
goto failure;
|
||||
|
||||
default: /* bug: option not considered. */
|
||||
fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
|
||||
abort ();
|
||||
} /* switch */
|
||||
} /* while */
|
||||
|
||||
|
||||
|
||||
if (check_required)
|
||||
{
|
||||
error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error);
|
||||
}
|
||||
|
||||
cmdline_parser_release (&local_args_info);
|
||||
|
||||
if ( error_occurred )
|
||||
return (EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
|
||||
cmdline_parser_release (&local_args_info);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
package "thread"
|
||||
version "0.1"
|
||||
purpose ""
|
||||
|
||||
option "nodeid" - "Node ID" int yes
|
||||
option "stdserial" S "Use stdin/stdout for serial" flag on
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** @file cmdline.h
|
||||
* @brief The header file for the command line option parser
|
||||
* generated by GNU Gengetopt version 2.22.6
|
||||
* http://www.gnu.org/software/gengetopt.
|
||||
* DO NOT modify this file, since it can be overwritten
|
||||
* @author GNU Gengetopt by Lorenzo Bettini */
|
||||
|
||||
#ifndef CMDLINE_H
|
||||
#define CMDLINE_H
|
||||
|
||||
#include <stdio.h> /* for FILE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef CMDLINE_PARSER_PACKAGE
|
||||
/** @brief the program name (used for printing errors) */
|
||||
#define CMDLINE_PARSER_PACKAGE "thread"
|
||||
#endif
|
||||
|
||||
#ifndef CMDLINE_PARSER_PACKAGE_NAME
|
||||
/** @brief the complete program name (used for help and version) */
|
||||
#define CMDLINE_PARSER_PACKAGE_NAME "thread"
|
||||
#endif
|
||||
|
||||
#ifndef CMDLINE_PARSER_VERSION
|
||||
/** @brief the program version */
|
||||
#define CMDLINE_PARSER_VERSION "0.1"
|
||||
#endif
|
||||
|
||||
/** @brief Where the command line options are stored */
|
||||
struct gengetopt_args_info
|
||||
{
|
||||
const char *help_help; /**< @brief Print help and exit help description. */
|
||||
const char *version_help; /**< @brief Print version and exit help description. */
|
||||
int nodeid_arg; /**< @brief Node ID. */
|
||||
char * nodeid_orig; /**< @brief Node ID original value given at command line. */
|
||||
const char *nodeid_help; /**< @brief Node ID help description. */
|
||||
int stdserial_flag; /**< @brief Use stdin/stdout for serial (default=on). */
|
||||
const char *stdserial_help; /**< @brief Use stdin/stdout for serial help description. */
|
||||
|
||||
unsigned int help_given ; /**< @brief Whether help was given. */
|
||||
unsigned int version_given ; /**< @brief Whether version was given. */
|
||||
unsigned int nodeid_given ; /**< @brief Whether nodeid was given. */
|
||||
unsigned int stdserial_given ; /**< @brief Whether stdserial was given. */
|
||||
|
||||
} ;
|
||||
|
||||
/** @brief The additional parameters to pass to parser functions */
|
||||
struct cmdline_parser_params
|
||||
{
|
||||
int override; /**< @brief whether to override possibly already present options (default 0) */
|
||||
int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
|
||||
int check_required; /**< @brief whether to check that all required options were provided (default 1) */
|
||||
int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
|
||||
int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
|
||||
} ;
|
||||
|
||||
/** @brief the purpose string of the program */
|
||||
extern const char *gengetopt_args_info_purpose;
|
||||
/** @brief the usage string of the program */
|
||||
extern const char *gengetopt_args_info_usage;
|
||||
/** @brief the description string of the program */
|
||||
extern const char *gengetopt_args_info_description;
|
||||
/** @brief all the lines making the help output */
|
||||
extern const char *gengetopt_args_info_help[];
|
||||
|
||||
/**
|
||||
* The command line parser
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* The command line parser (version with additional parameters - deprecated)
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param override whether to override possibly already present options
|
||||
* @param initialize whether to initialize the option structure my_args_info
|
||||
* @param check_required whether to check that all required options were provided
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
* @deprecated use cmdline_parser_ext() instead
|
||||
*/
|
||||
int cmdline_parser2 (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info,
|
||||
int override, int initialize, int check_required);
|
||||
|
||||
/**
|
||||
* The command line parser (version with additional parameters)
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param params additional parameters for the parser
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_ext (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Save the contents of the option struct into an already open FILE stream.
|
||||
* @param outfile the stream where to dump options
|
||||
* @param args_info the option struct to dump
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_dump(FILE *outfile,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Save the contents of the option struct into a (text) file.
|
||||
* This file can be read by the config file parser (if generated by gengetopt)
|
||||
* @param filename the file where to save
|
||||
* @param args_info the option struct to save
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_file_save(const char *filename,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Print the help
|
||||
*/
|
||||
void cmdline_parser_print_help(void);
|
||||
/**
|
||||
* Print the version
|
||||
*/
|
||||
void cmdline_parser_print_version(void);
|
||||
|
||||
/**
|
||||
* Initializes all the fields a cmdline_parser_params structure
|
||||
* to their default values
|
||||
* @param params the structure to initialize
|
||||
*/
|
||||
void cmdline_parser_params_init(struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Allocates dynamically a cmdline_parser_params structure and initializes
|
||||
* all its fields to their default values
|
||||
* @return the created and initialized cmdline_parser_params structure
|
||||
*/
|
||||
struct cmdline_parser_params *cmdline_parser_params_create(void);
|
||||
|
||||
/**
|
||||
* Initializes the passed gengetopt_args_info structure's fields
|
||||
* (also set default values for options that have a default)
|
||||
* @param args_info the structure to initialize
|
||||
*/
|
||||
void cmdline_parser_init (struct gengetopt_args_info *args_info);
|
||||
/**
|
||||
* Deallocates the string fields of the gengetopt_args_info structure
|
||||
* (but does not deallocate the structure itself)
|
||||
* @param args_info the structure to deallocate
|
||||
*/
|
||||
void cmdline_parser_free (struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Checks that all the required options were specified
|
||||
* @param args_info the structure to check
|
||||
* @param prog_name the name of the program that will be used to print
|
||||
* possible errors
|
||||
* @return
|
||||
*/
|
||||
int cmdline_parser_required (struct gengetopt_args_info *args_info,
|
||||
const char *prog_name);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* CMDLINE_H */
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <platform/logging.h>
|
||||
|
||||
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
|
||||
{
|
||||
struct timeval tv;
|
||||
char timeString[40];
|
||||
va_list args;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
strftime(timeString, sizeof(timeString), "%Y-%m-%d %H:%M:%S", localtime(&tv.tv_sec));
|
||||
fprintf(stderr, "%s.%06d ", timeString, (uint32_t)tv.tv_usec);
|
||||
|
||||
switch (aLogLevel)
|
||||
{
|
||||
case kLogLevelNone:
|
||||
printf("NONE ");
|
||||
break;
|
||||
|
||||
case kLogLevelCrit:
|
||||
printf("CRIT ");
|
||||
break;
|
||||
|
||||
case kLogLevelWarn:
|
||||
printf("WARN ");
|
||||
break;
|
||||
|
||||
case kLogLevelInfo:
|
||||
printf("INFO ");
|
||||
break;
|
||||
|
||||
case kLogLevelDebg:
|
||||
printf("DEBG ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (aLogRegion)
|
||||
{
|
||||
case kLogRegionApi:
|
||||
printf("API ");
|
||||
break;
|
||||
|
||||
case kLogRegionMle:
|
||||
printf("MLE ");
|
||||
break;
|
||||
|
||||
case kLogRegionArp:
|
||||
printf("ARP ");
|
||||
break;
|
||||
|
||||
case kLogRegionNetData:
|
||||
printf("NETD ");
|
||||
break;
|
||||
|
||||
case kLogRegionIp6:
|
||||
printf("IPV6 ");
|
||||
break;
|
||||
|
||||
case kLogRegionIcmp:
|
||||
printf("ICMP ");
|
||||
break;
|
||||
|
||||
case kLogRegionMac:
|
||||
printf("MAC ");
|
||||
break;
|
||||
|
||||
case kLogRegionMem:
|
||||
printf("MEM ");
|
||||
break;
|
||||
}
|
||||
|
||||
va_start(args, aFormat);
|
||||
vprintf(aFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform-specific initializers.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_H_
|
||||
#define PLATFORM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method initializes the alarm service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwAlarmInit(void);
|
||||
|
||||
/**
|
||||
* This method initializes the radio service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwRadioInit(void);
|
||||
|
||||
/**
|
||||
* This method initializes the random number service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwRandomInit(void);
|
||||
|
||||
/**
|
||||
* This method puts the thread executing OpenThread to sleep.
|
||||
*
|
||||
*/
|
||||
void hwSleep(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // PLATFORM_H_
|
||||
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <platform/posix/cmdline.h>
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <mac/mac.hpp>
|
||||
#include <platform/radio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern struct gengetopt_args_info args_info;
|
||||
|
||||
namespace Thread {
|
||||
|
||||
enum PhyState
|
||||
{
|
||||
kStateDisabled = 0,
|
||||
kStateSleep = 1,
|
||||
kStateIdle = 2,
|
||||
kStateListen = 3,
|
||||
kStateReceive = 4,
|
||||
kStateTransmit = 5,
|
||||
};
|
||||
|
||||
static void *phy_receive_thread(void *arg);
|
||||
|
||||
static PhyState s_state = kStateDisabled;
|
||||
static RadioPacket *s_receive_frame = NULL;
|
||||
static RadioPacket *s_transmit_frame = NULL;
|
||||
static RadioPacket m_ack_packet;
|
||||
static bool s_data_pending = false;
|
||||
|
||||
static uint8_t s_extended_address[8];
|
||||
static uint16_t s_short_address;
|
||||
static uint16_t s_panid;
|
||||
|
||||
static pthread_t s_pthread;
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_condition_variable = PTHREAD_COND_INITIALIZER;
|
||||
static int s_sockfd;
|
||||
|
||||
ThreadError otPlatRadioSetPanId(uint16_t panid)
|
||||
{
|
||||
s_panid = panid;
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSetExtendedAddress(uint8_t *address)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(s_extended_address); i++)
|
||||
{
|
||||
s_extended_address[i] = address[7 - i];
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSetShortAddress(uint16_t address)
|
||||
{
|
||||
s_short_address = address;
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
void hwRadioInit()
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_port = htons(9000 + args_info.nodeid_arg);
|
||||
sockaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
s_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
bind(s_sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
|
||||
pthread_create(&s_pthread, NULL, &phy_receive_thread, NULL);
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioEnable()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateDisabled, error = kThreadError_Busy);
|
||||
s_state = kStateSleep;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioDisable()
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_state = kStateDisabled;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSleep()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateSleep;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioIdle()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
case kStateSleep:
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
break;
|
||||
|
||||
case kStateIdle:
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
case kStateTransmit:
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
break;
|
||||
|
||||
case kStateDisabled:
|
||||
case kStateReceive:
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioReceive(RadioPacket *packet)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateListen;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
s_receive_frame = packet;
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(RadioPacket *packet)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateTransmit;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
s_transmit_frame = packet;
|
||||
s_data_pending = false;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
|
||||
for (int i = 1; i < 34; i++)
|
||||
{
|
||||
if (args_info.nodeid_arg == i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
sendto(s_sockfd, s_transmit_frame->mPsdu, s_transmit_frame->mLength, 0,
|
||||
(struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
}
|
||||
|
||||
if (!reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetAckRequest())
|
||||
{
|
||||
otPlatRadioSignalTransmitDone();
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetNoiseFloor()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioHandleTransmitDone(bool *rxPending)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(s_state == kStateTransmit, error = kThreadError_InvalidState);
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
|
||||
if (rxPending != NULL)
|
||||
{
|
||||
*rxPending = s_data_pending;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void *phy_receive_thread(void *arg)
|
||||
{
|
||||
fd_set fds;
|
||||
int rval;
|
||||
RadioPacket receive_frame;
|
||||
int length;
|
||||
uint8_t tx_sequence, rx_sequence;
|
||||
uint8_t command_id;
|
||||
|
||||
while (1)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s_sockfd, &fds);
|
||||
|
||||
rval = select(s_sockfd + 1, &fds, NULL, NULL, NULL);
|
||||
|
||||
if (rval < 0 || !FD_ISSET(s_sockfd, &fds))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
while (s_state == kStateIdle)
|
||||
{
|
||||
pthread_cond_wait(&s_condition_variable, &s_mutex);
|
||||
}
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
case kStateDisabled:
|
||||
case kStateIdle:
|
||||
case kStateSleep:
|
||||
recvfrom(s_sockfd, NULL, 0, 0, NULL, NULL);
|
||||
break;
|
||||
|
||||
case kStateTransmit:
|
||||
length = recvfrom(s_sockfd, receive_frame.mPsdu, Mac::Frame::kMTU, 0, NULL, NULL);
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(&receive_frame)->GetType() != Mac::Frame::kFcfFrameAck)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
tx_sequence = reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetSequence();
|
||||
|
||||
rx_sequence = reinterpret_cast<Mac::Frame *>(&receive_frame)->GetSequence();
|
||||
|
||||
if (tx_sequence != rx_sequence)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetType() == Mac::Frame::kFcfFrameMacCmd)
|
||||
{
|
||||
reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetCommandId(command_id);
|
||||
|
||||
if (command_id == Mac::Frame::kMacCmdDataRequest)
|
||||
{
|
||||
s_data_pending = true;
|
||||
}
|
||||
}
|
||||
|
||||
otPlatRadioSignalTransmitDone();
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
s_state = kStateReceive;
|
||||
otPlatRadioSignalReceiveDone();
|
||||
|
||||
while (s_state == kStateReceive)
|
||||
{
|
||||
pthread_cond_wait(&s_condition_variable, &s_mutex);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kStateReceive:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void send_ack()
|
||||
{
|
||||
Mac::Frame *ack_frame;
|
||||
uint8_t sequence;
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
sequence = reinterpret_cast<Mac::Frame *>(s_receive_frame)->GetSequence();
|
||||
|
||||
ack_frame = reinterpret_cast<Mac::Frame *>(&m_ack_packet);
|
||||
ack_frame->InitMacHeader(Mac::Frame::kFcfFrameAck, Mac::Frame::kSecNone);
|
||||
ack_frame->SetSequence(sequence);
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
|
||||
for (int i = 1; i < 34; i++)
|
||||
{
|
||||
if (args_info.nodeid_arg == i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
sendto(s_sockfd, m_ack_packet.mPsdu, m_ack_packet.mLength, 0,
|
||||
(struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioHandleReceiveDone()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Mac::Frame *receive_frame;
|
||||
uint16_t dstpan;
|
||||
Mac::Address dstaddr;
|
||||
int length;
|
||||
|
||||
VerifyOrExit(s_state == kStateReceive, error = kThreadError_InvalidState);
|
||||
|
||||
length = recvfrom(s_sockfd, s_receive_frame->mPsdu, Mac::Frame::kMTU, 0, NULL, NULL);
|
||||
receive_frame = reinterpret_cast<Mac::Frame *>(s_receive_frame);
|
||||
|
||||
receive_frame->GetDstAddr(dstaddr);
|
||||
|
||||
switch (dstaddr.mLength)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 2:
|
||||
receive_frame->GetDstPanId(dstpan);
|
||||
VerifyOrExit((dstpan == Mac::kShortAddrBroadcast || dstpan == s_panid) &&
|
||||
(dstaddr.mShortAddress == Mac::kShortAddrBroadcast || dstaddr.mShortAddress == s_short_address),
|
||||
error = kThreadError_Abort);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
receive_frame->GetDstPanId(dstpan);
|
||||
VerifyOrExit((dstpan == Mac::kShortAddrBroadcast || dstpan == s_panid) &&
|
||||
memcmp(&dstaddr.mExtAddress, s_extended_address, sizeof(dstaddr.mExtAddress)) == 0,
|
||||
error = kThreadError_Abort);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(error = kThreadError_Abort);
|
||||
}
|
||||
|
||||
s_receive_frame->mLength = length;
|
||||
s_receive_frame->mPower = -20;
|
||||
|
||||
// generate acknowledgment
|
||||
if (reinterpret_cast<Mac::Frame *>(s_receive_frame)->GetAckRequest())
|
||||
{
|
||||
send_ack();
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
if (s_state != kStateDisabled)
|
||||
{
|
||||
s_state = kStateIdle;
|
||||
}
|
||||
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements a pseudo-random number generator.
|
||||
*
|
||||
* @warning
|
||||
* This implementation is not a true random number generator and does @em satisfy the Thread requirements.
|
||||
*/
|
||||
|
||||
#include <platform/random.h>
|
||||
#include <platform/posix/cmdline.h>
|
||||
|
||||
extern struct gengetopt_args_info args_info;
|
||||
|
||||
static uint32_t s_state = 1;
|
||||
|
||||
void hwRandomInit(void)
|
||||
{
|
||||
s_state = args_info.nodeid_arg;
|
||||
}
|
||||
|
||||
uint32_t otPlatRandomGet(void)
|
||||
{
|
||||
uint32_t mlcg, p, q;
|
||||
uint64_t tmpstate;
|
||||
|
||||
tmpstate = (uint64_t)33614 * (uint64_t)s_state;
|
||||
q = tmpstate & 0xffffffff;
|
||||
q = q >> 1;
|
||||
p = tmpstate >> 32;
|
||||
mlcg = p + q;
|
||||
|
||||
if (mlcg & 0x80000000)
|
||||
{
|
||||
mlcg &= 0x7fffffff;
|
||||
mlcg++;
|
||||
}
|
||||
|
||||
s_state = mlcg;
|
||||
|
||||
return mlcg;
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <platform/posix/cmdline.h>
|
||||
#include <platform/serial.h>
|
||||
|
||||
static void *serial_receive_thread(void *arg);
|
||||
|
||||
#ifdef OPENTHREAD_TARGET_LINUX
|
||||
int posix_openpt(int oflag);
|
||||
int grantpt(int fildes);
|
||||
int unlockpt(int fd);
|
||||
char *ptsname(int fd);
|
||||
#endif // OPENTHREAD_TARGET_LINUX
|
||||
|
||||
extern struct gengetopt_args_info args_info;
|
||||
|
||||
static uint8_t s_receive_buffer[128];
|
||||
static int s_in_fd;
|
||||
static int s_out_fd;
|
||||
static struct termios s_in_termios;
|
||||
static struct termios s_out_termios;
|
||||
static pthread_t s_pthread;
|
||||
static sem_t *s_semaphore;
|
||||
|
||||
ThreadError otPlatSerialEnable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
struct termios termios;
|
||||
char *path;
|
||||
char cmd[256];
|
||||
|
||||
if (args_info.stdserial_given == 1)
|
||||
{
|
||||
s_in_fd = dup(STDIN_FILENO);
|
||||
s_out_fd = dup(STDOUT_FILENO);
|
||||
dup2(STDERR_FILENO, STDOUT_FILENO);
|
||||
}
|
||||
else
|
||||
{
|
||||
// open file
|
||||
#ifdef OPENTHREAD_TARGET_DARWIN
|
||||
|
||||
asprintf(&path, "/dev/ptyp%d", args_info.nodeid_arg);
|
||||
VerifyOrExit((s_in_fd = open(path, O_RDWR | O_NOCTTY)) >= 0, perror("posix_openpt"); error = kThreadError_Error);
|
||||
free(path);
|
||||
|
||||
// print pty path
|
||||
printf("/dev/ttyp%d\n", args_info.nodeid_arg);
|
||||
|
||||
#elif defined(OPENTHREAD_TARGET_LINUX)
|
||||
|
||||
VerifyOrExit((s_in_fd = posix_openpt(O_RDWR | O_NOCTTY)) >= 0, perror("posix_openpt"); error = kThreadError_Error);
|
||||
VerifyOrExit(grantpt(s_in_fd) == 0, perror("grantpt"); error = kThreadError_Error);
|
||||
VerifyOrExit(unlockpt(s_in_fd) == 0, perror("unlockpt"); error = kThreadError_Error);
|
||||
|
||||
// print pty path
|
||||
VerifyOrExit((path = ptsname(s_in_fd)) != NULL, perror("ptsname"); error = kThreadError_Error);
|
||||
printf("%s\n", path);
|
||||
|
||||
#else
|
||||
#error "Unknown platform."
|
||||
#endif
|
||||
|
||||
// check if file descriptor is pointing to a TTY device
|
||||
VerifyOrExit(isatty(s_in_fd), error = kThreadError_Error);
|
||||
|
||||
s_out_fd = dup(s_in_fd);
|
||||
|
||||
if (isatty(s_in_fd))
|
||||
{
|
||||
// get current configuration
|
||||
VerifyOrExit(tcgetattr(s_in_fd, &termios) == 0, perror("tcgetattr"); error = kThreadError_Error);
|
||||
s_in_termios = termios;
|
||||
|
||||
// turn off input processing
|
||||
termios.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
|
||||
|
||||
// turn off output processing
|
||||
termios.c_oflag = 0;
|
||||
|
||||
// turn off line processing
|
||||
termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
|
||||
|
||||
// turn off character processing
|
||||
termios.c_cflag &= ~(CSIZE | PARENB);
|
||||
termios.c_cflag |= CS8;
|
||||
|
||||
// return 1 byte at a time
|
||||
termios.c_cc[VMIN] = 1;
|
||||
|
||||
// turn off inter-character timer
|
||||
termios.c_cc[VTIME] = 0;
|
||||
|
||||
// configure baud rate
|
||||
VerifyOrExit(cfsetispeed(&termios, B115200) == 0, perror("cfsetispeed"); error = kThreadError_Error);
|
||||
|
||||
// set configuration
|
||||
VerifyOrExit(tcsetattr(s_in_fd, TCSAFLUSH, &termios) == 0, perror("tcsetattr"); error = kThreadError_Error);
|
||||
}
|
||||
|
||||
if (isatty(s_out_fd))
|
||||
{
|
||||
// get current configuration
|
||||
VerifyOrExit(tcgetattr(s_out_fd, &termios) == 0, perror("tcgetattr"); error = kThreadError_Error);
|
||||
s_out_termios = termios;
|
||||
|
||||
// turn off output processing
|
||||
termios.c_oflag = 0;
|
||||
|
||||
// turn off line processing
|
||||
termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
|
||||
|
||||
// turn off character processing
|
||||
termios.c_cflag &= ~(CSIZE | PARENB);
|
||||
termios.c_cflag |= CS8;
|
||||
|
||||
// return 1 byte at a time
|
||||
termios.c_cc[VMIN] = 1;
|
||||
|
||||
// turn off inter-character timer
|
||||
termios.c_cc[VTIME] = 0;
|
||||
|
||||
// configure baud rate
|
||||
VerifyOrExit(cfsetospeed(&termios, B115200) == 0, perror("cfsetospeed"); error = kThreadError_Error);
|
||||
|
||||
// set configuration
|
||||
VerifyOrExit(tcsetattr(s_out_fd, TCSAFLUSH, &termios) == 0, perror("tcsetattr"); error = kThreadError_Error);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "thread_serial_semaphore_%d", args_info.nodeid_arg);
|
||||
s_semaphore = sem_open(cmd, O_CREAT, 0644, 0);
|
||||
pthread_create(&s_pthread, NULL, &serial_receive_thread, NULL);
|
||||
|
||||
return error;
|
||||
|
||||
exit:
|
||||
close(s_in_fd);
|
||||
close(s_out_fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatSerialDisable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
close(s_in_fd);
|
||||
close(s_out_fd);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatSerialSend(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(write(s_out_fd, aBuf, aBufLength) >= 0, error = kThreadError_Error);
|
||||
otPlatSerialSignalSendDone();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void otPlatSerialHandleSendDone(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *serial_receive_thread(void *aContext)
|
||||
{
|
||||
fd_set fds;
|
||||
int rval;
|
||||
|
||||
while (1)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s_in_fd, &fds);
|
||||
|
||||
rval = select(s_in_fd + 1, &fds, NULL, NULL, NULL);
|
||||
|
||||
if (rval >= 0 && FD_ISSET(s_in_fd, &fds))
|
||||
{
|
||||
otPlatSerialSignalReceive();
|
||||
sem_wait(s_semaphore);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint8_t *otPlatSerialGetReceivedBytes(uint16_t *aBufLength)
|
||||
{
|
||||
size_t length;
|
||||
int i;
|
||||
|
||||
length = read(s_in_fd, s_receive_buffer, sizeof(s_receive_buffer));
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
if (s_receive_buffer[i] == 0x03)
|
||||
{
|
||||
otPlatSerialDisable();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (aBufLength != NULL)
|
||||
{
|
||||
*aBufLength = length;
|
||||
}
|
||||
|
||||
return s_receive_buffer;
|
||||
}
|
||||
|
||||
void otPlatSerialHandleReceiveDone(void)
|
||||
{
|
||||
sem_post(s_semaphore);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform abstraction for AES ECB computations.
|
||||
*/
|
||||
|
||||
#ifndef AES_ECB_H_
|
||||
#define AES_ECB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup core-security
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
otAesBlockSize = 16, ///< AES-128 block size.
|
||||
};
|
||||
|
||||
/**
|
||||
* This method sets the key.
|
||||
*
|
||||
* @param[in] aKey A pointer to the key.
|
||||
* @param[in] aKeyLength Length of the key in bytes.
|
||||
*
|
||||
*/
|
||||
void otCryptoAesEcbSetKey(const void *aKey, uint16_t aKeyLength);
|
||||
|
||||
/**
|
||||
* This method encrypts data.
|
||||
*
|
||||
* @param[in] aInput A pointer to the input.
|
||||
* @param[out] aOutput A pointer to the output.
|
||||
*
|
||||
*/
|
||||
void otCryptoAesEcbEncrypt(const uint8_t aInput[otAesBlockSize], uint8_t aOutput[otAesBlockSize]);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AES_ECB_H_
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform abstraction for HMAC SHA-256 computations.
|
||||
*/
|
||||
|
||||
#ifndef HMAC_SHA256_H_
|
||||
#define HMAC_SHA256_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup core-security
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
otCryptoSha256Size = 32, ///< SHA-256 hash size (bytes)
|
||||
};
|
||||
|
||||
/**
|
||||
* This method sets the key.
|
||||
*
|
||||
* @param[in] aKey A pointer to the key.
|
||||
* @param[in] aKeyLength The key length in bytes.
|
||||
*
|
||||
*/
|
||||
void otCryptoHmacSha256Start(const void *aKey, uint16_t aKeyLength);
|
||||
|
||||
/**
|
||||
* This method inputs bytes into the HMAC computation.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the input buffer.
|
||||
* @param[in] aBufLength The length of @p aBuf in bytes.
|
||||
*
|
||||
*/
|
||||
void otCryptoHmacSha256Update(const void *aBuf, uint16_t aBufLength);
|
||||
|
||||
/**
|
||||
* This method finalizes the hash computation.
|
||||
*
|
||||
* @param[out] aHash A pointer to the output buffer.
|
||||
*
|
||||
*/
|
||||
void otCryptoHmacSha256Finish(uint8_t aHash[otCryptoSha256Size]);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // HMAC_SHA256_H_
|
||||
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines the types and structures used in the OpenThread library API.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_TYPES_H_
|
||||
#define OPENTHREAD_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This enumeration represents error codes used throughout OpenThread.
|
||||
*/
|
||||
typedef enum ThreadError
|
||||
{
|
||||
kThreadError_None = 0,
|
||||
kThreadError_Failed = 1,
|
||||
kThreadError_Drop = 2,
|
||||
kThreadError_NoBufs = 3,
|
||||
kThreadError_NoRoute = 4,
|
||||
kThreadError_Busy = 5,
|
||||
kThreadError_Parse = 6,
|
||||
kThreadError_InvalidArgs = 7,
|
||||
kThreadError_Security = 8,
|
||||
kThreadError_AddressQuery = 9,
|
||||
kThreadError_NoAddress = 10,
|
||||
kThreadError_NotReceiving = 11,
|
||||
kThreadError_Abort = 12,
|
||||
kThreadError_NotImplemented = 13,
|
||||
kThreadError_InvalidState = 14,
|
||||
kThreadError_NoTasklets = 15,
|
||||
kThreadError_Error = 255,
|
||||
} ThreadError;
|
||||
|
||||
/**
|
||||
* @addtogroup config Configuration
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions for configuration.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup config-general General
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions that manage configuration parameters for the Thread Child, Router, and Leader rols.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_NETWORK_NAME_SIZE 16 ///< Network name size (bytes).
|
||||
|
||||
/**
|
||||
* This structure represents an MLE Link Mode configuration.
|
||||
*/
|
||||
typedef struct otLinkModeConfig
|
||||
{
|
||||
/**
|
||||
* 1, if the sender has its receiver on when not transmitting. 0, otherwise.
|
||||
*/
|
||||
uint8_t mRxOnWhenIdle : 1;
|
||||
|
||||
/**
|
||||
* 1, if the sender will use IEEE 802.15.4 to secure all data requests. 0, otherwise.
|
||||
*/
|
||||
uint8_t mSecureDataRequests : 1;
|
||||
|
||||
/**
|
||||
* 1, if the sender is an FFD. 0, otherwise.
|
||||
*/
|
||||
uint8_t mDeviceType : 1;
|
||||
|
||||
/**
|
||||
* 1, if the sender requires the full Network Data. 0, otherwise.
|
||||
*/
|
||||
uint8_t mNetworkData : 1;
|
||||
} otLinkModeConfig;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup config-br Border Router
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions that manage configuration parameters that apply to the Thread Border Router role.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
kIp6AddressSize = 16,
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents an IPv6 address.
|
||||
*/
|
||||
typedef struct otIp6Address
|
||||
{
|
||||
union
|
||||
{
|
||||
uint8_t m8[kIp6AddressSize];
|
||||
uint16_t m16[kIp6AddressSize / sizeof(uint16_t)];
|
||||
uint32_t m32[kIp6AddressSize / sizeof(uint32_t)];
|
||||
};
|
||||
} __attribute__((packed)) otIp6Address;
|
||||
|
||||
/**
|
||||
* This structure represents an IPv6 prefix.
|
||||
*/
|
||||
typedef struct otIp6Prefix
|
||||
{
|
||||
otIp6Address mPrefix; ///< The IPv6 prefix.
|
||||
uint8_t mLength; ///< The IPv6 prefix length.
|
||||
} otIp6Prefix;
|
||||
|
||||
/**
|
||||
* This structure represents a Border Router configuration.
|
||||
*/
|
||||
typedef struct otBorderRouterConfig
|
||||
{
|
||||
/**
|
||||
* TRUE, if this border router is a DHCPv6 Agent that supplies other configuration data. FALSE, otherwise.
|
||||
*/
|
||||
otIp6Prefix mPrefix;
|
||||
|
||||
/**
|
||||
* A 2-bit signed integer indicating router preference as defined in RFC 4291.
|
||||
*/
|
||||
int8_t mPreference : 2;
|
||||
|
||||
/**
|
||||
* TRUE, if @p mPrefix is preferred and should e used for address autoconfiguration. FALSE, otherwise.
|
||||
*/
|
||||
uint8_t mSlaacPreferred : 1;
|
||||
|
||||
/**
|
||||
* TRUE, if @p mPrefix is valid and should be used for address autoconfiguration. FALSE, otherwise.
|
||||
*/
|
||||
uint8_t mSlaacValid : 1;
|
||||
|
||||
/**
|
||||
* TRUE, if this border router is a DHCPv6 Agent that supplies IPv6 address configuration. FALSE, otherwise.
|
||||
*/
|
||||
uint8_t mDhcp : 1;
|
||||
|
||||
/**
|
||||
* TRUE, if this border router is a DHCPv6 Agent that supplies other configuration data. FALSE, otherwise.
|
||||
*/
|
||||
uint8_t mConfigure : 1;
|
||||
|
||||
/**
|
||||
* TRUE, if this border router is a default route for @p mPrefix. FALSE, otherwise.
|
||||
*/
|
||||
uint8_t mDefaultRoute : 1;
|
||||
|
||||
/**
|
||||
* TRUE, if this configuration is considered Stable Network Data. FALSE, otherwise.
|
||||
*/
|
||||
uint8_t mStable : 1;
|
||||
} otBorderRouterConfig;
|
||||
|
||||
/**
|
||||
* This structure represents an External Route configuration.
|
||||
*/
|
||||
typedef struct otExternalRouteConfig
|
||||
{
|
||||
/**
|
||||
* The prefix for the off-mesh route.
|
||||
*/
|
||||
otIp6Prefix mPrefix;
|
||||
|
||||
/**
|
||||
* A 2-bit signed integer indicating router preference as defined in RFC 4291.
|
||||
*/
|
||||
int8_t mPreference : 2;
|
||||
|
||||
/**
|
||||
* TRUE, if this configuration is considered Stable Network Data. FALSE, otherwise.
|
||||
*/
|
||||
uint8_t mStable : 1;
|
||||
} otExternalRouteConfig;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup config-test Test
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions that manage configuration parameters required for Thread Certification testing.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents any restrictions on the attach process.
|
||||
*/
|
||||
typedef enum otMleAttachFilter
|
||||
{
|
||||
kMleAttachAnyPartition = 0, ///< Attach to any Thread partition.
|
||||
kMleAttachSamePartition = 1, ///< Attach to the same Thread partition.
|
||||
kMleAttachBetterPartition = 2, ///< Attach to a better (i.e. higher weight/partition id) Thread partition.
|
||||
} otMleAttachFilter;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup diags Diagnostics
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions that expose internal state.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a Thread device role.
|
||||
*/
|
||||
enum otDeviceRole
|
||||
{
|
||||
kDeviceRoleDisabled, ///< The Thread stack is disabled.
|
||||
kDeviceRoleDetached, ///< Not currently participating in a Thread network/partition.
|
||||
kDeviceRoleChild, ///< The Thread Child role.
|
||||
kDeviceRoleRouter, ///< The Thread Router role.
|
||||
kDeviceRoleLeader, ///< The Thread Leader role.
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This structure represents an IPv6 network interface address.
|
||||
*
|
||||
*/
|
||||
typedef struct otNetifAddress
|
||||
{
|
||||
otIp6Address mAddress; ///< The IPv6 address.
|
||||
uint32_t mPreferredLifetime; ///< The Preferred Lifetime.
|
||||
uint32_t mValidLifetime; ///< The Valid lifetime.
|
||||
uint8_t mPrefixLength; ///< The Prefix length.
|
||||
struct otNetifAddress *mNext; ///< A pointer to the next network interface address.
|
||||
} otNetifAddress;
|
||||
|
||||
/**
|
||||
* @addtogroup messages Message Buffers
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions that manipulate OpenThread message buffers
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This type points to an OpenThread message buffer.
|
||||
*/
|
||||
typedef void *otMessage;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup udp UDP
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions that control UDP communication.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This structure represents an IPv6 socket address.
|
||||
*/
|
||||
typedef struct otSockAddr
|
||||
{
|
||||
otIp6Address mAddress; ///< An IPv6 address.
|
||||
uint16_t mPort; ///< A transport-layer port.
|
||||
uint8_t mScopeId; ///< An IPv6 scope identifier.
|
||||
} otSockAddr;
|
||||
|
||||
/**
|
||||
* This structure represents the local and peer IPv6 socket addresses.
|
||||
*/
|
||||
typedef struct otMessageInfo
|
||||
{
|
||||
otIp6Address mSockAddr; ///< The local IPv6 address.
|
||||
otIp6Address mPeerAddr; ///< The peer IPv6 address.
|
||||
uint16_t mSockPort; ///< The local transport-layer port.
|
||||
uint16_t mPeerPort; ///< The peer transport-layer port.
|
||||
uint8_t mInterfaceId; ///< An IPv6 interface identifier.
|
||||
uint8_t mHopLimit; ///< The IPv6 Hop Limit.
|
||||
const void *mLinkInfo; ///< A pointer to link-specific information.
|
||||
} otMessageInfo;
|
||||
|
||||
/**
|
||||
* This callback allows OpenThread to inform the application of a received UDP message.
|
||||
*/
|
||||
typedef void (*otUdpReceive)(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
/**
|
||||
* This structure represents a UDP socket.
|
||||
*/
|
||||
typedef struct otUdpSocket
|
||||
{
|
||||
otSockAddr mSockName; ///< The local IPv6 socket address.
|
||||
otSockAddr mPeerName; ///< The peer IPv6 socket address.
|
||||
otUdpReceive mHandler; ///< A function pointer to the application callback.
|
||||
void *mContext; ///< A pointer to application-specific context.
|
||||
struct otUdpSocket *mNext; ///< A pointer to the next UDP socket.
|
||||
} otUdpSocket;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_TYPES_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform abstraction for the alarm service.
|
||||
*/
|
||||
|
||||
#ifndef ALARM_H_
|
||||
#define ALARM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup alarm Alarm
|
||||
* @ingroup platform
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction for the alarm service.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize the Alarm.
|
||||
*/
|
||||
void otPlatAlarmInit(void);
|
||||
|
||||
/**
|
||||
* Set the alarm to fire at @p aDt milliseconds after @p aT0.
|
||||
*
|
||||
* @param[in] aT0 The reference time.
|
||||
* @param[in] aDt The time delay in milliseconds from @p aT0.
|
||||
*/
|
||||
void otPlatAlarmStartAt(uint32_t aT0, uint32_t aDt);
|
||||
|
||||
/**
|
||||
* Stop the alarm.
|
||||
*/
|
||||
void otPlatAlarmStop(void);
|
||||
|
||||
/**
|
||||
* Get the current current time.
|
||||
*
|
||||
* @returns The current time in milliseconds.
|
||||
*/
|
||||
uint32_t otPlatAlarmGetNow(void);
|
||||
|
||||
/**
|
||||
* Signal that the alarm has fired.
|
||||
*/
|
||||
extern void otPlatAlarmSignalFired(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // ALARM_H_
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform abstraction to support critical sections.
|
||||
*/
|
||||
|
||||
#ifndef ATOMIC_H_
|
||||
#define ATOMIC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup atomic Atomic
|
||||
* @ingroup platform
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction to support critical sections.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Begin critical section.
|
||||
*/
|
||||
uint32_t otPlatAtomicBegin();
|
||||
|
||||
/**
|
||||
* End critical section.
|
||||
*/
|
||||
void otPlatAtomicEnd(uint32_t state);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // ATOMIC_H_
|
||||
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform abstraction for the debug log service.
|
||||
*/
|
||||
|
||||
#ifndef LOGGING_H_
|
||||
#define LOGGING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup logging Logging
|
||||
* @ingroup platform
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction for the debug log service.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
#define OPENTHREAD_LOG_LEVEL_NONE 0
|
||||
#define OPENTHREAD_LOG_LEVEL_CRIT 1
|
||||
#define OPENTHREAD_LOG_LEVEL_WARN 2
|
||||
#define OPENTHREAD_LOG_LEVEL_INFO 3
|
||||
#define OPENTHREAD_LOG_LEVEL_DEBG 4
|
||||
|
||||
/**
|
||||
* This enum represents different log levels.
|
||||
*
|
||||
*/
|
||||
typedef enum otLogLevel
|
||||
{
|
||||
kLogLevelNone = OPENTHREAD_LOG_LEVEL_NONE, ///< None
|
||||
kLogLevelCrit = OPENTHREAD_LOG_LEVEL_CRIT, ///< Critical
|
||||
kLogLevelWarn = OPENTHREAD_LOG_LEVEL_WARN, ///< Warning
|
||||
kLogLevelInfo = OPENTHREAD_LOG_LEVEL_INFO, ///< Info
|
||||
kLogLevelDebg = OPENTHREAD_LOG_LEVEL_DEBG, ///< Debug
|
||||
} otLogLevel;
|
||||
|
||||
/**
|
||||
* This enum represents log regions.
|
||||
*
|
||||
*/
|
||||
typedef enum otLogRegion
|
||||
{
|
||||
kLogRegionApi = 1, ///< OpenThread API
|
||||
kLogRegionMle = 2, ///< MLE
|
||||
kLogRegionArp = 3, ///< EID-to-RLOC mapping.
|
||||
kLogRegionNetData = 4, ///< Network Data
|
||||
kLogRegionIcmp = 5, ///< ICMPv6
|
||||
kLogRegionIp6 = 6, ///< IPv6
|
||||
kLogRegionMac = 7, ///< IEEE 802.15.4 MAC
|
||||
kLogRegionMem = 8, ///< Memory
|
||||
} otLogRegion;
|
||||
|
||||
/**
|
||||
* This function outputs logs.
|
||||
*
|
||||
* @param[in] aLogLevel The log level.
|
||||
* @param[in] aLogRegion The log region.
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...);
|
||||
|
||||
/**
|
||||
* @def otLogCrit
|
||||
*
|
||||
* Logging at log level critical.
|
||||
*
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OPENTHREAD_LOG_LEVEL_CRIT
|
||||
#define otLogCrit(aRegion, aFormat, ...) otPlatLog(kLogLevelCrit, aRegion, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCrit(aRegion, aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogWarn
|
||||
*
|
||||
* Logging at log level warning.
|
||||
*
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OPENTHREAD_LOG_LEVEL_WARN
|
||||
#define otLogWarn(aRegion, aFormat, ...) otPlatLog(kLogLevelWarn, aRegion, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogWarn(aRegion, aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogInfo
|
||||
*
|
||||
* Logging at log level info.
|
||||
*
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OPENTHREAD_LOG_LEVEL_INFO
|
||||
#define otLogInfo(aRegion, aFormat, ...) otPlatLog(kLogLevelInfo, aRegion, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogInfo(aRegion, aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogDebg
|
||||
*
|
||||
* Logging at log level debug.
|
||||
*
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OPENTHREAD_LOG_LEVEL_DEBG
|
||||
#define otLogDebg(aRegion, aFormat, ...) otPlatLog(kLogLevelDebg, aRegion, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogDebg(aRegion, aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritApi
|
||||
*
|
||||
* This method generates a log with level critical for the API region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnApi
|
||||
*
|
||||
* This method generates a log with level warning for the API region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoApi
|
||||
*
|
||||
* This method generates a log with level info for the API region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgApi
|
||||
*
|
||||
* This method generates a log with level debug for the API region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_API
|
||||
#define otLogCritApi(aFormat, ...) otLogCrit(kLogRegionApi, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnApi(aFormat, ...) otLogWarn(kLogRegionApi, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoApi(aFormat, ...) otLogInfo(kLogRegionApi, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgApi(aFormat, ...) otLogDebg(kLogRegionApi, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritApi(aFormat, ...)
|
||||
#define otLogWarnApi(aFormat, ...)
|
||||
#define otLogInfoApi(aFormat, ...)
|
||||
#define otLogDebgApi(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritMle
|
||||
*
|
||||
* This method generates a log with level critical for the MLE region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnMle
|
||||
*
|
||||
* This method generates a log with level warning for the MLE region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoMle
|
||||
*
|
||||
* This method generates a log with level info for the MLE region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgMle
|
||||
*
|
||||
* This method generates a log with level debug for the MLE region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_MLE
|
||||
#define otLogCritMle(aFormat, ...) otLogCrit(kLogRegionMle, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnMle(aFormat, ...) otLogWarn(kLogRegionMle, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoMle(aFormat, ...) otLogInfo(kLogRegionMle, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgMle(aFormat, ...) otLogDebg(kLogRegionMle, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritMle(aFormat, ...)
|
||||
#define otLogWarnMle(aFormat, ...)
|
||||
#define otLogInfoMle(aFormat, ...)
|
||||
#define otLogDebgMle(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritArp
|
||||
*
|
||||
* This method generates a log with level critical for the EID-to-RLOC mapping region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnArp
|
||||
*
|
||||
* This method generates a log with level warning for the EID-to-RLOC mapping region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoArp
|
||||
*
|
||||
* This method generates a log with level info for the EID-to-RLOC mapping region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgArp
|
||||
*
|
||||
* This method generates a log with level debug for the EID-to-RLOC mapping region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_ARP
|
||||
#define otLogCritArp(aFormat, ...) otLogCrit(kLogRegionArp, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnArp(aFormat, ...) otLogWarn(kLogRegionArp, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoArp(aFormat, ...) otLogInfo(kLogRegionArp, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgArp(aFormat, ...) otLogDebg(kLogRegionArp, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritArp(aFormat, ...)
|
||||
#define otLogWarnArp(aFormat, ...)
|
||||
#define otLogInfoArp(aFormat, ...)
|
||||
#define otLogDebgArp(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritNetData
|
||||
*
|
||||
* This method generates a log with level critical for the Network Data region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnNetData
|
||||
*
|
||||
* This method generates a log with level warning for the Network Data region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoNetData
|
||||
*
|
||||
* This method generates a log with level info for the Network Data region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgNetData
|
||||
*
|
||||
* This method generates a log with level debug for the Network Data region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_NETDATA
|
||||
#define otLogCritNetData(aFormat, ...) otLogCrit(kLogRegionNetData, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnNetData(aFormat, ...) otLogWarn(kLogRegionNetData, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoNetData(aFormat, ...) otLogInfo(kLogRegionNetData, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgNetData(aFormat, ...) otLogDebg(kLogRegionNetData, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritNetData(aFormat, ...)
|
||||
#define otLogWarnNetData(aFormat, ...)
|
||||
#define otLogInfoNetData(aFormat, ...)
|
||||
#define otLogDebgNetData(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritIcmp
|
||||
*
|
||||
* This method generates a log with level critical for the ICMPv6 region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnIcmp
|
||||
*
|
||||
* This method generates a log with level warning for the ICMPv6 region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoIcmp
|
||||
*
|
||||
* This method generates a log with level info for the ICMPv6 region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgIcmp
|
||||
*
|
||||
* This method generates a log with level debug for the ICMPv6 region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_ICMP
|
||||
#define otLogCritIcmp(aFormat, ...) otLogCrit(kLogRegionIcmp, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnIcmp(aFormat, ...) otLogWarn(kLogRegionIcmp, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoIcmp(aFormat, ...) otLogInfo(kLogRegionIcmp, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgIcmp(aFormat, ...) otLogDebg(kLogRegionIcmp, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritIcmp(aFormat, ...)
|
||||
#define otLogWarnIcmp(aFormat, ...)
|
||||
#define otLogInfoIcmp(aFormat, ...)
|
||||
#define otLogDebgIcmp(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritIp6
|
||||
*
|
||||
* This method generates a log with level critical for the IPv6 region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnIp6
|
||||
*
|
||||
* This method generates a log with level warning for the IPv6 region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoIp6
|
||||
*
|
||||
* This method generates a log with level info for the IPv6 region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgIp6
|
||||
*
|
||||
* This method generates a log with level debug for the IPv6 region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_IP6
|
||||
#define otLogCritIp6(aFormat, ...) otLogCrit(kLogRegionIp6, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnIp6(aFormat, ...) otLogWarn(kLogRegionIp6, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoIp6(aFormat, ...) otLogInfo(kLogRegionIp6, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgIp6(aFormat, ...) otLogDebg(kLogRegionIp6, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritIp6(aFormat, ...)
|
||||
#define otLogWarnIp6(aFormat, ...)
|
||||
#define otLogInfoIp6(aFormat, ...)
|
||||
#define otLogDebgIp6(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritMac
|
||||
*
|
||||
* This method generates a log with level critical for the MAC region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnMac
|
||||
*
|
||||
* This method generates a log with level warning for the MAC region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoMac
|
||||
*
|
||||
* This method generates a log with level info for the MAC region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgMac
|
||||
*
|
||||
* This method generates a log with level debug for the MAC region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_MAC
|
||||
#define otLogCritMac(aFormat, ...) otLogCrit(kLogRegionMac, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnMac(aFormat, ...) otLogWarn(kLogRegionMac, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoMac(aFormat, ...) otLogInfo(kLogRegionMac, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgMac(aFormat, ...) otLogDebg(kLogRegionMac, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritMac(aFormat, ...)
|
||||
#define otLogWarnMac(aFormat, ...)
|
||||
#define otLogInfoMac(aFormat, ...)
|
||||
#define otLogDebgMac(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otLogCritMem
|
||||
*
|
||||
* This method generates a log with level critical for the memory region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogWarnMem
|
||||
*
|
||||
* This method generates a log with level warning for the memory region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogInfoMem
|
||||
*
|
||||
* This method generates a log with level info for the memory region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otLogDebgMem
|
||||
*
|
||||
* This method generates a log with level debug for the memory region.
|
||||
*
|
||||
* @param[in] aFormat A pointer to the format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_MEM
|
||||
#define otLogCritMem(aFormat, ...) otLogCrit(kLogRegionMem, aFormat, ## __VA_ARGS__)
|
||||
#define otLogWarnMem(aFormat, ...) otLogWarn(kLogRegionMem, aFormat, ## __VA_ARGS__)
|
||||
#define otLogInfoMem(aFormat, ...) otLogInfo(kLogRegionMem, aFormat, ## __VA_ARGS__)
|
||||
#define otLogDebgMem(aFormat, ...) otLogDebg(kLogRegionMem, aFormat, ## __VA_ARGS__)
|
||||
#else
|
||||
#define otLogCritMem(aFormat, ...)
|
||||
#define otLogWarnMem(aFormat, ...)
|
||||
#define otLogInfoMem(aFormat, ...)
|
||||
#define otLogDebgMem(aFormat, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // DEBUG_H_
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines the radio interface for OpenThread.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RADIO_H_
|
||||
#define RADIO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup radio Radio
|
||||
* @ingroup platform
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction for radio communication.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup radio-types Types
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction for a radio packet.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxPHYPacketSize = 127, ///< aMaxPHYPacketSize (IEEE 802.15.4-2006)
|
||||
kPhyMinChannel = 11, ///< 2.4 GHz IEEE 802.15.4-2006
|
||||
kPhyMaxChannel = 26, ///< 2.4 GHz IEEE 802.15.4-2006
|
||||
kPhySymbolsPerOctet = 2, ///< 2.4 GHz IEEE 802.15.4-2006
|
||||
kPhyBitRate = 250000, ///< 2.4 GHz IEEE 802.15.4 (kilbits per second)
|
||||
|
||||
kPhyBitsPerOctet = 8,
|
||||
kPhyUsPerSymbol = ((kPhyBitsPerOctet / kPhySymbolsPerOctet) * 1000000) / kPhyBitRate,
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents an IEEE 802.15.4 radio frame.
|
||||
*/
|
||||
typedef struct RadioPacket
|
||||
{
|
||||
uint8_t mLength; ///< Length of the PSDU.
|
||||
uint8_t mPsdu[kMaxPHYPacketSize]; ///< The PSDU.
|
||||
uint8_t mChannel; ///< Channel used to transmit/receive the frame.
|
||||
int8_t mPower; ///< Transmit/receive power in dBm.
|
||||
} RadioPacket;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup radio-config Configuration
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction for radio configuration.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set the PAN ID for address filtering.
|
||||
*
|
||||
* @param[in] aPanId The IEEE 802.15.4 PAN ID.
|
||||
*
|
||||
* @retval ::kThreadError_None If the PAN ID was set properly.
|
||||
* @retval ::kThreadError_Fail If the PAN ID was not set properly.
|
||||
*/
|
||||
ThreadError otPlatRadioSetPanId(uint16_t aPanId);
|
||||
|
||||
/**
|
||||
* Set the Extended Address for address filtering.
|
||||
*
|
||||
* @param[in] aExtendedAddress A pointer to the IEEE 802.15.4 Extended Address.
|
||||
*
|
||||
* @retval ::kThreadError_None If the Extended Address was set properly.
|
||||
* @retval ::kThreadError_Fail If the Extended Address was not set properly.
|
||||
*/
|
||||
ThreadError otPlatRadioSetExtendedAddress(uint8_t *aExtendedAddress);
|
||||
|
||||
/**
|
||||
* Set the Short Address for address filtering.
|
||||
*
|
||||
* @param[in] aShortAddress The IEEE 802.15.4 Short Address.
|
||||
*
|
||||
* @retval ::kThreadError_None If the Short Address was set properly.
|
||||
* @retval ::kThreadError_Fail If the Short Address was not set properly.
|
||||
*/
|
||||
ThreadError otPlatRadioSetShortAddress(uint16_t aShortAddress);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup radio-operation Operation
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction for radio operations.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Intialize the radio.
|
||||
*/
|
||||
void otPlatRadioInit();
|
||||
|
||||
/**
|
||||
* Enable the radio.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Idle.
|
||||
* @retval ::kThreadError_Fail Failed to transition to Idle.
|
||||
*/
|
||||
ThreadError otPlatRadioEnable();
|
||||
|
||||
/**
|
||||
* Disable the radio.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Disabled.
|
||||
* @retval ::kThreadError_Fail Failed to transition to Disabled.
|
||||
*/
|
||||
ThreadError otPlatRadioDisable();
|
||||
|
||||
/**
|
||||
* Transition the radio to Sleep.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Sleep.
|
||||
* @retval ::kThreadError_Fail Failed to transition to Sleep.
|
||||
*/
|
||||
ThreadError otPlatRadioSleep();
|
||||
|
||||
/**
|
||||
* Transition the radio to Idle.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Idle.
|
||||
* @retval ::kThreadError_Fail Failed to transition to Idle.
|
||||
*/
|
||||
ThreadError otPlatRadioIdle();
|
||||
|
||||
/**
|
||||
* Begins the receive sequence on the radio.
|
||||
*
|
||||
* The receive sequence consists of:
|
||||
* 1. Transitioning the radio to Receive from Idle.
|
||||
* 2. Remain in Receive until a packet is received or reception is aborted.
|
||||
* 3. Return to Idle.
|
||||
*
|
||||
* Upon completion of the receive sequence, otPlatRadioSignalReceiveDone() is called to signal completion to the MAC
|
||||
* layer.
|
||||
*
|
||||
* @param[in] aPacket A pointer to a packet buffer.
|
||||
*
|
||||
* @note The channel is specified in @p aPacket.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Receive.
|
||||
* @retval ::kThreadError_Fail Failed to transition to Receive.
|
||||
*/
|
||||
ThreadError otPlatRadioReceive(RadioPacket *aPacket);
|
||||
|
||||
/**
|
||||
* Signal that a packet has been received.
|
||||
*
|
||||
* This may be called from interrupt context. The MAC layer will then schedule a call to otPlatRadioHandleReceive().
|
||||
*/
|
||||
|
||||
extern void otPlatRadioSignalReceiveDone();
|
||||
|
||||
/**
|
||||
* Complete the receive sequence.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully received a frame.
|
||||
* @retval ::kThreadError_Abort Reception was aborted and a frame was not received.
|
||||
* @retval ::kThreadError_InvalidState The radio was not in Receive.
|
||||
*/
|
||||
ThreadError otPlatRadioHandleReceiveDone();
|
||||
|
||||
/**
|
||||
* Begins the transmit sequence on the radio.
|
||||
*
|
||||
* The transmit sequence consists of:
|
||||
* 1. Transitioning the radio to Transmit from Idle.
|
||||
* 2. Transmits the psdu on the given channel and at the given transmit power.
|
||||
* 3. Return to Idle.
|
||||
*
|
||||
* Upon completion of the transmit sequence, otPlatRadioSignalTransmitDone() is called to signal completion to the MAC
|
||||
* layer.
|
||||
*
|
||||
* @param[in] aPacket A pointer to a packet buffer.
|
||||
*
|
||||
* @note The channel is specified in @p aPacket.
|
||||
* @note The transmit power is specified in @p aPacket.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Transmit.
|
||||
* @retval ::kThreadError_InvalidArgs One or more parameters in @p aPacket are invalid.
|
||||
* @retval ::kThreadError_Fail Failed to transition to Transmit.
|
||||
*/
|
||||
ThreadError otPlatRadioTransmit(RadioPacket *aPacket);
|
||||
|
||||
/**
|
||||
* Signal that the requested transmission is complete.
|
||||
*
|
||||
* This may be called from interrupt context. OpenThread will then schedule a call to
|
||||
* otPlatRadio_handle_transmit_done().
|
||||
*/
|
||||
extern void otPlatRadioSignalTransmitDone();
|
||||
|
||||
/**
|
||||
* Complete the transmit sequence on the radio.
|
||||
*
|
||||
* @param[out] aFramePending TRUE if an ACK frame was received and the Frame Pending bit was set.
|
||||
*
|
||||
* @retval ::kThreadError_None The frame was transmitted.
|
||||
* @retval ::kThreadError_NoAck The frame was transmitted, but no ACK was received.
|
||||
* @retval ::kThreadError_CcaFailed The transmission was aborted due to CCA failure.
|
||||
* @retval ::kThreadError_Abort The transmission was aborted for other reasons.
|
||||
* @retval ::kThreadError_InvalidState The radio did not transmit a packet.
|
||||
*/
|
||||
ThreadError otPlatRadioHandleTransmitDone(bool *aFramePending);
|
||||
|
||||
/**
|
||||
* Get the most recent RSSI measurement.
|
||||
*
|
||||
* @returns The noise floor value in dBm when the noise floor value is valid. 127 when noise floor value is invalid.
|
||||
*/
|
||||
int8_t otPlatRadioGetNoiseFloor();
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // RADIO_H_
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform abstraction for true random number generation.
|
||||
*/
|
||||
|
||||
#ifndef RANDOM_H_
|
||||
#define RANDOM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup random Random
|
||||
* @ingroup platform
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction to support critical sections.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize the true random number generator.
|
||||
*
|
||||
*/
|
||||
void otPlatRandomInit(void);
|
||||
|
||||
/**
|
||||
* Get a 32-bit true random value.
|
||||
*
|
||||
* @returns A 32-bit true random value.
|
||||
*
|
||||
*/
|
||||
uint32_t otPlatRandomGet(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // RANDOM_H_
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform abstraction for serial communication.
|
||||
*/
|
||||
|
||||
#ifndef SERIAL_H_
|
||||
#define SERIAL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup serial Serial
|
||||
* @ingroup platform
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction for serial communication.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enable the serial.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully enabled the serial.
|
||||
* @retval ::kThreadError_Fail Failed to enabled the serial.
|
||||
*/
|
||||
ThreadError otPlatSerialEnable(void);
|
||||
|
||||
/**
|
||||
* Disable the serial.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully disabled the serial.
|
||||
* @retval ::kThreadError_Fail Failed to disable the serial.
|
||||
*/
|
||||
ThreadError otPlatSerialDisable(void);
|
||||
|
||||
/**
|
||||
* Send bytes over the serial.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the data buffer.
|
||||
* @param[in] aBufLength Number of bytes to transmit.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully started transmission.
|
||||
* @retval ::kThreadError_Fail Failed to start the transmission.
|
||||
*/
|
||||
ThreadError otPlatSerialSend(const uint8_t *aBuf, uint16_t aBufLength);
|
||||
|
||||
/**
|
||||
* Signal that the bytes send operation has completed.
|
||||
*
|
||||
* This may be called from interrupt context. This will schedule calls to otPlatSerialHandleSendDone().
|
||||
*/
|
||||
extern void otPlatSerialSignalSendDone(void);
|
||||
|
||||
/**
|
||||
* Complete the send sequence.
|
||||
*/
|
||||
void otPlatSerialHandleSendDone(void);
|
||||
|
||||
/**
|
||||
* Signal that bytes have been received.
|
||||
*
|
||||
* This may be called from interrupt context. This will schedule calls to otPlatSerialGetReceivedBytes() and
|
||||
* otPlatSerialHandleReceiveDone().
|
||||
*/
|
||||
extern void otPlatSerialSignalReceive(void);
|
||||
|
||||
/**
|
||||
* Get a pointer to the received bytes.
|
||||
*
|
||||
* @param[out] aBufLength A pointer to a variable that this function will put the number of bytes received.
|
||||
*
|
||||
* @returns A pointer to the received bytes. NULL, if there are no received bytes to process.
|
||||
*/
|
||||
const uint8_t *otPlatSerialGetReceivedBytes(uint16_t *aBufLength);
|
||||
|
||||
/**
|
||||
* Release received bytes.
|
||||
*/
|
||||
void otPlatSerialHandleReceiveDone();
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SERIAL_H_
|
||||
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
# Always package (e.g. for 'make dist') these subdirectories.
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
cli \
|
||||
core \
|
||||
$(NULL)
|
||||
|
||||
# Always build (e.g. for 'make all') these subdirectories.
|
||||
|
||||
SUBDIRS = \
|
||||
cli \
|
||||
core \
|
||||
$(NULL)
|
||||
|
||||
all:
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
lib_LIBRARIES = libopenthread-cli.a
|
||||
|
||||
libopenthread_cli_a_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/core \
|
||||
$(OPENTHREAD_TARGET_DEFINES) \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_cli_a_SOURCES = \
|
||||
cli.cpp \
|
||||
cli_serial.cpp \
|
||||
$(NULL)
|
||||
|
||||
include_HEADERS = \
|
||||
$(NULL)
|
||||
|
||||
install-headers: install-includeHEADERS
|
||||
|
||||
if OPENTHREAD_BUILD_COVERAGE
|
||||
CLEANFILES = $(wildcard *.gcda *.gcno)
|
||||
endif # OPENTHREAD_BUILD_COVERAGE
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,460 @@
|
||||
# OpenThread CLI Reference
|
||||
|
||||
The OpenThread CLI exposes configuration and management APIs via a
|
||||
command line interface. This CLI may be used to play with OpenThread
|
||||
and may be used along side additional application code. The
|
||||
OpenThread test scripts use this CLI to execute test cases.
|
||||
|
||||
## OpenThread Command List
|
||||
|
||||
* [channel](#channel)
|
||||
* [childtimeout](#childtimeout)
|
||||
* [contextreusedelay](#contextreusedelay)
|
||||
* [extaddr](#extaddr)
|
||||
* [extpanid](#extpanid)
|
||||
* [ipaddr](#ipaddr)
|
||||
* [keysequence](#keysequence)
|
||||
* [leaderweight](#leaderweight)
|
||||
* [masterkey](#masterkey)
|
||||
* [mode](#mode)
|
||||
* [netdataregister](#netdataregister)
|
||||
* [networkidtimeout](#networkidtimeout)
|
||||
* [networkname](#networkname)
|
||||
* [panid](#panid)
|
||||
* [ping](#ping)
|
||||
* [prefix](#prefix)
|
||||
* [releaserouterid](#releaserouterid)
|
||||
* [rloc16](#rloc16)
|
||||
* [route](#route)
|
||||
* [routerupgradethreshold](#routerupgradethreshold)
|
||||
* [start](#start)
|
||||
* [state](#state)
|
||||
* [stop](#stop)
|
||||
* [whitelist](#whitelist)
|
||||
|
||||
## OpenThread Command Details
|
||||
|
||||
### channel
|
||||
|
||||
Get the IEEE 802.15.4 Channel value.
|
||||
|
||||
```bash
|
||||
$ channel
|
||||
11
|
||||
Done
|
||||
```
|
||||
|
||||
### channel \<channel\>
|
||||
|
||||
Set the IEEE 802.15.4 Channel value.
|
||||
|
||||
```bash
|
||||
$ channel 11
|
||||
Done
|
||||
```
|
||||
|
||||
### childtimeout
|
||||
|
||||
Get the Thread Child Timeout value.
|
||||
|
||||
```bash
|
||||
$ childtimeout
|
||||
300
|
||||
Done
|
||||
```
|
||||
|
||||
### childtimeout \<timeout\>
|
||||
|
||||
Set the Thread Child Timeout value.
|
||||
|
||||
```bash
|
||||
$ childtimeout 300
|
||||
Done
|
||||
```
|
||||
|
||||
### contextreusedelay
|
||||
|
||||
Get the CONTEXT_ID_REUSE_DELAY value.
|
||||
|
||||
```bash
|
||||
$ contextreusedelay
|
||||
11
|
||||
Done
|
||||
```
|
||||
|
||||
### contextreusedelay \<delay\>
|
||||
|
||||
Set the CONTEXT_ID_REUSE_DELAY value.
|
||||
|
||||
```bash
|
||||
$ contextreusedelay 11
|
||||
Done
|
||||
```
|
||||
|
||||
### extaddr
|
||||
|
||||
Get the IEEE 802.15.4 Extended Address.
|
||||
|
||||
```bash
|
||||
$ extaddr
|
||||
0xdead00beef00cafe
|
||||
Done
|
||||
```
|
||||
|
||||
### extpanid
|
||||
|
||||
Get the Thread Extended PAN ID value.
|
||||
|
||||
```bash
|
||||
$ extpanid
|
||||
0xdead00beef00cafe
|
||||
Done
|
||||
```
|
||||
|
||||
### extpanid \<extpanid\>
|
||||
|
||||
Set the Thread Extended PAN ID value.
|
||||
|
||||
```bash
|
||||
$ extpanid dead00beef00cafe
|
||||
Done
|
||||
```
|
||||
|
||||
### ipaddr
|
||||
|
||||
List all IPv6 addresses assigned to the Thread interface.
|
||||
|
||||
```bash
|
||||
$ ipaddr
|
||||
fdde:ad00:beef:0:0:ff:fe00:0
|
||||
fe80:0:0:0:0:ff:fe00:0
|
||||
fdde:ad00:beef:0:558:f56b:d688:799
|
||||
fe80:0:0:0:f3d9:2a82:c8d8:fe43
|
||||
Done
|
||||
```
|
||||
|
||||
### ipaddr add \<ipaddr\>
|
||||
|
||||
Add an IPv6 address to the Thread interface.
|
||||
|
||||
```bash
|
||||
$ ipaddr add 2001::dead:beef:cafe
|
||||
Done
|
||||
```
|
||||
|
||||
### ipaddr del \<ipaddr\>
|
||||
|
||||
Add an IPv6 address to the Thread interface.
|
||||
|
||||
```bash
|
||||
$ ipaddr del 2001::dead:beef:cafe
|
||||
Done
|
||||
```
|
||||
|
||||
### keysequence
|
||||
|
||||
Get the Thread Key Sequence.
|
||||
|
||||
```bash
|
||||
$ keysequence
|
||||
10
|
||||
Done
|
||||
```
|
||||
|
||||
### keysequence \<keysequence\>
|
||||
|
||||
Set the Thread Key Sequence.
|
||||
|
||||
```bash
|
||||
$ keysequence 10
|
||||
Done
|
||||
```
|
||||
|
||||
### leaderweight
|
||||
|
||||
Get the Thread Leader Weight.
|
||||
|
||||
```bash
|
||||
$ leaderweight
|
||||
128
|
||||
Done
|
||||
```
|
||||
|
||||
### leaderweight \<weight\>
|
||||
|
||||
Set the Thread Leader Weight.
|
||||
|
||||
```bash
|
||||
$ leaderweight 128
|
||||
Done
|
||||
```
|
||||
|
||||
### masterkey
|
||||
|
||||
Get the Thread Master Key value.
|
||||
|
||||
```bash
|
||||
$ masterkey
|
||||
00112233445566778899aabbccddeeff
|
||||
Done
|
||||
```
|
||||
|
||||
### masterkey \<key\>
|
||||
|
||||
Set the Thread Master Key value.
|
||||
|
||||
```bash
|
||||
$ masterkey 00112233445566778899aabbccddeeff
|
||||
Done
|
||||
```
|
||||
|
||||
### mode
|
||||
|
||||
Get the Thread Device Mode value.
|
||||
|
||||
* r: rx-on-when-idle
|
||||
* s: Secure IEEE 802.15.4 Data Requests
|
||||
* d: Full Function Device
|
||||
* n: Full Network Data
|
||||
|
||||
```bash
|
||||
$ mode
|
||||
rsdn
|
||||
Done
|
||||
```
|
||||
|
||||
### mode [rsdn]
|
||||
|
||||
Set the Thread Device Mode value.
|
||||
|
||||
* r: rx-on-when-idle
|
||||
* s: Secure IEEE 802.15.4 Data Requests
|
||||
* d: Full Function Device
|
||||
* n: Full Network Data
|
||||
|
||||
```bash
|
||||
$ mode rsdn
|
||||
Done
|
||||
```
|
||||
|
||||
### netdataregister
|
||||
|
||||
Register local network data with Thread Leader.
|
||||
|
||||
```bash
|
||||
$ netdataregister
|
||||
Done
|
||||
```
|
||||
|
||||
### networkidtimeout
|
||||
|
||||
Get the NETWORK_ID_TIMEOUT parameter used in the Router role.
|
||||
|
||||
```bash
|
||||
$ networkidtimeout
|
||||
120
|
||||
Done
|
||||
```
|
||||
|
||||
### networkidtimeout \<timeout\>
|
||||
|
||||
Set the NETWORK_ID_TIMEOUT parameter used in the Router role.
|
||||
|
||||
```bash
|
||||
$ networkidtimeout 120
|
||||
Done
|
||||
```
|
||||
|
||||
### networkname
|
||||
|
||||
Get the Thread Network Name.
|
||||
|
||||
```bash
|
||||
$ networkname
|
||||
OpenThread
|
||||
Done
|
||||
```
|
||||
|
||||
### networkname \<name\>
|
||||
|
||||
Set the Thread Network Name.
|
||||
|
||||
```bash
|
||||
$ networkname OpenThread
|
||||
Done
|
||||
```
|
||||
|
||||
### panid
|
||||
|
||||
Get the IEEE 802.15.4 PAN ID value.
|
||||
|
||||
```bash
|
||||
$ panid
|
||||
0xdead
|
||||
Done
|
||||
```
|
||||
|
||||
### panid \<panid\>
|
||||
|
||||
Set the IEEE 802.15.4 PAN ID value.
|
||||
|
||||
```bash
|
||||
$ panid 0xdead
|
||||
Done
|
||||
```
|
||||
|
||||
### ping \<ipaddr\> [size]
|
||||
|
||||
Send an ICMPv6 Echo Request.
|
||||
|
||||
```bash
|
||||
$ ping fdde:ad00:beef:0:558:f56b:d688:799
|
||||
16 bytes from fdde:ad00:beef:0:558:f56b:d688:799: icmp_seq=1 hlim=64
|
||||
```
|
||||
|
||||
### prefix add \<prefix\> [pvdcsr] [prf]
|
||||
|
||||
Add a valid prefix to the Network Data.
|
||||
|
||||
* p: Stateless IPv6 Address Autoconfiguration Preferred flag
|
||||
* v: Stateless IPv6 Address Autoconfiguration Valid flag
|
||||
* d: DHCPv6 IPv6 Address Configuration flag
|
||||
* c: DHCPv6 Other Configuration flag
|
||||
* s: Stable flag
|
||||
* r: Default Route flag
|
||||
* prf: Default router preference. An integer in the range [-1, 1]
|
||||
|
||||
```bash
|
||||
$ prefix add 2001:dead:beef:cafe::/64 pvsr 0
|
||||
Done
|
||||
```
|
||||
|
||||
### prefix remove \<prefix\>
|
||||
|
||||
Invalidate a prefix in the network data.
|
||||
|
||||
```bash
|
||||
$ prefix remove 2001:dead:beef:cafe::/64
|
||||
Done
|
||||
```
|
||||
|
||||
### releaserouterid \<routerid\>
|
||||
Release a Router ID that has been allocated by the device in the Leader role.
|
||||
```bash
|
||||
$ releaserouterid 16
|
||||
Done
|
||||
```
|
||||
|
||||
### rloc16
|
||||
|
||||
Get the Thread RLOC16 value.
|
||||
|
||||
```bash
|
||||
$ rloc16
|
||||
0xdead
|
||||
Done
|
||||
```
|
||||
|
||||
### route add \<prefix\> [s] [prf]
|
||||
|
||||
Add a valid prefix to the Network Data.
|
||||
|
||||
* s: Stable flag
|
||||
* r: Default Route flag
|
||||
* prf: Default router preference. An integer in the range [-1, 1]
|
||||
|
||||
```bash
|
||||
$ route add 2001:dead:beef:cafe::/64 pvsr 0
|
||||
Done
|
||||
```
|
||||
|
||||
### route remove \<prefix\>
|
||||
|
||||
Invalidate a prefix in the network data.
|
||||
|
||||
```bash
|
||||
$ route remove 2001:dead:beef:cafe::/64
|
||||
Done
|
||||
```
|
||||
|
||||
### routerupgradethreshold
|
||||
|
||||
Get the ROUTER_UPGRADE_THRESHOLD value.
|
||||
|
||||
```bash
|
||||
$ routerupgradethreshold
|
||||
16
|
||||
Done
|
||||
```
|
||||
|
||||
### routerupgradethreshold \<threshold\>
|
||||
|
||||
Set the ROUTER_UPGRADE_THRESHOLD value.
|
||||
|
||||
```bash
|
||||
$ routerupgradethreshold 16
|
||||
Done
|
||||
```
|
||||
|
||||
### start
|
||||
|
||||
Enable OpenThread.
|
||||
|
||||
```bash
|
||||
$ start
|
||||
Done
|
||||
```
|
||||
|
||||
### stop
|
||||
|
||||
Disable OpenThread.
|
||||
|
||||
```bash
|
||||
$ stop
|
||||
Done
|
||||
```
|
||||
|
||||
### whitelist add \<extaddr\>
|
||||
|
||||
Add an IEEE 802.15.4 Extended Address to the whitelist.
|
||||
|
||||
```bash
|
||||
$ whitelist add dead00beef00cafe
|
||||
Done
|
||||
```
|
||||
|
||||
### whitelist clear
|
||||
|
||||
Clear all entries from the whitelist.
|
||||
|
||||
```bash
|
||||
$ whitelist clear
|
||||
Done
|
||||
```
|
||||
|
||||
### whitelist disable
|
||||
|
||||
Disable MAC whitelist filtering.
|
||||
|
||||
```bash
|
||||
$ whitelist disable
|
||||
Done
|
||||
```
|
||||
|
||||
### whitelist enable
|
||||
|
||||
Enable MAC whitelist filtering.
|
||||
|
||||
```bash
|
||||
$ whitelist enable
|
||||
Done
|
||||
```
|
||||
|
||||
### whitelist remove \<extaddr\>
|
||||
|
||||
Add an IEEE 802.15.4 Extended Address to the whitelist.
|
||||
|
||||
```bash
|
||||
$ whitelist add dead00beef00cafe
|
||||
Done
|
||||
```
|
||||
+1010
File diff suppressed because it is too large
Load Diff
+185
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains definitions for the CLI interpreter.
|
||||
*/
|
||||
|
||||
#ifndef CLI_HPP_
|
||||
#define CLI_HPP_
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <cli/cli_server.hpp>
|
||||
#include <net/icmp6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
/**
|
||||
* @namespace Thread::Cli
|
||||
*
|
||||
* @brief
|
||||
* This namespace contains definitions for the CLI interpreter.
|
||||
*
|
||||
*/
|
||||
namespace Cli {
|
||||
|
||||
/**
|
||||
* This class implements the response buffer for CLI command results.
|
||||
*
|
||||
*/
|
||||
class ResponseBuffer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the response buffer.
|
||||
*
|
||||
*/
|
||||
void Init(void) { mEnd = mBuffer; }
|
||||
|
||||
/**
|
||||
* This method appends output according to the format string.
|
||||
*
|
||||
* @param[in] fmt A pointer to the NULL-terminated format string.
|
||||
* @param[in] ... Arguments for the format specification.
|
||||
*
|
||||
*/
|
||||
void Append(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(mEnd, sizeof(mBuffer) - (mEnd - mBuffer), fmt, ap);
|
||||
va_end(ap);
|
||||
mEnd += strlen(mEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the response string.
|
||||
*
|
||||
* @returns A pointer to the response string.
|
||||
*
|
||||
*/
|
||||
const char *GetResponse(void) { return mBuffer; }
|
||||
|
||||
/**
|
||||
* This method returns the length of the response string.
|
||||
*
|
||||
* @returns The length to the response string.
|
||||
*
|
||||
*/
|
||||
uint16_t GetResponseLength(void) { return mEnd - mBuffer; }
|
||||
|
||||
private:
|
||||
char mBuffer[512];
|
||||
char *mEnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents a CLI command.
|
||||
*
|
||||
*/
|
||||
struct Command
|
||||
{
|
||||
const char *mName; ///< A pointer to the command string.
|
||||
void (*mCommand)(int argc, char *argv[]); ///< A function pointer to process the command.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements the CLI interpreter.
|
||||
*
|
||||
*/
|
||||
class Interpreter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method interprets a CLI command.
|
||||
*
|
||||
* @param[in] aBuf A pointer to a string.
|
||||
* @param[in] aBufLength The length of the string in bytes.
|
||||
* @param[in] aServer A reference to the CLI server.
|
||||
*
|
||||
*/
|
||||
static void ProcessLine(char *aBuf, uint16_t aBufLength, Server &aServer);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxArgs = 8,
|
||||
};
|
||||
|
||||
static void ProcessHelp(int argc, char *argv[]);
|
||||
static void ProcessChannel(int argc, char *argv[]);
|
||||
static void ProcessChildTimeout(int argc, char *argv[]);
|
||||
static void ProcessContextIdReuseDelay(int argc, char *argv[]);
|
||||
static void ProcessExtAddress(int argc, char *argv[]);
|
||||
static void ProcessExtPanId(int argc, char *argv[]);
|
||||
static void ProcessIpAddr(int argc, char *argv[]);
|
||||
static ThreadError ProcessIpAddrAdd(int argc, char *argv[]);
|
||||
static ThreadError ProcessIpAddrDel(int argc, char *argv[]);
|
||||
static void ProcessKeySequence(int argc, char *argv[]);
|
||||
static void ProcessLeaderWeight(int argc, char *argv[]);
|
||||
static void ProcessMasterKey(int argc, char *argv[]);
|
||||
static void ProcessMode(int argc, char *argv[]);
|
||||
static void ProcessNetworkDataRegister(int argc, char *argv[]);
|
||||
static void ProcessNetworkIdTimeout(int argc, char *argv[]);
|
||||
static void ProcessNetworkName(int argc, char *argv[]);
|
||||
static void ProcessPanId(int argc, char *argv[]);
|
||||
static void ProcessPing(int argc, char *argv[]);
|
||||
static void ProcessPrefix(int argc, char *argv[]);
|
||||
static ThreadError ProcessPrefixAdd(int argc, char *argv[]);
|
||||
static ThreadError ProcessPrefixRemove(int argc, char *argv[]);
|
||||
static void ProcessReleaseRouterId(int argc, char *argv[]);
|
||||
static void ProcessRoute(int argc, char *argv[]);
|
||||
static ThreadError ProcessRouteAdd(int argc, char *argv[]);
|
||||
static ThreadError ProcessRouteRemove(int argc, char *argv[]);
|
||||
static void ProcessRouterUpgradeThreshold(int argc, char *argv[]);
|
||||
static void ProcessRloc16(int argc, char *argv[]);
|
||||
static void ProcessShutdown(int argc, char *argv[]);
|
||||
static void ProcessStart(int argc, char *argv[]);
|
||||
static void ProcessState(int argc, char *argv[]);
|
||||
static void ProcessStop(int argc, char *argv[]);
|
||||
static void ProcessWhitelist(int argc, char *argv[]);
|
||||
|
||||
static void HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
static int Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength);
|
||||
static ThreadError ParseLong(char *argv, long &value);
|
||||
|
||||
static const struct Command sCommands[];
|
||||
static ResponseBuffer sResponse;
|
||||
|
||||
static otNetifAddress sAddress;
|
||||
|
||||
static Ip6::SockAddr sSockAddr;
|
||||
static Ip6::IcmpEcho sIcmpEcho;
|
||||
static Server *sServer;
|
||||
static uint8_t sEchoRequest[];
|
||||
};
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
|
||||
#endif // CLI_HPP_
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the CLI server on the serial service.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cli/cli.hpp>
|
||||
#include <cli/cli_serial.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/encoding.hpp>
|
||||
#include <common/tasklet.hpp>
|
||||
#include <platform/serial.h>
|
||||
|
||||
namespace Thread {
|
||||
namespace Cli {
|
||||
|
||||
static const uint8_t sEraseString[] = {'\b', ' ', '\b'};
|
||||
static const uint8_t CRNL[] = {'\r', '\n'};
|
||||
static Serial *sServer;
|
||||
|
||||
Tasklet Serial::sReceiveTask(&ReceiveTask, NULL);
|
||||
|
||||
Serial::Serial(void)
|
||||
{
|
||||
sServer = this;
|
||||
}
|
||||
|
||||
ThreadError Serial::Start(void)
|
||||
{
|
||||
mRxLength = 0;
|
||||
otPlatSerialEnable();
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
extern "C" void otPlatSerialSignalSendDone(void)
|
||||
{
|
||||
}
|
||||
|
||||
extern "C" void otPlatSerialSignalReceive(void)
|
||||
{
|
||||
Serial::sReceiveTask.Post();
|
||||
}
|
||||
|
||||
void Serial::ReceiveTask(void *aContext)
|
||||
{
|
||||
sServer->ReceiveTask();
|
||||
}
|
||||
|
||||
void Serial::ReceiveTask(void)
|
||||
{
|
||||
uint16_t bufLength;
|
||||
const uint8_t *buf;
|
||||
const uint8_t *cur;
|
||||
const uint8_t *end;
|
||||
|
||||
buf = otPlatSerialGetReceivedBytes(&bufLength);
|
||||
|
||||
end = buf + bufLength;
|
||||
|
||||
for (cur = buf; cur < end; cur++)
|
||||
{
|
||||
switch (*cur)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
otPlatSerialSend(CRNL, sizeof(CRNL));
|
||||
break;
|
||||
|
||||
default:
|
||||
otPlatSerialSend(cur, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (bufLength > 0 && mRxLength < kRxBufferSize)
|
||||
{
|
||||
switch (*buf)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
if (mRxLength > 0)
|
||||
{
|
||||
mRxBuffer[mRxLength] = '\0';
|
||||
ProcessCommand();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
case 127:
|
||||
if (mRxLength > 0)
|
||||
{
|
||||
mRxBuffer[--mRxLength] = '\0';
|
||||
otPlatSerialSend(sEraseString, sizeof(sEraseString));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
mRxBuffer[mRxLength++] = *buf;
|
||||
break;
|
||||
}
|
||||
|
||||
buf++;
|
||||
bufLength--;
|
||||
}
|
||||
|
||||
otPlatSerialHandleReceiveDone();
|
||||
}
|
||||
|
||||
ThreadError Serial::ProcessCommand(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
if (mRxBuffer[mRxLength - 1] == '\n')
|
||||
{
|
||||
mRxBuffer[--mRxLength] = '\0';
|
||||
}
|
||||
|
||||
if (mRxBuffer[mRxLength - 1] == '\r')
|
||||
{
|
||||
mRxBuffer[--mRxLength] = '\0';
|
||||
}
|
||||
|
||||
Interpreter::ProcessLine(mRxBuffer, mRxLength, *this);
|
||||
|
||||
mRxLength = 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Serial::Output(const char *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
return otPlatSerialSend(reinterpret_cast<const uint8_t *>(aBuf), aBufLength);
|
||||
}
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains definitions for a CLI server on the serial service.
|
||||
*/
|
||||
|
||||
#ifndef CLI_SERIAL_HPP_
|
||||
#define CLI_SERIAL_HPP_
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <cli/cli_server.hpp>
|
||||
#include <common/tasklet.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Cli {
|
||||
|
||||
/**
|
||||
* This class implements the CLI server on top of the serial platform abstraction.
|
||||
*
|
||||
*/
|
||||
class Serial: public Server
|
||||
{
|
||||
public:
|
||||
Serial(void);
|
||||
|
||||
/**
|
||||
* This method starts the CLI server.
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the server.
|
||||
*
|
||||
*/
|
||||
ThreadError Start(void);
|
||||
|
||||
/**
|
||||
* This method delivers output to the client.
|
||||
*
|
||||
* @param[in] aBuf A pointer to a buffer.
|
||||
* @param[in] aBufLength Number of bytes in the buffer.
|
||||
*
|
||||
* @retval kThreadError_None Successfully delivered output the client.
|
||||
*
|
||||
*/
|
||||
ThreadError Output(const char *aBuf, uint16_t aBufLength);
|
||||
|
||||
static Tasklet sReceiveTask;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kRxBufferSize = 128,
|
||||
};
|
||||
|
||||
static void ReceiveTask(void *aContext);
|
||||
|
||||
ThreadError ProcessCommand(void);
|
||||
void ReceiveTask(void);
|
||||
|
||||
char mRxBuffer[kRxBufferSize];
|
||||
uint16_t mRxLength;
|
||||
};
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
|
||||
#endif // CLI_SERIAL_HPP_
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains definitions for adding a CLI command to the CLI server.
|
||||
*/
|
||||
|
||||
#ifndef CLI_SERVER_HPP_
|
||||
#define CLI_SERVER_HPP_
|
||||
|
||||
#include <common/message.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Cli {
|
||||
|
||||
/**
|
||||
* This class implements the CLI server.
|
||||
*
|
||||
*/
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method starts the CLI server.
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the server.
|
||||
*
|
||||
*/
|
||||
virtual ThreadError Start() = 0;
|
||||
|
||||
/**
|
||||
* This method delivers output to the client.
|
||||
*
|
||||
* @param[in] aBuf A pointer to a buffer.
|
||||
* @param[in] aBufLength Number of bytes in the buffer.
|
||||
*
|
||||
* @retval kThreadError_None Successfully delivered output the client.
|
||||
*
|
||||
*/
|
||||
virtual ThreadError Output(const char *aBuf, uint16_t aBufLength) = 0;
|
||||
};
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
|
||||
#endif // CLI_SERVER_HPP_
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the CLI server on a UDP socket.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cli/cli.hpp>
|
||||
#include <cli/cli_udp.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Cli {
|
||||
|
||||
ThreadError Udp::Start(void)
|
||||
{
|
||||
ThreadError error;
|
||||
|
||||
otSockAddr sockaddr = {};
|
||||
sockaddr.mPort = 7335;
|
||||
|
||||
SuccessOrExit(error = otOpenUdpSocket(&mSocket, &HandleUdpReceive, this));
|
||||
SuccessOrExit(error = otBindUdpSocket(&mSocket, &sockaddr));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Udp::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
Udp *obj = reinterpret_cast<Udp *>(aContext);
|
||||
obj->HandleUdpReceive(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void Udp::HandleUdpReceive(otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint16_t payloadLength = otGetMessageLength(aMessage) - otGetMessageOffset(aMessage);
|
||||
char buf[512];
|
||||
|
||||
VerifyOrExit(payloadLength <= sizeof(buf), ;);
|
||||
otReadMessage(aMessage, otGetMessageOffset(aMessage), buf, payloadLength);
|
||||
|
||||
if (buf[payloadLength - 1] == '\n')
|
||||
{
|
||||
buf[--payloadLength] = '\0';
|
||||
}
|
||||
|
||||
if (buf[payloadLength - 1] == '\r')
|
||||
{
|
||||
buf[--payloadLength] = '\0';
|
||||
}
|
||||
|
||||
mPeer = *aMessageInfo;
|
||||
|
||||
Interpreter::ProcessLine(buf, payloadLength, *this);
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
ThreadError Udp::Output(const char *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
otMessage message;
|
||||
|
||||
VerifyOrExit((message = otNewUdpMessage()) != NULL, error = kThreadError_NoBufs);
|
||||
SuccessOrExit(error = otSetMessageLength(message, aBufLength));
|
||||
otWriteMessage(message, 0, aBuf, aBufLength);
|
||||
SuccessOrExit(error = otSendUdp(&mSocket, message, &mPeer));
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
otFreeMessage(message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains definitions for a CLI server on a UDP socket.
|
||||
*/
|
||||
|
||||
#ifndef CLI_UDP_HPP_
|
||||
#define CLI_UDP_HPP_
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <cli/cli_server.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Cli {
|
||||
|
||||
/**
|
||||
* This class implements the CLI server on top of a UDP socket.
|
||||
*
|
||||
*/
|
||||
class Udp: public Server
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method starts the CLI server.
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the server.
|
||||
*
|
||||
*/
|
||||
ThreadError Start(void) final;
|
||||
|
||||
/**
|
||||
* This method delivers output to the client.
|
||||
*
|
||||
* @param[in] aBuf A pointer to a buffer.
|
||||
* @param[in] aBufLength Number of bytes in the buffer.
|
||||
*
|
||||
* @retval kThreadError_None Successfully delivered output the client.
|
||||
*
|
||||
*/
|
||||
ThreadError Output(const char *aBuf, uint16_t aBufLength) final;
|
||||
|
||||
private:
|
||||
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleUdpReceive(otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
otUdpSocket mSocket;
|
||||
otMessageInfo mPeer;
|
||||
};
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
|
||||
#endif // CLI_UDP_HPP_
|
||||
@@ -0,0 +1,79 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
lib_LIBRARIES = libopenthread.a
|
||||
|
||||
libopenthread_a_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
$(OPENTHREAD_TARGET_DEFINES) \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_a_SOURCES = \
|
||||
openthread.cpp \
|
||||
coap/coap_header.cpp \
|
||||
coap/coap_server.cpp \
|
||||
common/logging.cpp \
|
||||
common/message.cpp \
|
||||
common/tasklet.cpp \
|
||||
common/timer.cpp \
|
||||
crypto/aes_ccm.cpp \
|
||||
mac/mac.cpp \
|
||||
mac/mac_frame.cpp \
|
||||
mac/mac_whitelist.cpp \
|
||||
net/icmp6.cpp \
|
||||
net/ip6.cpp \
|
||||
net/ip6_address.cpp \
|
||||
net/ip6_mpl.cpp \
|
||||
net/ip6_routes.cpp \
|
||||
net/netif.cpp \
|
||||
net/udp6.cpp \
|
||||
thread/address_resolver.cpp \
|
||||
thread/key_manager.cpp \
|
||||
thread/lowpan.cpp \
|
||||
thread/mesh_forwarder.cpp \
|
||||
thread/mle.cpp \
|
||||
thread/mle_router.cpp \
|
||||
thread/mle_tlvs.cpp \
|
||||
thread/network_data.cpp \
|
||||
thread/network_data_local.cpp \
|
||||
thread/network_data_leader.cpp \
|
||||
thread/thread_netif.cpp \
|
||||
thread/thread_tlvs.cpp \
|
||||
$(NULL)
|
||||
|
||||
include_HEADERS = \
|
||||
$(NULL)
|
||||
|
||||
install-headers: install-includeHEADERS
|
||||
|
||||
if OPENTHREAD_BUILD_COVERAGE
|
||||
CLEANFILES = $(wildcard *.gcda *.gcno)
|
||||
endif # OPENTHREAD_BUILD_COVERAGE
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the CoAP header generation and parsing.
|
||||
*/
|
||||
|
||||
#include <coap/coap_header.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/encoding.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Coap {
|
||||
|
||||
void Header::Init(void)
|
||||
{
|
||||
mHeaderLength = kMinHeaderLength;
|
||||
mOptionLast = 0;
|
||||
mNextOptionOffset = 0;
|
||||
memset(&mOption, 0, sizeof(mOption));
|
||||
memset(mHeader, 0, sizeof(mHeader));
|
||||
}
|
||||
|
||||
ThreadError Header::FromMessage(const Message &aMessage)
|
||||
{
|
||||
ThreadError error = kThreadError_Parse;
|
||||
uint16_t offset = aMessage.GetOffset();
|
||||
uint16_t length = aMessage.GetLength() - aMessage.GetOffset();
|
||||
uint8_t tokenLength;
|
||||
bool firstOption = true;
|
||||
uint16_t optionDelta;
|
||||
uint16_t optionLength;
|
||||
|
||||
VerifyOrExit(length >= kTokenOffset, error = kThreadError_Parse);
|
||||
aMessage.Read(offset, kTokenOffset, mHeader);
|
||||
mHeaderLength = kTokenOffset;
|
||||
offset += kTokenOffset;
|
||||
length -= kTokenOffset;
|
||||
|
||||
VerifyOrExit(GetVersion() == 1, error = kThreadError_Parse);
|
||||
|
||||
tokenLength = GetTokenLength();
|
||||
VerifyOrExit(tokenLength <= kMaxTokenLength && tokenLength < length, error = kThreadError_Parse);
|
||||
aMessage.Read(offset, tokenLength, mHeader + mHeaderLength);
|
||||
mHeaderLength += tokenLength;
|
||||
offset += tokenLength;
|
||||
length -= tokenLength;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
aMessage.Read(offset, 5, mHeader + mHeaderLength);
|
||||
|
||||
if (mHeader[mHeaderLength] == 0xff)
|
||||
{
|
||||
mHeaderLength += sizeof(uint8_t);
|
||||
ExitNow(error = kThreadError_None);
|
||||
}
|
||||
|
||||
optionDelta = mHeader[mHeaderLength] >> 4;
|
||||
optionLength = mHeader[mHeaderLength] & 0xf;
|
||||
mHeaderLength += sizeof(uint8_t);
|
||||
offset += sizeof(uint8_t);
|
||||
length -= sizeof(uint8_t);
|
||||
|
||||
if (optionDelta < kOption1ByteExtension)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else if (optionDelta == kOption1ByteExtension)
|
||||
{
|
||||
optionDelta = kOption1ByteExtensionOffset + mHeader[mHeaderLength];
|
||||
mHeaderLength += sizeof(uint8_t);
|
||||
offset += sizeof(uint8_t);
|
||||
length -= sizeof(uint8_t);
|
||||
}
|
||||
else if (optionDelta == kOption2ByteExtension)
|
||||
{
|
||||
optionDelta = kOption2ByteExtensionOffset + ((static_cast<uint16_t>(mHeader[mHeaderLength]) << 8) |
|
||||
mHeader[mHeaderLength + 1]);
|
||||
mHeaderLength += sizeof(uint16_t);
|
||||
offset += sizeof(uint16_t);
|
||||
length -= sizeof(uint16_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = kThreadError_Parse);
|
||||
}
|
||||
|
||||
if (optionLength < kOption1ByteExtension)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else if (optionLength == kOption1ByteExtension)
|
||||
{
|
||||
optionLength = kOption1ByteExtensionOffset + mHeader[mHeaderLength];
|
||||
mHeaderLength += sizeof(uint8_t);
|
||||
offset += sizeof(uint8_t);
|
||||
length -= sizeof(uint8_t);
|
||||
}
|
||||
else if (optionLength == kOption2ByteExtension)
|
||||
{
|
||||
optionLength = kOption2ByteExtensionOffset + ((static_cast<uint16_t>(mHeader[mHeaderLength]) << 8) |
|
||||
mHeader[mHeaderLength + 1]);
|
||||
mHeaderLength += sizeof(uint16_t);
|
||||
offset += sizeof(uint16_t);
|
||||
length -= sizeof(uint16_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = kThreadError_Parse);
|
||||
}
|
||||
|
||||
if (firstOption)
|
||||
{
|
||||
mOption.mNumber = optionDelta;
|
||||
mOption.mLength = optionLength;
|
||||
mOption.mValue = mHeader + mHeaderLength;
|
||||
mNextOptionOffset = mHeaderLength + optionLength;
|
||||
firstOption = false;
|
||||
}
|
||||
|
||||
VerifyOrExit(optionLength <= length, error = kThreadError_Parse);
|
||||
aMessage.Read(offset, optionLength, mHeader + mHeaderLength);
|
||||
mHeaderLength += optionLength;
|
||||
offset += optionLength;
|
||||
length -= optionLength;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Header::AppendOption(const Option &aOption)
|
||||
{
|
||||
uint8_t *buf = mHeader + mHeaderLength;
|
||||
uint8_t *cur = buf + 1;
|
||||
uint16_t optionDelta = aOption.mNumber - mOptionLast;
|
||||
uint16_t optionLength;
|
||||
|
||||
if (optionDelta < kOption1ByteExtensionOffset)
|
||||
{
|
||||
*buf = optionDelta << Option::kOptionDeltaOffset;
|
||||
}
|
||||
else if (optionDelta < kOption2ByteExtensionOffset)
|
||||
{
|
||||
*buf |= kOption1ByteExtension << Option::kOptionDeltaOffset;
|
||||
*cur++ = optionDelta - kOption1ByteExtensionOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buf |= kOption2ByteExtension << Option::kOptionDeltaOffset;
|
||||
optionDelta -= kOption2ByteExtensionOffset;
|
||||
*cur++ = optionDelta >> 8;
|
||||
*cur++ = optionDelta;
|
||||
}
|
||||
|
||||
if (aOption.mLength < kOption1ByteExtensionOffset)
|
||||
{
|
||||
*buf |= aOption.mLength;
|
||||
}
|
||||
else if (aOption.mLength < kOption2ByteExtensionOffset)
|
||||
{
|
||||
*buf |= kOption1ByteExtension;
|
||||
*cur++ = aOption.mLength - kOption1ByteExtensionOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buf |= kOption2ByteExtension;
|
||||
optionLength = aOption.mLength - kOption2ByteExtensionOffset;
|
||||
*cur++ = optionLength >> 8;
|
||||
*cur++ = optionLength;
|
||||
}
|
||||
|
||||
memcpy(cur, aOption.mValue, aOption.mLength);
|
||||
cur += aOption.mLength;
|
||||
|
||||
mHeaderLength += cur - buf;
|
||||
mOptionLast = aOption.mNumber;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Header::AppendUriPathOptions(const char *aUriPath)
|
||||
{
|
||||
const char *cur = aUriPath;
|
||||
const char *end;
|
||||
Header::Option coapOption;
|
||||
|
||||
coapOption.mNumber = Option::kOptionUriPath;
|
||||
|
||||
while ((end = strchr(cur, '/')) != NULL)
|
||||
{
|
||||
coapOption.mLength = end - cur;
|
||||
coapOption.mValue = reinterpret_cast<const uint8_t *>(cur);
|
||||
AppendOption(coapOption);
|
||||
cur = end + 1;
|
||||
}
|
||||
|
||||
coapOption.mLength = strlen(cur);
|
||||
coapOption.mValue = reinterpret_cast<const uint8_t *>(cur);
|
||||
AppendOption(coapOption);
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Header::AppendContentFormatOption(MediaType aType)
|
||||
{
|
||||
Option coapOption;
|
||||
uint8_t type = aType;
|
||||
|
||||
coapOption.mNumber = Option::kOptionContentFormat;
|
||||
coapOption.mLength = 1;
|
||||
coapOption.mValue = &type;
|
||||
AppendOption(coapOption);
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
const Header::Option *Header::GetCurrentOption(void) const
|
||||
{
|
||||
return &mOption;
|
||||
}
|
||||
|
||||
const Header::Option *Header::GetNextOption(void)
|
||||
{
|
||||
Option *rval = NULL;
|
||||
uint16_t optionDelta;
|
||||
uint16_t optionLength;
|
||||
|
||||
VerifyOrExit(mNextOptionOffset < mHeaderLength, ;);
|
||||
|
||||
optionDelta = mHeader[mNextOptionOffset] >> 4;
|
||||
optionLength = mHeader[mNextOptionOffset] & 0xf;
|
||||
mNextOptionOffset += sizeof(uint8_t);
|
||||
|
||||
if (optionDelta < kOption1ByteExtension)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else if (optionDelta == kOption1ByteExtension)
|
||||
{
|
||||
optionDelta = kOption1ByteExtensionOffset + mHeader[mNextOptionOffset];
|
||||
mNextOptionOffset += sizeof(uint8_t);
|
||||
}
|
||||
else if (optionDelta == kOption2ByteExtension)
|
||||
{
|
||||
optionDelta = kOption2ByteExtensionOffset + ((static_cast<uint16_t>(mHeader[mNextOptionOffset]) << 8) |
|
||||
mHeader[mNextOptionOffset + 1]);
|
||||
mNextOptionOffset += sizeof(uint16_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (optionLength < kOption1ByteExtension)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else if (optionLength == kOption1ByteExtension)
|
||||
{
|
||||
optionLength = kOption1ByteExtensionOffset + mHeader[mNextOptionOffset];
|
||||
mNextOptionOffset += sizeof(uint8_t);
|
||||
}
|
||||
else if (optionLength == kOption2ByteExtension)
|
||||
{
|
||||
optionLength = kOption2ByteExtensionOffset + ((static_cast<uint16_t>(mHeader[mNextOptionOffset]) << 8) |
|
||||
mHeader[mNextOptionOffset + 1]);
|
||||
mNextOptionOffset += sizeof(uint16_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
mOption.mNumber += optionDelta;
|
||||
mOption.mLength = optionLength;
|
||||
mOption.mValue = mHeader + mNextOptionOffset;
|
||||
mNextOptionOffset += optionLength;
|
||||
rval = &mOption;
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
} // namespace Coap
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for generating and processing CoAP headers.
|
||||
*/
|
||||
|
||||
#ifndef COAP_HEADER_HPP_
|
||||
#define COAP_HEADER_HPP_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <common/message.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
/**
|
||||
* @namespace Thread::Coap
|
||||
* @brief
|
||||
* This namespace includes definitions for CoAP.
|
||||
*
|
||||
*/
|
||||
namespace Coap {
|
||||
|
||||
/**
|
||||
* @addtogroup core-coap
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for CoAP.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements CoAP header generation and parsing.
|
||||
*
|
||||
*/
|
||||
class Header
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the CoAP header.
|
||||
*
|
||||
*/
|
||||
void Init(void);
|
||||
|
||||
/**
|
||||
* This method parses the CoAP header from a message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
* @retval kThreadError_None Successfully parsed the message.
|
||||
* @retval kThreadError_Parse Failed to parse the message.
|
||||
*
|
||||
*/
|
||||
ThreadError FromMessage(const Message &aMessage);
|
||||
|
||||
/**
|
||||
* This method returns the Version value.
|
||||
*
|
||||
* @returns The Version value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetVersion(void) const { return (mHeader[0] & kVersionMask) >> kVersionOffset; }
|
||||
|
||||
/**
|
||||
* This method sets the Version value.
|
||||
*
|
||||
* @param[in] aVersion The Version value.
|
||||
*
|
||||
*/
|
||||
void SetVersion(uint8_t aVersion) { mHeader[0] &= ~kVersionMask; mHeader[0] |= aVersion << kVersionOffset; }
|
||||
|
||||
/**
|
||||
* CoAP Type values.
|
||||
*
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
kTypeConfirmable = 0x00, ///< Confirmable
|
||||
kTypeNonConfirmable = 0x10, ///< Non-confirmable
|
||||
kTypeAcknowledgment = 0x20, ///< Acknowledgment
|
||||
kTypeReset = 0x30, ///< Reset
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns the Type value.
|
||||
*
|
||||
* @returns The Type value.
|
||||
*
|
||||
*/
|
||||
Type GetType(void) const { return static_cast<Header::Type>(mHeader[0] & kTypeMask); }
|
||||
|
||||
/**
|
||||
* This method sets the Type value.
|
||||
*
|
||||
* @param[in] aType The Type value.
|
||||
*
|
||||
*/
|
||||
void SetType(Type aType) { mHeader[0] &= ~kTypeMask; mHeader[0] |= aType; }
|
||||
|
||||
/**
|
||||
* CoAP Code values.
|
||||
*
|
||||
*/
|
||||
enum Code
|
||||
{
|
||||
kCodeGet = 0x01, ///< Get
|
||||
kCodePost = 0x02, ///< Post
|
||||
kCodePut = 0x03, ///< Put
|
||||
kCodeDelete = 0x04, ///< Delete
|
||||
kCodeChanged = 0x44, ///< Changed
|
||||
kCodeContent = 0x45, ///< Content
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns the Code value.
|
||||
*
|
||||
* @returns The Code value.
|
||||
*
|
||||
*/
|
||||
Code GetCode(void) const { return static_cast<Header::Code>(mHeader[1]); }
|
||||
|
||||
/**
|
||||
* This method sets the Code value.
|
||||
*
|
||||
* @param[in] aCode The Code value.
|
||||
*
|
||||
*/
|
||||
void SetCode(Code aCode) { mHeader[1] = aCode; }
|
||||
|
||||
/**
|
||||
* This method returns the Message ID value.
|
||||
*
|
||||
* @returns The Message ID value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetMessageId(void) const { return (static_cast<uint16_t>(mHeader[2]) << 8) | mHeader[3]; }
|
||||
|
||||
/**
|
||||
* This method sets the Message ID value.
|
||||
*
|
||||
* @param[in] aMessageId The Message ID value.
|
||||
*
|
||||
*/
|
||||
void SetMessageId(uint16_t aMessageId) { mHeader[2] = aMessageId >> 8; mHeader[3] = aMessageId; }
|
||||
|
||||
/**
|
||||
* This method returns the Token length.
|
||||
*
|
||||
* @returns The Token length.
|
||||
*
|
||||
*/
|
||||
uint8_t GetTokenLength(void) const { return (mHeader[0] & kTokenLengthMask) >> kTokenLengthOffset; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Token value.
|
||||
*
|
||||
* @returns A pointer to the Token value.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetToken(void) const { return mHeader + kTokenOffset; }
|
||||
|
||||
/**
|
||||
* This method sets the Token value and length.
|
||||
*
|
||||
* @param[in] aToken A pointer to the Token value.
|
||||
* @param[in] aTokenLength The Length of @p aToken.
|
||||
*
|
||||
*/
|
||||
void SetToken(const uint8_t *aToken, uint8_t aTokenLength) {
|
||||
mHeader[0] = (mHeader[0] & ~kTokenLengthMask) | (aTokenLength << kTokenLengthOffset);
|
||||
memcpy(mHeader + kTokenOffset, aToken, aTokenLength);
|
||||
mHeaderLength += aTokenLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* This structure represents a CoAP option.
|
||||
*
|
||||
*/
|
||||
struct Option
|
||||
{
|
||||
/**
|
||||
* Protocol Constants
|
||||
*
|
||||
*/
|
||||
enum
|
||||
{
|
||||
kOptionDeltaOffset = 4, ///< Delta
|
||||
};
|
||||
|
||||
/**
|
||||
* Option Numbers
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
kOptionUriPath = 11, ///< Uri-Path
|
||||
kOptionContentFormat = 12, ///< Content-Format
|
||||
};
|
||||
|
||||
uint16_t mNumber; ///< Option Number
|
||||
uint16_t mLength; ///< Option Length
|
||||
const uint8_t *mValue; ///< A pointer to the Option Value
|
||||
};
|
||||
|
||||
/**
|
||||
* This method appends a CoAP option.
|
||||
*
|
||||
* @param[in] aOption The CoAP Option.
|
||||
*
|
||||
* @retval kThreadError_None Successfully appended the option.
|
||||
* @retval kThreadError_InvalidArgs The option type is not equal or gerater than the last option type.
|
||||
*
|
||||
*/
|
||||
ThreadError AppendOption(const Option &aOption);
|
||||
|
||||
/**
|
||||
* This method appends a Uri-Path option.
|
||||
*
|
||||
* @param[in] aUriPath A pointer to a NULL-terminated string.
|
||||
*
|
||||
* @retval kThreadError_None Successfully appended the option.
|
||||
* @retval kThreadError_InvalidArgs The option type is not equal or gerater than the last option type.
|
||||
*
|
||||
*/
|
||||
ThreadError AppendUriPathOptions(const char *aUriPath);
|
||||
|
||||
/**
|
||||
* Media Types
|
||||
*
|
||||
*/
|
||||
enum MediaType
|
||||
{
|
||||
kApplicationOctetStream = 42, ///< application/octet-stream
|
||||
};
|
||||
|
||||
/**
|
||||
* This method appends a Content-Format option.
|
||||
*
|
||||
* @param[in] aType The Media Type value.
|
||||
*
|
||||
* @retval kThreadError_None Successfully appended the option.
|
||||
* @retval kThreadError_InvalidArgs The option type is not equal or gerater than the last option type.
|
||||
*
|
||||
*/
|
||||
ThreadError AppendContentFormatOption(MediaType aType);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the current option.
|
||||
*
|
||||
* @returns A pointer to the current option.
|
||||
*
|
||||
*/
|
||||
const Option *GetCurrentOption(void) const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the next option.
|
||||
*
|
||||
* @returns A pointer to the next option.
|
||||
*
|
||||
*/
|
||||
const Option *GetNextOption(void);
|
||||
|
||||
/**
|
||||
* This method terminates the CoAP header.
|
||||
*
|
||||
*/
|
||||
void Finalize(void) { mHeader[mHeaderLength++] = 0xff; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the first byte of the header.
|
||||
*
|
||||
* @returns A pointer to the first byte of the header.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetBytes(void) const { return mHeader; }
|
||||
|
||||
/**
|
||||
* This method returns the header length in bytes.
|
||||
*
|
||||
* @returns The header length in bytes.
|
||||
*
|
||||
*/
|
||||
uint8_t GetLength(void) const { return mHeaderLength; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Protocol Constants (RFC 7252).
|
||||
*
|
||||
*/
|
||||
enum
|
||||
{
|
||||
kVersionMask = 0xc0, ///< Version mask as specified (RFC 7252).
|
||||
kVersionOffset = 6, ///< Version offset as specified (RFC 7252).
|
||||
|
||||
kTokenLengthMask = 0x0f, ///< Token Length mask as specified (RFC 7252).
|
||||
kTokenLengthOffset = 0, ///< Token Length offset as specified (RFC 7252).
|
||||
kTokenOffset = 4, ///< Token offset as specified (RFC 7252).
|
||||
kMaxTokenLength = 8, ///< Max token length as specified (RFC 7252).
|
||||
|
||||
kOption1ByteExtension = 13, ///< Indicates a 1 byte extension (RFC 7252).
|
||||
kOption2ByteExtension = 14, ///< Indicates a 1 byte extension (RFC 7252).
|
||||
|
||||
kOption1ByteExtensionOffset = 13, ///< Delta/Length offset as specified (RFC 7252).
|
||||
kOption2ByteExtensionOffset = 269, ///< Delta/Length offset as specified (RFC 7252).
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kTypeMask = 0x30,
|
||||
kMinHeaderLength = 4,
|
||||
kMaxHeaderLength = 128,
|
||||
};
|
||||
uint8_t mHeader[kMaxHeaderLength];
|
||||
uint8_t mHeaderLength;
|
||||
uint16_t mOptionLast;
|
||||
uint16_t mNextOptionOffset;
|
||||
Option mOption;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Coap
|
||||
} // namespace Thread
|
||||
|
||||
#endif // COAP_HEADER_HPP_
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the CoAP server message dispatch.
|
||||
*/
|
||||
|
||||
#include <coap/coap_server.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Coap {
|
||||
|
||||
Server::Server(uint16_t aPort)
|
||||
{
|
||||
mPort = aPort;
|
||||
mResources = NULL;
|
||||
}
|
||||
|
||||
ThreadError Server::Start()
|
||||
{
|
||||
ThreadError error;
|
||||
Ip6::SockAddr sockaddr;
|
||||
sockaddr.mPort = mPort;
|
||||
|
||||
SuccessOrExit(error = mSocket.Open(&HandleUdpReceive, this));
|
||||
SuccessOrExit(error = mSocket.Bind(sockaddr));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Server::Stop()
|
||||
{
|
||||
return mSocket.Close();
|
||||
}
|
||||
|
||||
ThreadError Server::AddResource(Resource &aResource)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
for (Resource *cur = mResources; cur; cur = cur->mNext)
|
||||
{
|
||||
VerifyOrExit(cur != &aResource, error = kThreadError_Busy);
|
||||
}
|
||||
|
||||
aResource.mNext = mResources;
|
||||
mResources = &aResource;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Server::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
Server *obj = reinterpret_cast<Server *>(aContext);
|
||||
obj->HandleUdpReceive(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Header header;
|
||||
char uriPath[kMaxReceivedUriPath];
|
||||
char *curUriPath = uriPath;
|
||||
const Header::Option *coapOption;
|
||||
|
||||
SuccessOrExit(header.FromMessage(aMessage));
|
||||
aMessage.MoveOffset(header.GetLength());
|
||||
|
||||
coapOption = header.GetCurrentOption();
|
||||
|
||||
while (coapOption != NULL)
|
||||
{
|
||||
switch (coapOption->mNumber)
|
||||
{
|
||||
case Header::Option::kOptionUriPath:
|
||||
VerifyOrExit(coapOption->mLength < sizeof(uriPath) - (curUriPath - uriPath), ;);
|
||||
memcpy(curUriPath, coapOption->mValue, coapOption->mLength);
|
||||
curUriPath[coapOption->mLength] = '/';
|
||||
curUriPath += coapOption->mLength + 1;
|
||||
break;
|
||||
|
||||
case Header::Option::kOptionContentFormat:
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
coapOption = header.GetNextOption();
|
||||
}
|
||||
|
||||
curUriPath[-1] = '\0';
|
||||
|
||||
for (Resource *resource = mResources; resource; resource = resource->mNext)
|
||||
{
|
||||
if (strcmp(resource->mUriPath, uriPath) == 0)
|
||||
{
|
||||
resource->HandleRequest(header, aMessage, aMessageInfo);
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
ThreadError Server::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return mSocket.SendTo(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
} // namespace Coap
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for the CoAP server.
|
||||
*/
|
||||
|
||||
#ifndef COAP_SERVER_HPP_
|
||||
#define COAP_SERVER_HPP_
|
||||
|
||||
#include <coap/coap_header.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <net/udp6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Coap {
|
||||
|
||||
/**
|
||||
* @addtogroup core-coap
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements CoAP resource handling.
|
||||
*
|
||||
*/
|
||||
class Resource
|
||||
{
|
||||
friend class Server;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when a CoAP message with a given Uri-Path is received.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aHeader A reference to the CoAP header.
|
||||
* @param[in] aMessage A reference to the message.
|
||||
* @param[in] aMessageInfo A reference to the message info for @p aMessage.
|
||||
*
|
||||
*/
|
||||
typedef void (*CoapMessageHandler)(void *aContext, Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This constructor initializes the resource.
|
||||
*
|
||||
* @param[in] aUriPath A pointer to a NULL-terminated string for the Uri-Path.
|
||||
* @param[in] aHandler A function pointer that is called when receiving a CoAP message for @p aUriPath.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*/
|
||||
Resource(const char *aUriPath, CoapMessageHandler aHandler, void *aContext) {
|
||||
mUriPath = aUriPath;
|
||||
mHandler = aHandler;
|
||||
mContext = aContext;
|
||||
}
|
||||
|
||||
private:
|
||||
void HandleRequest(Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) {
|
||||
mHandler(mContext, aHeader, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
const char *mUriPath;
|
||||
CoapMessageHandler mHandler;
|
||||
void *mContext;
|
||||
Resource *mNext;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements the CoAP server.
|
||||
*
|
||||
*/
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
*/
|
||||
explicit Server(uint16_t aPort);
|
||||
|
||||
/**
|
||||
* This method starts the CoAP server.
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the CoAP server.
|
||||
*
|
||||
*/
|
||||
ThreadError Start();
|
||||
|
||||
/**
|
||||
* This method stops the CoAP server.
|
||||
*
|
||||
* @retval kThreadError_None Successfully stopped the CoAP server.
|
||||
*
|
||||
*/
|
||||
ThreadError Stop();
|
||||
|
||||
/**
|
||||
* This method adds a resource to the CoAP server.
|
||||
*
|
||||
* @param[in] aResource A reference to the resource.
|
||||
*
|
||||
* @retval kThreadError_None Successfully added @p aResource.
|
||||
* @retval kThreadError_Busy The @p aResource was alerady added.
|
||||
*
|
||||
*/
|
||||
ThreadError AddResource(Resource &aResource);
|
||||
|
||||
/**
|
||||
* This method sends a CoAP response from the server.
|
||||
*
|
||||
* @param[in] aMessage The CoAP response to send.
|
||||
* @param[in] aMessageInfo The message info corresponding to @p aMessage.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the CoAP response message.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers available to send the CoAP response.
|
||||
*
|
||||
*/
|
||||
ThreadError SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxReceivedUriPath = 32, ///< Maximum supported URI path on received messages.
|
||||
};
|
||||
|
||||
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
Ip6::UdpSocket mSocket;
|
||||
uint16_t mPort;
|
||||
Resource *mResources;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Coap
|
||||
} // namespace Thread
|
||||
|
||||
#endif // COAP_SERVER_HPP_
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes macros for validating runtime conditions.
|
||||
*/
|
||||
|
||||
#ifndef CODE_UTILS_HPP_
|
||||
#define CODE_UTILS_HPP_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SuccessOrExit(ERR) \
|
||||
do { \
|
||||
if ((ERR) != 0) { \
|
||||
goto exit; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define VerifyOrExit(COND, ACTION) \
|
||||
do { \
|
||||
if (!(COND)) { \
|
||||
ACTION; \
|
||||
goto exit; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define ExitNow(...) \
|
||||
do { \
|
||||
__VA_ARGS__; \
|
||||
goto exit; \
|
||||
} while (false)
|
||||
|
||||
#endif // CODE_UTILS_HPP_
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes functions for debugging.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG_HPP_
|
||||
#define DEBUG_HPP_
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(OPENTHREAD_TARGET_DARWIN) || defined(OPENTHREAD_TARGET_LINUX)
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#else
|
||||
|
||||
#define assert(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
while (1) {} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // DEBUG_HPP_
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for byte-ordering encoding.
|
||||
*/
|
||||
|
||||
#ifndef ENCODING_HPP_
|
||||
#define ENCODING_HPP_
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Thread {
|
||||
namespace Encoding {
|
||||
|
||||
inline uint16_t Swap16(uint16_t v)
|
||||
{
|
||||
return
|
||||
((v & static_cast<uint16_t>(0x00ffU)) << 8) |
|
||||
((v & static_cast<uint16_t>(0xff00U)) >> 8);
|
||||
}
|
||||
|
||||
inline uint32_t Swap32(uint32_t v)
|
||||
{
|
||||
return
|
||||
((v & static_cast<uint32_t>(0x000000ffUL)) << 24) |
|
||||
((v & static_cast<uint32_t>(0x0000ff00UL)) << 8) |
|
||||
((v & static_cast<uint32_t>(0x00ff0000UL)) >> 8) |
|
||||
((v & static_cast<uint32_t>(0xff000000UL)) >> 24);
|
||||
}
|
||||
|
||||
inline uint64_t Swap64(uint64_t v)
|
||||
{
|
||||
return
|
||||
((v & static_cast<uint64_t>(0x00000000000000ffULL)) << 56) |
|
||||
((v & static_cast<uint64_t>(0x000000000000ff00ULL)) << 40) |
|
||||
((v & static_cast<uint64_t>(0x0000000000ff0000ULL)) << 24) |
|
||||
((v & static_cast<uint64_t>(0x00000000ff000000ULL)) << 8) |
|
||||
((v & static_cast<uint64_t>(0x000000ff00000000ULL)) >> 8) |
|
||||
((v & static_cast<uint64_t>(0x0000ff0000000000ULL)) >> 24) |
|
||||
((v & static_cast<uint64_t>(0x00ff000000000000ULL)) >> 40) |
|
||||
((v & static_cast<uint64_t>(0xff00000000000000ULL)) >> 56);
|
||||
}
|
||||
|
||||
#define BitVectorBytes(x) \
|
||||
(((x) + (CHAR_BIT-1)) / CHAR_BIT)
|
||||
|
||||
namespace BigEndian {
|
||||
|
||||
#if BYTE_ORDER_BIG_ENDIAN
|
||||
|
||||
inline uint16_t HostSwap16(uint16_t v) { return v; }
|
||||
inline uint32_t HostSwap32(uint32_t v) { return v; }
|
||||
inline uint64_t HostSwap64(uint64_t v) { return v; }
|
||||
|
||||
#else /* BYTE_ORDER_LITTLE_ENDIAN */
|
||||
|
||||
inline uint16_t HostSwap16(uint16_t v) { return Swap16(v); }
|
||||
inline uint32_t HostSwap32(uint32_t v) { return Swap32(v); }
|
||||
inline uint64_t HostSwap64(uint64_t v) { return Swap64(v); }
|
||||
|
||||
#endif // LITTLE_ENDIAN
|
||||
|
||||
} // namespace BigEndian
|
||||
|
||||
namespace LittleEndian {
|
||||
|
||||
#if BYTE_ORDER_BIG_ENDIAN
|
||||
|
||||
inline uint16_t HostSwap16(uint16_t v) { return Swap16(v); }
|
||||
inline uint32_t HostSwap32(uint32_t v) { return Swap32(v); }
|
||||
inline uint64_t HostSwap64(uint64_t v) { return Swap64(v); }
|
||||
|
||||
#else /* BYTE_ORDER_LITTLE_ENDIAN */
|
||||
|
||||
inline uint16_t HostSwap16(uint16_t v) { return v; }
|
||||
inline uint32_t HostSwap32(uint32_t v) { return v; }
|
||||
inline uint64_t HostSwap64(uint64_t v) { return v; }
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace LittleEndian
|
||||
} // namespace Encoding
|
||||
} // namespace Thread
|
||||
|
||||
#endif // ENCODING_HPP_
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the tasklet scheduler.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <platform/logging.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This static method outputs a line of the memory dump.
|
||||
*
|
||||
* @param[in] aLogLevel The log level.
|
||||
* @param[in] aLogRegion The log region.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes in the buffer.
|
||||
*
|
||||
*/
|
||||
static void DumpLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const void *aBuf, const int aLength)
|
||||
{
|
||||
char buf[80];
|
||||
char *cur = buf;
|
||||
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), "|");
|
||||
cur += strlen(cur);
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (i < aLength)
|
||||
{
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), " %02X", ((uint8_t *)(aBuf))[i]);
|
||||
cur += strlen(cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), " ..");
|
||||
cur += strlen(cur);
|
||||
}
|
||||
|
||||
if (!((i + 1) % 8))
|
||||
{
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), " |");
|
||||
cur += strlen(cur);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), " ");
|
||||
cur += strlen(cur);
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
char c = 0x7f & ((char *)(aBuf))[i];
|
||||
|
||||
if (i < aLength && isprint(c))
|
||||
{
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), "%c", c);
|
||||
cur += strlen(cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), ".");
|
||||
cur += strlen(cur);
|
||||
}
|
||||
}
|
||||
|
||||
otPlatLog(aLogLevel, aLogRegion, "%s\n", buf);
|
||||
}
|
||||
|
||||
void otDump(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aId, const void *aBuf, const int aLength)
|
||||
{
|
||||
int idlen = strlen(aId);
|
||||
const int width = 72;
|
||||
char buf[80];
|
||||
char *cur = buf;
|
||||
|
||||
otPlatLog(aLogLevel, aLogRegion, "\n");
|
||||
|
||||
for (int i = 0; i < (width - idlen) / 2 - 5; i++)
|
||||
{
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), "=");
|
||||
cur += strlen(cur);
|
||||
}
|
||||
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), "[%s len=%03d]", aId, aLength);
|
||||
cur += strlen(cur);
|
||||
|
||||
for (int i = 0; i < (width - idlen) / 2 - 4; i++)
|
||||
{
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), "=");
|
||||
cur += strlen(cur);
|
||||
}
|
||||
|
||||
otPlatLog(aLogLevel, aLogRegion, "%s\n", buf);
|
||||
|
||||
for (int i = 0; i < aLength; i += 16)
|
||||
{
|
||||
DumpLine(aLogLevel, aLogRegion, (uint8_t *)(aBuf) + i, (aLength - i) < 16 ? (aLength - i) : 16);
|
||||
}
|
||||
|
||||
cur = buf;
|
||||
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
snprintf(cur, sizeof(buf) - (cur - buf), "-");
|
||||
cur += strlen(cur);
|
||||
}
|
||||
|
||||
otPlatLog(aLogLevel, aLogRegion, "%s\n", buf);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes functions for debugging.
|
||||
*/
|
||||
|
||||
#ifndef LOGGING_HPP_
|
||||
#define LOGGING_HPP_
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <platform/logging.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpCrit
|
||||
*
|
||||
* This method generates a memory dump with log level critical.
|
||||
*
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OPENTHREAD_LOG_LEVEL_CRIT
|
||||
#define otDumpCrit(aRegion, aId, aBuf, aLength) otDump(kLogLevelCrit, aRegion, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpCrit(aRegion, aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpWarn
|
||||
*
|
||||
* This method generates a memory dump with log level warning.
|
||||
*
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OPENTHREAD_LOG_LEVEL_WARN
|
||||
#define otDumpWarn(aRegion, aId, aBuf, aLength) otDump(kLogLevelWarn, aRegion, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpWarn(aRegion, aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpInfo
|
||||
*
|
||||
* This method generates a memory dump with log level info.
|
||||
*
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OPENTHREAD_LOG_LEVEL_INFO
|
||||
#define otDumpInfo(aRegion, aId, aBuf, aLength) otDump(kLogLevelInfo, aRegion, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpInfo(aRegion, aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpDebg
|
||||
*
|
||||
* This method generates a memory dump with log level debug.
|
||||
*
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OPENTHREAD_LOG_LEVEL_DEBG
|
||||
#define otDumpDebg(aRegion, aId, aBuf, aLength) otDump(kLogLevelDebg, aRegion, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpDebg(aRegion, aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpCritNetData
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region Network Data.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpWarnNetData
|
||||
*
|
||||
* This method generates a memory dump with log level warning and region Network Data.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpInfoNetData
|
||||
*
|
||||
* This method generates a memory dump with log level info and region Network Data.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpDebgNetData
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region Network Data.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_NETDATA
|
||||
#define otDumpCritNetData(aId, aBuf, aLength) otDumpCrit(kLogRegionNetData, aId, aBuf, aLength)
|
||||
#define otDumpWarnNetData(aId, aBuf, aLength) otDumpWarn(kLogRegionNetData, aId, aBuf, aLength)
|
||||
#define otDumpInfoNetData(aId, aBuf, aLength) otDumpInfo(kLogRegionNetData, aId, aBuf, aLength)
|
||||
#define otDumpDebgNetData(aId, aBuf, aLength) otDumpDebg(kLogRegionNetData, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpCritNetData(aId, aBuf, aLength)
|
||||
#define otDumpWarnNetData(aId, aBuf, aLength)
|
||||
#define otDumpInfoNetData(aId, aBuf, aLength)
|
||||
#define otDumpDebgNetData(aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpCritMle
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region MLE.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpWarnMle
|
||||
*
|
||||
* This method generates a memory dump with log level warning and region MLE.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpInfoMle
|
||||
*
|
||||
* This method generates a memory dump with log level info and region MLE.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpDebgMle
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region MLE.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_MLE
|
||||
#define otDumpCritMle(aId, aBuf, aLength) otDumpCrit(kLogRegionMle, aId, aBuf, aLength)
|
||||
#define otDumpWarnMle(aId, aBuf, aLength) otDumpWarn(kLogRegionMle, aId, aBuf, aLength)
|
||||
#define otDumpInfoMle(aId, aBuf, aLength) otDumpInfo(kLogRegionMle, aId, aBuf, aLength)
|
||||
#define otDumpDebgMle(aId, aBuf, aLength) otDumpDebg(kLogRegionMle, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpCritMle(aId, aBuf, aLength)
|
||||
#define otDumpWarnMle(aId, aBuf, aLength)
|
||||
#define otDumpInfoMle(aId, aBuf, aLength)
|
||||
#define otDumpDebgMle(aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpCritArp
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region EID-to-RLOC mapping.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpWarnArp
|
||||
*
|
||||
* This method generates a memory dump with log level warning and region EID-to-RLOC mapping.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpInfoArp
|
||||
*
|
||||
* This method generates a memory dump with log level info and region EID-to-RLOC mapping.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpDebgArp
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region EID-to-RLOC mapping.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_ARP
|
||||
#define otDumpCritArp(aId, aBuf, aLength) otDumpCrit(kLogRegionArp, aId, aBuf, aLength)
|
||||
#define otDumpWarnArp(aId, aBuf, aLength) otDumpWarn(kLogRegionArp, aId, aBuf, aLength)
|
||||
#define otDumpInfoArp(aId, aBuf, aLength) otDumpInfo(kLogRegionArp, aId, aBuf, aLength)
|
||||
#define otDumpDebgArp(aId, aBuf, aLength) otDumpDebg(kLogRegionArp, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpCritArp(aId, aBuf, aLength)
|
||||
#define otDumpWarnArp(aId, aBuf, aLength)
|
||||
#define otDumpInfoArp(aId, aBuf, aLength)
|
||||
#define otDumpDebgArp(aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpCritIcmp
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region ICMPv6.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpWarnIcmp
|
||||
*
|
||||
* This method generates a memory dump with log level warning and region ICMPv6.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpInfoIcmp
|
||||
*
|
||||
* This method generates a memory dump with log level info and region ICMPv6.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpDebgIcmp
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region ICMPv6.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_ICMP
|
||||
#define otDumpCritIcmp(aId, aBuf, aLength) otDumpCrit(kLogRegionIcmp, aId, aBuf, aLength)
|
||||
#define otDumpWarnIcmp(aId, aBuf, aLength) otDumpWarn(kLogRegionIcmp, aId, aBuf, aLength)
|
||||
#define otDumpInfoIcmp(aId, aBuf, aLength) otDumpInfo(kLogRegionIcmp, aId, aBuf, aLength)
|
||||
#define otDumpDebgIcmp(aId, aBuf, aLength) otDumpDebg(kLogRegionIcmp, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpCritIcmp(aId, aBuf, aLength)
|
||||
#define otDumpWarnIcmp(aId, aBuf, aLength)
|
||||
#define otDumpInfoIcmp(aId, aBuf, aLength)
|
||||
#define otDumpDebgIcmp(aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpCritIp6
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region IPv6.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpWarnIp6
|
||||
*
|
||||
* This method generates a memory dump with log level warning and region IPv6.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpInfoIp6
|
||||
*
|
||||
* This method generates a memory dump with log level info and region IPv6.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpDebgIp6
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region IPv6.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_IP6
|
||||
#define otDumpCritIp6(aId, aBuf, aLength) otDumpCrit(kLogRegionIp6, aId, aBuf, aLength)
|
||||
#define otDumpWarnIp6(aId, aBuf, aLength) otDumpWarn(kLogRegionIp6, aId, aBuf, aLength)
|
||||
#define otDumpInfoIp6(aId, aBuf, aLength) otDumpInfo(kLogRegionIp6, aId, aBuf, aLength)
|
||||
#define otDumpDebgIp6(aId, aBuf, aLength) otDumpDebg(kLogRegionIp6, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpCritIp6(aId, aBuf, aLength)
|
||||
#define otDumpWarnIp6(aId, aBuf, aLength)
|
||||
#define otDumpInfoIp6(aId, aBuf, aLength)
|
||||
#define otDumpDebgIp6(aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpCritMac
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region MAC.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpWarnMac
|
||||
*
|
||||
* This method generates a memory dump with log level warning and region MAC.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpInfoMac
|
||||
*
|
||||
* This method generates a memory dump with log level info and region MAC.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpDebgMac
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region MAC.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_MAC
|
||||
#define otDumpCritMac(aId, aBuf, aLength) otDumpCrit(kLogRegionMac, aId, aBuf, aLength)
|
||||
#define otDumpWarnMac(aId, aBuf, aLength) otDumpWarn(kLogRegionMac, aId, aBuf, aLength)
|
||||
#define otDumpInfoMac(aId, aBuf, aLength) otDumpInfo(kLogRegionMac, aId, aBuf, aLength)
|
||||
#define otDumpDebgMac(aId, aBuf, aLength) otDumpDebg(kLogRegionMac, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpCritMac(aId, aBuf, aLength)
|
||||
#define otDumpWarnMac(aId, aBuf, aLength)
|
||||
#define otDumpInfoMac(aId, aBuf, aLength)
|
||||
#define otDumpDebgMac(aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def otDumpCritMem
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region memory.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpWarnMem
|
||||
*
|
||||
* This method generates a memory dump with log level warning and region memory.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpInfoMem
|
||||
*
|
||||
* This method generates a memory dump with log level info and region memory.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def otDumpDebgMem
|
||||
*
|
||||
* This method generates a memory dump with log level debug and region memory.
|
||||
*
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
#ifdef OPENTHREAD_CONFIG_LOG_MEM
|
||||
#define otDumpCritMem(aId, aBuf, aLength) otDumpCrit(kLogRegionMem, aId, aBuf, aLength)
|
||||
#define otDumpWarnMem(aId, aBuf, aLength) otDumpWarn(kLogRegionMem, aId, aBuf, aLength)
|
||||
#define otDumpInfoMem(aId, aBuf, aLength) otDumpInfo(kLogRegionMem, aId, aBuf, aLength)
|
||||
#define otDumpDebgMem(aId, aBuf, aLength) otDumpDebg(kLogRegionMem, aId, aBuf, aLength)
|
||||
#else
|
||||
#define otDumpCritMem(aId, aBuf, aLength)
|
||||
#define otDumpWarnMem(aId, aBuf, aLength)
|
||||
#define otDumpInfoMem(aId, aBuf, aLength)
|
||||
#define otDumpDebgMem(aId, aBuf, aLength)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method dumps bytes to the log in a human-readable fashion.
|
||||
*
|
||||
* @param[in] aLevel The log level.
|
||||
* @param[in] aRegion The log region.
|
||||
* @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
|
||||
* @param[in] aBuf A pointer to the buffer.
|
||||
* @param[in] aLength Number of bytes to print.
|
||||
*
|
||||
*/
|
||||
void otDump(otLogLevel aLevel, otLogRegion aRegion, const char *aId, const void *aBuf, const int aLength);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // LOGGING_HPP_
|
||||
@@ -0,0 +1,667 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the message buffer pool and message buffers.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <net/ip6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
static Buffer *NewBuffer(void);
|
||||
static ThreadError FreeBuffers(Buffer *aBuffer);
|
||||
static ThreadError ReclaimBuffers(int aNumBuffers);
|
||||
|
||||
static int sNumFreeBuffers;
|
||||
static Buffer sBuffers[kNumBuffers];
|
||||
static Buffer *sFreeBuffers;
|
||||
static MessageList sAll;
|
||||
|
||||
Buffer *NewBuffer(void)
|
||||
{
|
||||
Buffer *buffer = NULL;
|
||||
|
||||
VerifyOrExit(sFreeBuffers != NULL, ;);
|
||||
|
||||
buffer = sFreeBuffers;
|
||||
sFreeBuffers = sFreeBuffers->GetNextBuffer();
|
||||
buffer->SetNextBuffer(NULL);
|
||||
sNumFreeBuffers--;
|
||||
|
||||
exit:
|
||||
return buffer;
|
||||
}
|
||||
|
||||
ThreadError FreeBuffers(Buffer *aBuffer)
|
||||
{
|
||||
Buffer *tmpBuffer;
|
||||
|
||||
while (aBuffer != NULL)
|
||||
{
|
||||
tmpBuffer = aBuffer->GetNextBuffer();
|
||||
aBuffer->SetNextBuffer(sFreeBuffers);
|
||||
sFreeBuffers = aBuffer;
|
||||
sNumFreeBuffers++;
|
||||
aBuffer = tmpBuffer;
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError ReclaimBuffers(int aNumBuffers)
|
||||
{
|
||||
return (aNumBuffers <= sNumFreeBuffers) ? kThreadError_None : kThreadError_NoBufs;
|
||||
}
|
||||
|
||||
ThreadError Message::Init(void)
|
||||
{
|
||||
sFreeBuffers = sBuffers;
|
||||
|
||||
for (int i = 0; i < kNumBuffers - 1; i++)
|
||||
{
|
||||
sBuffers[i].SetNextBuffer(&sBuffers[i + 1]);
|
||||
}
|
||||
|
||||
sBuffers[kNumBuffers - 1].SetNextBuffer(NULL);
|
||||
sNumFreeBuffers = kNumBuffers;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
Message *Message::New(uint8_t aType, uint16_t aReserved)
|
||||
{
|
||||
Message *message = NULL;
|
||||
|
||||
VerifyOrExit((message = reinterpret_cast<Message *>(NewBuffer())) != NULL, ;);
|
||||
|
||||
memset(message, 0, sizeof(*message));
|
||||
message->SetType(aType);
|
||||
message->SetReserved(aReserved);
|
||||
|
||||
VerifyOrExit(message->SetLength(0) == kThreadError_None, Message::Free(*message));
|
||||
|
||||
exit:
|
||||
return message;
|
||||
}
|
||||
|
||||
ThreadError Message::Free(Message &aMessage)
|
||||
{
|
||||
assert(aMessage.GetMessageList(MessageInfo::kListAll).mList == NULL &&
|
||||
aMessage.GetMessageList(MessageInfo::kListInterface).mList == NULL);
|
||||
return FreeBuffers(reinterpret_cast<Buffer *>(&aMessage));
|
||||
}
|
||||
|
||||
ThreadError Message::ResizeMessage(uint16_t aLength)
|
||||
{
|
||||
// add buffers
|
||||
Buffer *curBuffer = this;
|
||||
Buffer *lastBuffer;
|
||||
uint16_t curLength = kHeadBufferDataSize;
|
||||
|
||||
while (curLength < aLength)
|
||||
{
|
||||
if (curBuffer->GetNextBuffer() == NULL)
|
||||
{
|
||||
curBuffer->SetNextBuffer(NewBuffer());
|
||||
}
|
||||
|
||||
curBuffer = curBuffer->GetNextBuffer();
|
||||
curLength += kBufferDataSize;
|
||||
}
|
||||
|
||||
// remove buffers
|
||||
lastBuffer = curBuffer;
|
||||
curBuffer = curBuffer->GetNextBuffer();
|
||||
lastBuffer->SetNextBuffer(NULL);
|
||||
|
||||
FreeBuffers(curBuffer);
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
Message *Message::GetNext(void) const
|
||||
{
|
||||
return GetMessageList(MessageInfo::kListInterface).mNext;
|
||||
}
|
||||
|
||||
uint16_t Message::GetLength(void) const
|
||||
{
|
||||
return mInfo.mLength;
|
||||
}
|
||||
|
||||
ThreadError Message::SetLength(uint16_t aLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint16_t totalLengthRequest = GetReserved() + aLength;
|
||||
uint16_t totalLengthCurrent = GetReserved() + GetLength();
|
||||
int bufs = 0;
|
||||
|
||||
if (totalLengthRequest > kHeadBufferDataSize)
|
||||
{
|
||||
bufs = (((totalLengthRequest - kHeadBufferDataSize) - 1) / kBufferDataSize) + 1;
|
||||
}
|
||||
|
||||
if (totalLengthCurrent > kHeadBufferDataSize)
|
||||
{
|
||||
bufs -= (((totalLengthCurrent - kHeadBufferDataSize) - 1) / kBufferDataSize) + 1;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = ReclaimBuffers(bufs));
|
||||
|
||||
ResizeMessage(totalLengthRequest);
|
||||
mInfo.mLength = aLength;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint16_t Message::GetOffset(void) const
|
||||
{
|
||||
return mInfo.mOffset;
|
||||
}
|
||||
|
||||
ThreadError Message::MoveOffset(int aDelta)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
assert(GetOffset() + aDelta <= GetLength());
|
||||
VerifyOrExit(GetOffset() + aDelta <= GetLength(), error = kThreadError_InvalidArgs);
|
||||
|
||||
mInfo.mOffset += aDelta;
|
||||
assert(mInfo.mOffset <= GetLength());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Message::SetOffset(uint16_t aOffset)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
assert(aOffset <= GetLength());
|
||||
VerifyOrExit(aOffset <= GetLength(), error = kThreadError_InvalidArgs);
|
||||
|
||||
mInfo.mOffset = aOffset;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t Message::GetType(void) const
|
||||
{
|
||||
return mInfo.mType;
|
||||
}
|
||||
|
||||
void Message::SetType(uint8_t aType)
|
||||
{
|
||||
mInfo.mType = aType;
|
||||
}
|
||||
|
||||
ThreadError Message::Append(const void *aBuf, uint16_t aLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint16_t oldLength = GetLength();
|
||||
|
||||
SuccessOrExit(error = SetLength(GetLength() + aLength));
|
||||
Write(oldLength, aLength, aBuf);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Message::Prepend(const void *aBuf, uint16_t aLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(aLength <= GetReserved(), error = kThreadError_NoBufs);
|
||||
|
||||
SetReserved(GetReserved() - aLength);
|
||||
mInfo.mLength += aLength;
|
||||
SetOffset(GetOffset() + aLength);
|
||||
|
||||
Write(0, aLength, aBuf);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int Message::Read(uint16_t aOffset, uint16_t aLength, void *aBuf) const
|
||||
{
|
||||
Buffer *curBuffer;
|
||||
uint16_t bytesCopied = 0;
|
||||
uint16_t bytesToCopy;
|
||||
|
||||
if (aOffset >= GetLength())
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (aOffset + aLength >= GetLength())
|
||||
{
|
||||
aLength = GetLength() - aOffset;
|
||||
}
|
||||
|
||||
aOffset += GetReserved();
|
||||
|
||||
// special case first buffer
|
||||
if (aOffset < kHeadBufferDataSize)
|
||||
{
|
||||
bytesToCopy = kHeadBufferDataSize - aOffset;
|
||||
|
||||
if (bytesToCopy > aLength)
|
||||
{
|
||||
bytesToCopy = aLength;
|
||||
}
|
||||
|
||||
memcpy(aBuf, GetFirstData() + aOffset, bytesToCopy);
|
||||
|
||||
aLength -= bytesToCopy;
|
||||
bytesCopied += bytesToCopy;
|
||||
aBuf = reinterpret_cast<uint8_t *>(aBuf) + bytesToCopy;
|
||||
|
||||
aOffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
aOffset -= kHeadBufferDataSize;
|
||||
}
|
||||
|
||||
// advance to offset
|
||||
curBuffer = GetNextBuffer();
|
||||
|
||||
while (aOffset >= kBufferDataSize)
|
||||
{
|
||||
assert(curBuffer != NULL);
|
||||
|
||||
curBuffer = curBuffer->GetNextBuffer();
|
||||
aOffset -= kBufferDataSize;
|
||||
}
|
||||
|
||||
// begin copy
|
||||
while (aLength > 0)
|
||||
{
|
||||
assert(curBuffer != NULL);
|
||||
|
||||
bytesToCopy = kBufferDataSize - aOffset;
|
||||
|
||||
if (bytesToCopy > aLength)
|
||||
{
|
||||
bytesToCopy = aLength;
|
||||
}
|
||||
|
||||
memcpy(aBuf, curBuffer->GetData() + aOffset, bytesToCopy);
|
||||
|
||||
aLength -= bytesToCopy;
|
||||
bytesCopied += bytesToCopy;
|
||||
aBuf = reinterpret_cast<uint8_t *>(aBuf) + bytesToCopy;
|
||||
|
||||
curBuffer = curBuffer->GetNextBuffer();
|
||||
aOffset = 0;
|
||||
}
|
||||
|
||||
exit:
|
||||
return bytesCopied;
|
||||
}
|
||||
|
||||
int Message::Write(uint16_t aOffset, uint16_t aLength, const void *aBuf)
|
||||
{
|
||||
Buffer *curBuffer;
|
||||
uint16_t bytesCopied = 0;
|
||||
uint16_t bytesToCopy;
|
||||
|
||||
assert(aOffset + aLength <= GetLength());
|
||||
|
||||
if (aOffset + aLength >= GetLength())
|
||||
{
|
||||
aLength = GetLength() - aOffset;
|
||||
}
|
||||
|
||||
aOffset += GetReserved();
|
||||
|
||||
// special case first buffer
|
||||
if (aOffset < kHeadBufferDataSize)
|
||||
{
|
||||
bytesToCopy = kHeadBufferDataSize - aOffset;
|
||||
|
||||
if (bytesToCopy > aLength)
|
||||
{
|
||||
bytesToCopy = aLength;
|
||||
}
|
||||
|
||||
memcpy(GetFirstData() + aOffset, aBuf, bytesToCopy);
|
||||
|
||||
aLength -= bytesToCopy;
|
||||
bytesCopied += bytesToCopy;
|
||||
aBuf = reinterpret_cast<const uint8_t *>(aBuf) + bytesToCopy;
|
||||
|
||||
aOffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
aOffset -= kHeadBufferDataSize;
|
||||
}
|
||||
|
||||
// advance to offset
|
||||
curBuffer = GetNextBuffer();
|
||||
|
||||
while (aOffset >= kBufferDataSize)
|
||||
{
|
||||
assert(curBuffer != NULL);
|
||||
|
||||
curBuffer = curBuffer->GetNextBuffer();
|
||||
aOffset -= kBufferDataSize;
|
||||
}
|
||||
|
||||
// begin copy
|
||||
while (aLength > 0)
|
||||
{
|
||||
assert(curBuffer != NULL);
|
||||
|
||||
bytesToCopy = kBufferDataSize - aOffset;
|
||||
|
||||
if (bytesToCopy > aLength)
|
||||
{
|
||||
bytesToCopy = aLength;
|
||||
}
|
||||
|
||||
memcpy(curBuffer->GetData() + aOffset, aBuf, bytesToCopy);
|
||||
|
||||
aLength -= bytesToCopy;
|
||||
bytesCopied += bytesToCopy;
|
||||
aBuf = reinterpret_cast<const uint8_t *>(aBuf) + bytesToCopy;
|
||||
|
||||
curBuffer = curBuffer->GetNextBuffer();
|
||||
aOffset = 0;
|
||||
}
|
||||
|
||||
return bytesCopied;
|
||||
}
|
||||
|
||||
int Message::CopyTo(uint16_t aSourceOffset, uint16_t aDestinationOffset, uint16_t aLength, Message &aMessage)
|
||||
{
|
||||
uint16_t bytesCopied = 0;
|
||||
uint16_t bytesToCopy;
|
||||
uint8_t buf[16];
|
||||
|
||||
while (aLength > 0)
|
||||
{
|
||||
bytesToCopy = (aLength < sizeof(buf)) ? aLength : sizeof(buf);
|
||||
|
||||
Read(aSourceOffset, bytesToCopy, buf);
|
||||
aMessage.Write(aDestinationOffset, bytesToCopy, buf);
|
||||
|
||||
aSourceOffset += bytesToCopy;
|
||||
aDestinationOffset += bytesToCopy;
|
||||
aLength -= bytesToCopy;
|
||||
bytesCopied += bytesToCopy;
|
||||
}
|
||||
|
||||
return bytesCopied;
|
||||
}
|
||||
|
||||
uint16_t Message::GetDatagramTag(void) const
|
||||
{
|
||||
return mInfo.mDatagramTag;
|
||||
}
|
||||
|
||||
void Message::SetDatagramTag(uint16_t aTag)
|
||||
{
|
||||
mInfo.mDatagramTag = aTag;
|
||||
}
|
||||
|
||||
uint8_t Message::GetTimeout(void) const
|
||||
{
|
||||
return mInfo.mTimeout;
|
||||
}
|
||||
|
||||
void Message::SetTimeout(uint8_t aTimeout)
|
||||
{
|
||||
mInfo.mTimeout = aTimeout;
|
||||
}
|
||||
|
||||
bool Message::GetChildMask(uint8_t aChildIndex) const
|
||||
{
|
||||
assert(aChildIndex < sizeof(mInfo.mChildMask) * 8);
|
||||
return (mInfo.mChildMask[aChildIndex / 8] & (0x80 >> (aChildIndex % 8))) != 0;
|
||||
}
|
||||
|
||||
void Message::ClearChildMask(uint8_t aChildIndex)
|
||||
{
|
||||
assert(aChildIndex < sizeof(mInfo.mChildMask) * 8);
|
||||
mInfo.mChildMask[aChildIndex / 8] &= ~(0x80 >> (aChildIndex % 8));
|
||||
}
|
||||
|
||||
void Message::SetChildMask(uint8_t aChildIndex)
|
||||
{
|
||||
assert(aChildIndex < sizeof(mInfo.mChildMask) * 8);
|
||||
mInfo.mChildMask[aChildIndex / 8] |= 0x80 >> (aChildIndex % 8);
|
||||
}
|
||||
|
||||
bool Message::IsChildPending(void) const
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
for (size_t i = 0; i < sizeof(mInfo.mChildMask); i++)
|
||||
{
|
||||
if (mInfo.mChildMask[i] != 0)
|
||||
{
|
||||
ExitNow(rval = true);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool Message::GetDirectTransmission(void) const
|
||||
{
|
||||
return mInfo.mDirectTx;
|
||||
}
|
||||
|
||||
void Message::ClearDirectTransmission(void)
|
||||
{
|
||||
mInfo.mDirectTx = false;
|
||||
}
|
||||
|
||||
void Message::SetDirectTransmission(void)
|
||||
{
|
||||
mInfo.mDirectTx = true;
|
||||
}
|
||||
|
||||
uint16_t Message::UpdateChecksum(uint16_t aChecksum, uint16_t aOffset, uint16_t aLength) const
|
||||
{
|
||||
Buffer *curBuffer;
|
||||
uint16_t bytesCovered = 0;
|
||||
uint16_t bytesToCover;
|
||||
|
||||
assert(aOffset + aLength <= GetLength());
|
||||
|
||||
aOffset += GetReserved();
|
||||
|
||||
// special case first buffer
|
||||
if (aOffset < kHeadBufferDataSize)
|
||||
{
|
||||
bytesToCover = kHeadBufferDataSize - aOffset;
|
||||
|
||||
if (bytesToCover > aLength)
|
||||
{
|
||||
bytesToCover = aLength;
|
||||
}
|
||||
|
||||
aChecksum = Ip6::Ip6::UpdateChecksum(aChecksum, GetFirstData() + aOffset, bytesToCover);
|
||||
|
||||
aLength -= bytesToCover;
|
||||
bytesCovered += bytesToCover;
|
||||
|
||||
aOffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
aOffset -= kHeadBufferDataSize;
|
||||
}
|
||||
|
||||
// advance to offset
|
||||
curBuffer = GetNextBuffer();
|
||||
|
||||
while (aOffset >= kBufferDataSize)
|
||||
{
|
||||
assert(curBuffer != NULL);
|
||||
|
||||
curBuffer = curBuffer->GetNextBuffer();
|
||||
aOffset -= kBufferDataSize;
|
||||
}
|
||||
|
||||
// begin copy
|
||||
while (aLength > 0)
|
||||
{
|
||||
assert(curBuffer != NULL);
|
||||
|
||||
bytesToCover = kBufferDataSize - aOffset;
|
||||
|
||||
if (bytesToCover > aLength)
|
||||
{
|
||||
bytesToCover = aLength;
|
||||
}
|
||||
|
||||
aChecksum = Ip6::Ip6::UpdateChecksum(aChecksum, curBuffer->GetData() + aOffset, bytesToCover);
|
||||
|
||||
aLength -= bytesToCover;
|
||||
bytesCovered += bytesToCover;
|
||||
|
||||
curBuffer = curBuffer->GetNextBuffer();
|
||||
aOffset = 0;
|
||||
}
|
||||
|
||||
return aChecksum;
|
||||
}
|
||||
|
||||
uint16_t Message::GetReserved(void) const
|
||||
{
|
||||
return mInfo.mReserved;
|
||||
}
|
||||
|
||||
void Message::SetReserved(uint16_t aReserved)
|
||||
{
|
||||
mInfo.mReserved = aReserved;
|
||||
}
|
||||
|
||||
MessageQueue::MessageQueue(void)
|
||||
{
|
||||
mInterface.mHead = NULL;
|
||||
mInterface.mTail = NULL;
|
||||
}
|
||||
|
||||
ThreadError MessageQueue::AddToList(int aList, Message &aMessage)
|
||||
{
|
||||
MessageList *list;
|
||||
|
||||
assert(aMessage.GetMessageList(aList).mNext == NULL &&
|
||||
aMessage.GetMessageList(aList).mPrev == NULL &&
|
||||
aMessage.GetMessageList(aList).mList != NULL);
|
||||
|
||||
list = aMessage.GetMessageList(aList).mList;
|
||||
|
||||
if (list->mHead == NULL)
|
||||
{
|
||||
list->mHead = &aMessage;
|
||||
list->mTail = &aMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->mTail->GetMessageList(aList).mNext = &aMessage;
|
||||
aMessage.GetMessageList(aList).mPrev = list->mTail;
|
||||
list->mTail = &aMessage;
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError MessageQueue::RemoveFromList(int aList, Message &aMessage)
|
||||
{
|
||||
MessageList *list;
|
||||
|
||||
assert(aMessage.GetMessageList(aList).mList != NULL);
|
||||
|
||||
list = aMessage.GetMessageList(aList).mList;
|
||||
|
||||
assert(list->mHead == &aMessage ||
|
||||
aMessage.GetMessageList(aList).mNext != NULL ||
|
||||
aMessage.GetMessageList(aList).mPrev != NULL);
|
||||
|
||||
if (aMessage.GetMessageList(aList).mPrev)
|
||||
{
|
||||
aMessage.GetMessageList(aList).mPrev->GetMessageList(aList).mNext = aMessage.GetMessageList(aList).mNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->mHead = aMessage.GetMessageList(aList).mNext;
|
||||
}
|
||||
|
||||
if (aMessage.GetMessageList(aList).mNext)
|
||||
{
|
||||
aMessage.GetMessageList(aList).mNext->GetMessageList(aList).mPrev = aMessage.GetMessageList(aList).mPrev;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->mTail = aMessage.GetMessageList(aList).mPrev;
|
||||
}
|
||||
|
||||
aMessage.GetMessageList(aList).mPrev = NULL;
|
||||
aMessage.GetMessageList(aList).mNext = NULL;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
Message *MessageQueue::GetHead(void) const
|
||||
{
|
||||
return mInterface.mHead;
|
||||
}
|
||||
|
||||
ThreadError MessageQueue::Enqueue(Message &aMessage)
|
||||
{
|
||||
aMessage.GetMessageList(MessageInfo::kListAll).mList = &sAll;
|
||||
aMessage.GetMessageList(MessageInfo::kListInterface).mList = &mInterface;
|
||||
AddToList(MessageInfo::kListAll, aMessage);
|
||||
AddToList(MessageInfo::kListInterface, aMessage);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError MessageQueue::Dequeue(Message &aMessage)
|
||||
{
|
||||
RemoveFromList(MessageInfo::kListAll, aMessage);
|
||||
RemoveFromList(MessageInfo::kListInterface, aMessage);
|
||||
aMessage.GetMessageList(MessageInfo::kListAll).mList = NULL;
|
||||
aMessage.GetMessageList(MessageInfo::kListInterface).mList = NULL;
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,600 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for the message buffer pool and message buffers.
|
||||
*/
|
||||
|
||||
#ifndef MESSAGE_HPP_
|
||||
#define MESSAGE_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <openthread-core-config.h>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
/**
|
||||
* @addtogroup core-message
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for the message buffer pool and message buffers.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
kNumBuffers = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS,
|
||||
kBufferSize = OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE,
|
||||
};
|
||||
|
||||
class Message;
|
||||
|
||||
/**
|
||||
* This structure contains pointers to the head and tail of a Message list.
|
||||
*
|
||||
*/
|
||||
struct MessageList
|
||||
{
|
||||
Message *mHead; ///< A pointer to the first Message in the list.
|
||||
Message *mTail; ///< A pointer to the last Message in the list.
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure contains pointers to the MessageList structure, the next Message, and previous Message.
|
||||
*
|
||||
*/
|
||||
struct MessageListEntry
|
||||
{
|
||||
struct MessageList *mList; ///< A pointer to the MessageList structure for the list.
|
||||
Message *mNext; ///< A pointer to the next Message in the list.
|
||||
Message *mPrev; ///< A pointer to the pprevious Message in the list.
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure contains a pointer to the next Message buffer.
|
||||
*
|
||||
*/
|
||||
struct BufferHeader
|
||||
{
|
||||
class Buffer *mNext; ///< A pointer to the next Message buffer.
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure contains metdata about a Message.
|
||||
*
|
||||
*/
|
||||
struct MessageInfo
|
||||
{
|
||||
enum
|
||||
{
|
||||
kListAll = 0, ///< Identifies the all messages list.
|
||||
kListInterface = 1, ///< Identifies the per-inteface message list.
|
||||
};
|
||||
MessageListEntry mList[2]; ///< Message lists.
|
||||
uint16_t mReserved; ///< Number of header bytes reserved for the message.
|
||||
uint16_t mLength; ///< Number of bytes within the message.
|
||||
uint16_t mOffset; ///< A byte offset within the message.
|
||||
uint16_t mDatagramTag; ///< The datagram tag used for 6LoWPAN fragmentation.
|
||||
uint8_t mTimeout; ///< Seconds remaining before dropping the message.
|
||||
|
||||
uint8_t mChildMask[8]; ///< A bit-vector to indicate which sleepy children need to receive this message.
|
||||
|
||||
uint8_t mType : 2; ///< Identifies the type of message.
|
||||
bool mDirectTx : 1; ///< Used to indicate whether a direct transmission is required.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class represents a Message buffer.
|
||||
*
|
||||
*/
|
||||
class Buffer
|
||||
{
|
||||
friend class Message;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This method returns a pointer to the next message buffer.
|
||||
*
|
||||
* @returns A pointer to the next message buffer.
|
||||
*
|
||||
*/
|
||||
class Buffer *GetNextBuffer(void) const { return mHeader.mNext; }
|
||||
|
||||
/**
|
||||
* This method sets the pointer to the next message buffer.
|
||||
*
|
||||
*/
|
||||
void SetNextBuffer(class Buffer *buf) { mHeader.mNext = buf; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* This method returns a pointer to the first byte of data in the first message buffer.
|
||||
*
|
||||
* @returns A pointer to the first data byte.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetFirstData(void) { return mHeadData; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the first byte of data in the first message buffer.
|
||||
*
|
||||
* @returns A pointer to the first data byte.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetFirstData(void) const { return mHeadData; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the first data byte of a subsequent message buffer.
|
||||
*
|
||||
* @returns A pointer to the first data byte.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetData(void) { return mData; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the first data byte of a subsequent message buffer.
|
||||
*
|
||||
* @returns A pointer to the first data byte.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetData(void) const { return mData; }
|
||||
|
||||
enum
|
||||
{
|
||||
kBufferDataSize = kBufferSize - sizeof(struct BufferHeader),
|
||||
kHeadBufferDataSize = kBufferDataSize - sizeof(struct MessageInfo),
|
||||
};
|
||||
|
||||
struct BufferHeader mHeader;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
MessageInfo mInfo;
|
||||
uint8_t mHeadData[kHeadBufferDataSize];
|
||||
};
|
||||
uint8_t mData[kBufferDataSize];
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This class represents a message.
|
||||
*
|
||||
*/
|
||||
class Message: private Buffer
|
||||
{
|
||||
friend class MessageQueue;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kTypeIp6 = 0, ///< A full uncompress IPv6 packet
|
||||
kType6lowpan = 1, ///< A 6lowpan frame
|
||||
kTypeMacDataPoll = 2, ///< A MAC data poll message
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the next message in the same interface list.
|
||||
*
|
||||
* @returns A pointer to the next message in the same interface list.
|
||||
*
|
||||
*/
|
||||
Message *GetNext(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the number of bytes in the message.
|
||||
*
|
||||
* @returns The number of bytes in the message.
|
||||
*/
|
||||
uint16_t GetLength(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the number of bytes in the message.
|
||||
*
|
||||
* @param[in] aLength Requested number of bytes in the message.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the length of the message.
|
||||
* @retval kThreadError_NoBufs Failed to grow the size of the message because insufficient buffers were
|
||||
* available.
|
||||
*
|
||||
*/
|
||||
ThreadError SetLength(uint16_t aLength);
|
||||
|
||||
/**
|
||||
* This method returns the byte offset within the message.
|
||||
*
|
||||
* @returns A byte offset within the message.
|
||||
*
|
||||
*/
|
||||
uint16_t GetOffset(void) const;
|
||||
|
||||
/**
|
||||
* This method moves the byte offset within the message.
|
||||
*
|
||||
* @param[in] aDelta The number of bytes to move the current offset, which may be positive or negative.
|
||||
*
|
||||
* @retval kThreadError_None Successfully moved the byte offset.
|
||||
* @retval kThreadError_InvalidArgs The resulting byte offset is not within the existing message.
|
||||
*
|
||||
*/
|
||||
ThreadError MoveOffset(int aDelta);
|
||||
|
||||
/**
|
||||
* This method sets the byte offset within the message.
|
||||
*
|
||||
* @param[in] aOffset The number of bytes to move the current offset, which may be positive or negative.
|
||||
*
|
||||
* @retval kThreadError_None Successfully moved the byte offset.
|
||||
* @retval kThreadError_InvalidArgs The requestd byte offset is not within the existing message.
|
||||
*
|
||||
*/
|
||||
ThreadError SetOffset(uint16_t aOffset);
|
||||
|
||||
/**
|
||||
* This method returns the type of the message.
|
||||
*
|
||||
* @returns The type of the message.
|
||||
*
|
||||
*/
|
||||
uint8_t GetType(void) const;
|
||||
|
||||
/**
|
||||
* This method prepends bytes to the front of the message.
|
||||
*
|
||||
* On success, this method grows the message by @p aLength bytes.
|
||||
*
|
||||
* @param[in] aBuf A pointer to a data buffer.
|
||||
* @param[in] aLength The number of bytes to prepend.
|
||||
*
|
||||
* @retval kThreadError_None Successfully prepended the bytes.
|
||||
* @retval kThreadError_NoBufs Not enough reserved bytes in the message.
|
||||
*
|
||||
*/
|
||||
ThreadError Prepend(const void *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* This method appends bytes to the end of the message.
|
||||
*
|
||||
* On success, this method grows the message by @p aLength bytes.
|
||||
*
|
||||
* @param[in] aBuf A pointer to a data buffer.
|
||||
* @param[in] aLength The number of bytes to append.
|
||||
*
|
||||
* @retval kThreadError_None Successfully appended the bytes.
|
||||
* @retval kThreadError_NoBufs Insufficient available buffers to grow the message.
|
||||
*
|
||||
*/
|
||||
ThreadError Append(const void *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* This method reads bytes from the message.
|
||||
*
|
||||
* @param[in] aOffset Byte offset within the message to begin reading.
|
||||
* @param[in] aLength Number of bytes to read.
|
||||
* @param[in] aBuf A pointer to a data buffer.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
*/
|
||||
int Read(uint16_t aOffset, uint16_t aLength, void *aBuf) const;
|
||||
|
||||
/**
|
||||
* This method writes bytes to the message.
|
||||
*
|
||||
* @param[in] aOffset Byte offset within the message to begin writing.
|
||||
* @param[in] aLength Number of bytes to write.
|
||||
* @param[in] aBuf A pointer to a data buffer.
|
||||
*
|
||||
* @returns The number of bytes written.
|
||||
*
|
||||
*/
|
||||
int Write(uint16_t aOffset, uint16_t aLength, const void *aBuf);
|
||||
|
||||
/**
|
||||
* This method copies bytes from one message to another.
|
||||
*
|
||||
* @param[in] aSourceOffset Byte offset within the source message to begin reading.
|
||||
* @param[in] aDestinationOffset Byte offset within the destination message to begin writing.
|
||||
* @param[in] aLength Number of bytes to copy.
|
||||
* @param[in] aMessage Message to copy to.
|
||||
*
|
||||
* @returns The number of bytes copied.
|
||||
*
|
||||
*/
|
||||
int CopyTo(uint16_t aSourceOffset, uint16_t aDestinationOffset, uint16_t aLength, Message &aMessage);
|
||||
|
||||
/**
|
||||
* This method returns the datagram tag used for 6LoWPAN fragmentation.
|
||||
*
|
||||
* @returns The 6LoWPAN datagram tag.
|
||||
*
|
||||
*/
|
||||
uint16_t GetDatagramTag(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the datagram tag used for 6LoWPAN fragmentation.
|
||||
*
|
||||
* @param[in] aTag The 6LoWPAN datagram tag.
|
||||
*
|
||||
*/
|
||||
void SetDatagramTag(uint16_t aTag);
|
||||
|
||||
/**
|
||||
* This method returns the timeout used for 6LoWPAN reassembly.
|
||||
*
|
||||
* @returns The time remaining in seconds.
|
||||
*
|
||||
*/
|
||||
uint8_t GetTimeout(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the timeout used for 6LoWPAN reassembly.
|
||||
*
|
||||
*/
|
||||
void SetTimeout(uint8_t aTimeout);
|
||||
|
||||
/**
|
||||
* This method returns whether or not the message forwarding is scheduled for the child.
|
||||
*
|
||||
* @param[in] aChildIndex The index into the child table.
|
||||
*
|
||||
* @retval TRUE If the message is scheduled to be forwarded to the child.
|
||||
* @retval FALSE If the message is not scheduled to be forwarded to the child.
|
||||
*
|
||||
*/
|
||||
bool GetChildMask(uint8_t aChildIndex) const;
|
||||
|
||||
/**
|
||||
* This method unschedules forwarding of the message to the child.
|
||||
*
|
||||
* @param[in] aChildIndex The index into the child table.
|
||||
*
|
||||
*/
|
||||
void ClearChildMask(uint8_t aChildIndex);
|
||||
|
||||
/**
|
||||
* This method schedules forwarding of the message to the child.
|
||||
*
|
||||
* @param[in] aChildIndex The index into the child table.
|
||||
*
|
||||
*/
|
||||
void SetChildMask(uint8_t aChildIndex);
|
||||
|
||||
/**
|
||||
* This method returns whether or not the message forwarding is scheduled for at least one child.
|
||||
*
|
||||
* @retval TRUE If message forwarding is scheduled for at least one child.
|
||||
* @retval FALSE If message forwarding is not scheduled for any child.
|
||||
*
|
||||
*/
|
||||
bool IsChildPending(void) const;
|
||||
|
||||
/**
|
||||
* This method returns whether or not message forwarding is scheduled for direct transmission.
|
||||
*
|
||||
* @retval TRUE If message forwarding is scheduled for direct transmission.
|
||||
* @retval FALSE If message forwarding is not scheduled for direct transmission.
|
||||
*
|
||||
*/
|
||||
bool GetDirectTransmission(void) const;
|
||||
|
||||
/**
|
||||
* This method unschedules forwarding using direct transmission.
|
||||
*
|
||||
*/
|
||||
void ClearDirectTransmission(void);
|
||||
|
||||
/**
|
||||
* This method schedules forwarding using direct transmission.
|
||||
*
|
||||
*/
|
||||
void SetDirectTransmission(void);
|
||||
|
||||
/**
|
||||
* This method is used to update a checksum value.
|
||||
*
|
||||
* @param[in] aChecksum Initial checksum value.
|
||||
* @param[in] aOffset Byte offset within the message to begin checksum computation.
|
||||
* @param[in] aLength Number of bytes to compute the checksum over.
|
||||
*
|
||||
* @retval The updated checksum value.
|
||||
*
|
||||
*/
|
||||
uint16_t UpdateChecksum(uint16_t aChecksum, uint16_t aOffset, uint16_t aLength) const;
|
||||
|
||||
/**
|
||||
* This static method is used to initialize the message buffer pool.
|
||||
*
|
||||
*/
|
||||
static ThreadError Init(void);
|
||||
|
||||
/**
|
||||
* This static method is used to obtain a new message.
|
||||
*
|
||||
* @param[in] aType The message type.
|
||||
* @param[in] aReserveHeader The number of header bytes to reserve.
|
||||
*
|
||||
* @returns A pointer to the message or NULL if no message buffers are available.
|
||||
*
|
||||
*/
|
||||
static Message *New(uint8_t aType, uint16_t aReserveHeader);
|
||||
|
||||
/**
|
||||
* This static method is used to free a message and return all message buffers to the buffer pool.
|
||||
*
|
||||
* @param[in] aMessage The message to free.
|
||||
*
|
||||
* @retval kThreadError_None Successfully freed the message.
|
||||
* @retval kThreadError_InvalidArgs The message is already freed.
|
||||
*
|
||||
*/
|
||||
static ThreadError Free(Message &aMessage);
|
||||
|
||||
private:
|
||||
/**
|
||||
* This method returns a reference to a message list.
|
||||
*
|
||||
* @param[in] aList The message list.
|
||||
*
|
||||
* @returns A reference to a message lis.
|
||||
*
|
||||
*/
|
||||
MessageListEntry &GetMessageList(uint8_t aList) { return mInfo.mList[aList]; }
|
||||
|
||||
/**
|
||||
* This method returns a reference to a message list.
|
||||
*
|
||||
* @param[in] aList The message list.
|
||||
*
|
||||
* @returns A reference to a message lis.
|
||||
*
|
||||
*/
|
||||
const MessageListEntry &GetMessageList(uint8_t aList) const { return mInfo.mList[aList]; }
|
||||
|
||||
/**
|
||||
* This method returns the number of reserved header bytes.
|
||||
*
|
||||
* @returns The number of reserved header bytes.
|
||||
*
|
||||
*/
|
||||
uint16_t GetReserved(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the number of reserved header bytes.
|
||||
*
|
||||
* @pram[in] aReservedHeader The number of header bytes to reserve.
|
||||
*
|
||||
*/
|
||||
void SetReserved(uint16_t aReservedHeader);
|
||||
|
||||
/**
|
||||
* This method sets the message type.
|
||||
*
|
||||
* @param[in] aType The message type.
|
||||
*
|
||||
*/
|
||||
void SetType(uint8_t aType);
|
||||
|
||||
/**
|
||||
* This method adds or frees message buffers to meet the requested length.
|
||||
*
|
||||
* @param[in] aLength The number of bytes that the message buffer needs to handle.
|
||||
*
|
||||
* @retval kThreadError_None Successfully resized the message.
|
||||
* @retval kThreadError_InvalidArags Could not grow the message due to insufficient available message buffers.
|
||||
*
|
||||
*/
|
||||
ThreadError ResizeMessage(uint16_t aLength);
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements a message queue.
|
||||
*
|
||||
*/
|
||||
class MessageQueue
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the message queue.
|
||||
*
|
||||
*/
|
||||
MessageQueue(void);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the first message.
|
||||
*
|
||||
* @returns A pointer to the first message.
|
||||
*
|
||||
*/
|
||||
Message *GetHead(void) const;
|
||||
|
||||
/**
|
||||
* This method adds a message to the end of the list.
|
||||
*
|
||||
* @param[in] aMessage The message to add.
|
||||
*
|
||||
* @retval kThreadError_None Successfully added the message to the list.
|
||||
* @retval kThreadError_Busy The message is already enqueued in a list.
|
||||
*
|
||||
*/
|
||||
ThreadError Enqueue(Message &aMessage);
|
||||
|
||||
/**
|
||||
* This method removes a message from the list.
|
||||
*
|
||||
* @param[in] aMessage The message to remove.
|
||||
*
|
||||
* @retval kThreadError_None Successfully removed the message from the list.
|
||||
* @retval kThreadError_Busy The message is not enqueued in a list.
|
||||
*
|
||||
*/
|
||||
ThreadError Dequeue(Message &aMessage);
|
||||
|
||||
private:
|
||||
/**
|
||||
* This static method adds a message to a list.
|
||||
*
|
||||
* @param[in] aListId The list to add @p aMessage to.
|
||||
* @param[in] aMessage The message to add to @p aListId.
|
||||
*
|
||||
* @retval kThreadError_None Successfully added the message to the list.
|
||||
* @retval kThreadError_Busy The message is already enqueued in a list.
|
||||
*
|
||||
*/
|
||||
static ThreadError AddToList(int aListId, Message &aMessage);
|
||||
|
||||
/**
|
||||
* This static method removes a message from a list.
|
||||
*
|
||||
* @param[in] aListId The list to add @p aMessage to.
|
||||
* @param[in] aMessage The message to add to @p aListId.
|
||||
*
|
||||
* @retval kThreadError_None Successfully added the message to the list.
|
||||
* @retval kThreadError_Busy The message is not enqueued in the list.
|
||||
*
|
||||
*/
|
||||
static ThreadError RemoveFromList(int aListId, Message &aMessage);
|
||||
|
||||
MessageList mInterface; ///< The instance-specific message list.
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // MESSAGE_HPP_
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the tasklet scheduler.
|
||||
*/
|
||||
|
||||
#include <openthread.h>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/tasklet.hpp>
|
||||
#include <platform/atomic.h>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
Tasklet *TaskletScheduler::sHead = NULL;
|
||||
Tasklet *TaskletScheduler::sTail = NULL;
|
||||
|
||||
Tasklet::Tasklet(Handler aHandler, void *aContext)
|
||||
{
|
||||
mHandler = aHandler;
|
||||
mContext = aContext;
|
||||
mNext = NULL;
|
||||
}
|
||||
|
||||
ThreadError Tasklet::Post(void)
|
||||
{
|
||||
return TaskletScheduler::Post(*this);
|
||||
}
|
||||
|
||||
ThreadError TaskletScheduler::Post(Tasklet &aTasklet)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint32_t state = otPlatAtomicBegin();
|
||||
|
||||
VerifyOrExit(sTail != &aTasklet && aTasklet.mNext == NULL, error = kThreadError_Busy);
|
||||
|
||||
if (sTail == NULL)
|
||||
{
|
||||
sHead = &aTasklet;
|
||||
sTail = &aTasklet;
|
||||
otSignalTaskletPending();
|
||||
}
|
||||
else
|
||||
{
|
||||
sTail->mNext = &aTasklet;
|
||||
sTail = &aTasklet;
|
||||
}
|
||||
|
||||
exit:
|
||||
otPlatAtomicEnd(state);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Tasklet *TaskletScheduler::PopTasklet(void)
|
||||
{
|
||||
Tasklet *task = sHead;
|
||||
|
||||
if (task != NULL)
|
||||
{
|
||||
sHead = sHead->mNext;
|
||||
|
||||
if (sHead == NULL)
|
||||
{
|
||||
sTail = NULL;
|
||||
}
|
||||
|
||||
task->mNext = NULL;
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
bool TaskletScheduler::AreTaskletsPending(void)
|
||||
{
|
||||
return sHead != NULL;
|
||||
}
|
||||
|
||||
void TaskletScheduler::RunNextTasklet(void)
|
||||
{
|
||||
uint32_t state;
|
||||
Tasklet *task;
|
||||
|
||||
state = otPlatAtomicBegin();
|
||||
task = PopTasklet();
|
||||
otPlatAtomicEnd(state);
|
||||
|
||||
if (task != NULL)
|
||||
{
|
||||
task->RunTask();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for tasklets and the tasklet scheduler.
|
||||
*/
|
||||
|
||||
#ifndef TASKLET_HPP_
|
||||
#define TASKLET_HPP_
|
||||
|
||||
#include <openthread-types.h>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
/**
|
||||
* @addtogroup core-tasklet
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for tasklets and the tasklet scheduler.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class is used to represent a tasklet.
|
||||
*
|
||||
*/
|
||||
class Tasklet
|
||||
{
|
||||
friend class TaskletScheduler;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when the tasklet is run.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
typedef void (*Handler)(void *aContext);
|
||||
|
||||
/**
|
||||
* This constructor creates a tasklet instance.
|
||||
*
|
||||
* @param[in] aHandler A pointer to a function that is called when the tasklet is run.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
Tasklet(Handler aHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* This method puts the tasklet on the run queue.
|
||||
*
|
||||
*/
|
||||
ThreadError Post(void);
|
||||
|
||||
private:
|
||||
/**
|
||||
* This method is called when the tasklet is run.
|
||||
*
|
||||
*/
|
||||
void RunTask(void) { mHandler(mContext); }
|
||||
|
||||
Handler mHandler; ///< A pointer to a function that is called when the tasklet is run.
|
||||
void *mContext; ///< A pointer to arbitrary context information.
|
||||
Tasklet *mNext; ///< A pointer to the next tasklet in the run queue.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements the tasklet scheduler.
|
||||
*
|
||||
*/
|
||||
class TaskletScheduler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This static method enqueues a tasklet into the run queue.
|
||||
*
|
||||
* @param[in] aTasklet A reference to the tasklet to enqueue.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the tasklet.
|
||||
* @retval kThreadError_Busy The tasklet was already enqueued.
|
||||
*/
|
||||
static ThreadError Post(Tasklet &aTasklet);
|
||||
|
||||
/**
|
||||
* This static method indicates whether or not there are tasklets pending.
|
||||
*
|
||||
* @retval TRUE If there are tasklets pending.
|
||||
* @retval FALSE If there are no tasklets pending.
|
||||
*
|
||||
*/
|
||||
static bool AreTaskletsPending(void);
|
||||
|
||||
/**
|
||||
* This static method runs the next tasklet.
|
||||
*
|
||||
*/
|
||||
static void RunNextTasklet(void);
|
||||
|
||||
private:
|
||||
static Tasklet *PopTasklet(void);
|
||||
static Tasklet *sHead;
|
||||
static Tasklet *sTail;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // TASKLET_HPP_
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements a multiplexed timer service on top of the alarm abstraction.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/timer.hpp>
|
||||
#include <platform/alarm.h>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
static Tasklet sTask(&TimerScheduler::FireTimers, NULL);
|
||||
static Timer *sHead = NULL;
|
||||
static Timer *sTail = NULL;
|
||||
|
||||
void TimerScheduler::Add(Timer &aTimer)
|
||||
{
|
||||
VerifyOrExit(aTimer.mNext == NULL && sTail != &aTimer, ;);
|
||||
|
||||
if (sTail == NULL)
|
||||
{
|
||||
sHead = &aTimer;
|
||||
}
|
||||
else
|
||||
{
|
||||
sTail->mNext = &aTimer;
|
||||
}
|
||||
|
||||
aTimer.mNext = NULL;
|
||||
sTail = &aTimer;
|
||||
|
||||
exit:
|
||||
SetAlarm();
|
||||
}
|
||||
|
||||
void TimerScheduler::Remove(Timer &aTimer)
|
||||
{
|
||||
VerifyOrExit(aTimer.mNext != NULL || sTail == &aTimer, ;);
|
||||
|
||||
if (sHead == &aTimer)
|
||||
{
|
||||
sHead = aTimer.mNext;
|
||||
|
||||
if (sTail == &aTimer)
|
||||
{
|
||||
sTail = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Timer *cur = sHead; cur; cur = cur->mNext)
|
||||
{
|
||||
if (cur->mNext == &aTimer)
|
||||
{
|
||||
cur->mNext = aTimer.mNext;
|
||||
|
||||
if (sTail == &aTimer)
|
||||
{
|
||||
sTail = cur;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aTimer.mNext = NULL;
|
||||
SetAlarm();
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
bool TimerScheduler::IsAdded(const Timer &aTimer)
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
if (sHead == &aTimer)
|
||||
{
|
||||
ExitNow(rval = true);
|
||||
}
|
||||
|
||||
for (Timer *cur = sHead; cur; cur = cur->mNext)
|
||||
{
|
||||
if (cur == &aTimer)
|
||||
{
|
||||
ExitNow(rval = true);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
void TimerScheduler::SetAlarm(void)
|
||||
{
|
||||
uint32_t now = otPlatAlarmGetNow();
|
||||
int32_t minRemaining = (1UL << 31) - 1;
|
||||
uint32_t elapsed;
|
||||
int32_t remaining;
|
||||
|
||||
if (sHead == NULL)
|
||||
{
|
||||
otPlatAlarmStop();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
for (Timer *timer = sHead; timer; timer = timer->mNext)
|
||||
{
|
||||
elapsed = now - timer->mT0;
|
||||
remaining = timer->mDt - elapsed;
|
||||
|
||||
if (remaining < minRemaining)
|
||||
{
|
||||
minRemaining = remaining;
|
||||
}
|
||||
}
|
||||
|
||||
if (minRemaining <= 0)
|
||||
{
|
||||
sTask.Post();
|
||||
}
|
||||
else
|
||||
{
|
||||
otPlatAlarmStartAt(now, minRemaining);
|
||||
}
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
extern "C" void otPlatAlarmSignalFired(void)
|
||||
{
|
||||
Thread::sTask.Post();
|
||||
}
|
||||
|
||||
void TimerScheduler::FireTimers(void *aContext)
|
||||
{
|
||||
uint32_t now = otPlatAlarmGetNow();
|
||||
uint32_t elapsed;
|
||||
|
||||
for (Timer *cur = sHead; cur; cur = cur->mNext)
|
||||
{
|
||||
elapsed = now - cur->mT0;
|
||||
|
||||
if (elapsed >= cur->mDt)
|
||||
{
|
||||
Remove(*cur);
|
||||
cur->Fired();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SetAlarm();
|
||||
}
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for the multiplexed timer service.
|
||||
*/
|
||||
|
||||
#ifndef TIMER_HPP_
|
||||
#define TIMER_HPP_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <common/tasklet.hpp>
|
||||
#include <platform/alarm.h>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
class Timer;
|
||||
|
||||
/**
|
||||
* @addtogroup core-timer
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for the multiplexed timer service.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements the timer scheduler.
|
||||
*
|
||||
*/
|
||||
class TimerScheduler
|
||||
{
|
||||
friend class Timer;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This static method adds a timer instance to the timer scheduler.
|
||||
*
|
||||
* @param[in] aTimer A reference to the timer instance.
|
||||
*
|
||||
*/
|
||||
static void Add(Timer &aTimer);
|
||||
|
||||
/**
|
||||
* This static method removes a timer instance to the timer scheduler.
|
||||
*
|
||||
* @param[in] aTimer A reference to the timer instance.
|
||||
*
|
||||
*/
|
||||
static void Remove(Timer &aTimer);
|
||||
|
||||
/**
|
||||
* This static method returns whether or not the timer instance is already added.
|
||||
*
|
||||
* @retval TRUE If the timer instance is already added.
|
||||
* @retval FALSE If the timer instance is not added.
|
||||
*
|
||||
*/
|
||||
static bool IsAdded(const Timer &aTimer);
|
||||
|
||||
/**
|
||||
* This static method processes all running timers.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
static void FireTimers(void *aContext);
|
||||
|
||||
private:
|
||||
static void SetAlarm(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements a timer.
|
||||
*
|
||||
*/
|
||||
class Timer
|
||||
{
|
||||
friend class TimerScheduler;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when the timer expires.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*/
|
||||
typedef void (*Handler)(void *aContext);
|
||||
|
||||
/**
|
||||
* This constructor creates a timer instance.
|
||||
*
|
||||
* @param[in] aHandler A pointer to a function that is called when the timer expires.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
Timer(Handler aHandler, void *aContext) { mNext = NULL; mHandler = aHandler; mContext = aContext; }
|
||||
|
||||
/**
|
||||
* This method returns the start time in milliseconds for the timer.
|
||||
*
|
||||
* @returns The start time in milliseconds.
|
||||
*
|
||||
*/
|
||||
uint32_t Gett0(void) const { return mT0; }
|
||||
|
||||
/**
|
||||
* This method returns the delta time in milliseconds for the timer.
|
||||
*
|
||||
* @returns The delta time.
|
||||
*
|
||||
*/
|
||||
uint32_t Getdt(void) const { return mDt; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the timer instance is running.
|
||||
*
|
||||
* @retval TRUE If the timer is running.
|
||||
* @retval FALSE If the timer is not running.
|
||||
*/
|
||||
bool IsRunning(void) const { return TimerScheduler::IsAdded(*this); }
|
||||
|
||||
/**
|
||||
* This method schedules the timer to fire a @p dt milliseconds from now.
|
||||
*
|
||||
* @param[in] aDt The expire time in milliseconds from now.
|
||||
*/
|
||||
void Start(uint32_t aDt) { StartAt(GetNow(), aDt); }
|
||||
|
||||
/**
|
||||
* This method schedules the timer to fire at @p dt milliseconds from @p t0.
|
||||
*
|
||||
* @param[in] aT0 The start time in milliseconds.
|
||||
* @param[in] aDt The expire time in milliseconds from @p t0.
|
||||
*/
|
||||
void StartAt(uint32_t aT0, uint32_t aDt) { mT0 = aT0; mDt = aDt; TimerScheduler::Add(*this); }
|
||||
|
||||
/**
|
||||
* This method stops the timer.
|
||||
*
|
||||
*/
|
||||
void Stop(void) { TimerScheduler::Remove(*this); }
|
||||
|
||||
/**
|
||||
* This static method returns the current time in milliseconds.
|
||||
*
|
||||
* @returns The current time in milliseconds.
|
||||
*
|
||||
*/
|
||||
static uint32_t GetNow(void) { return otPlatAlarmGetNow(); }
|
||||
|
||||
/**
|
||||
* This static method returns the number of milliseonds given seconds.
|
||||
*
|
||||
* @returns The number of milliseconds.
|
||||
*
|
||||
*/
|
||||
static uint32_t SecToMsec(uint32_t aSeconds) { return aSeconds * 1000u; }
|
||||
|
||||
/**
|
||||
* This static method returns the number of seconds given milliseconds.
|
||||
*
|
||||
* @returns The number of seconds.
|
||||
*
|
||||
*/
|
||||
static uint32_t MsecToSec(uint32_t aMilliseconds) { return aMilliseconds / 1000u; }
|
||||
|
||||
private:
|
||||
void Fired(void) { mHandler(mContext); }
|
||||
|
||||
Handler mHandler; ///< A pointer to the function that is called when the timer expires.
|
||||
void *mContext; ///< A pointer to arbitrary context information.
|
||||
uint32_t mT0; ///< The start time of the timer in milliseconds.
|
||||
uint32_t mDt; ///< The time delay from the start time in milliseconds.
|
||||
Timer *mNext; ///< The next timer in the scheduler list.
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // TIMER_HPP_
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements AES-CCM.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <crypto/aes_ccm.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Crypto {
|
||||
|
||||
ThreadError AesCcm::SetKey(const uint8_t *aKey, uint16_t aKeyLength)
|
||||
{
|
||||
otCryptoAesEcbSetKey(aKey, 8 * aKeyLength);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
void AesCcm::Init(uint32_t aHeaderLength, uint32_t aPlainTextLength, uint8_t aTagLength,
|
||||
const void *aNonce, uint8_t aNonceLength)
|
||||
{
|
||||
const uint8_t *nonceBytes = reinterpret_cast<const uint8_t *>(aNonce);
|
||||
uint8_t blockLength = 0;
|
||||
uint32_t len;
|
||||
uint8_t L;
|
||||
uint8_t i;
|
||||
|
||||
// aTagLength must be even
|
||||
aTagLength &= ~1;
|
||||
|
||||
if (aTagLength > sizeof(mBlock))
|
||||
{
|
||||
aTagLength = sizeof(mBlock);
|
||||
}
|
||||
|
||||
L = 0;
|
||||
|
||||
for (len = aPlainTextLength; len; len >>= 8)
|
||||
{
|
||||
L++;
|
||||
}
|
||||
|
||||
if (L <= 1)
|
||||
{
|
||||
L = 2;
|
||||
}
|
||||
|
||||
if (aNonceLength > 13)
|
||||
{
|
||||
aNonceLength = 13;
|
||||
}
|
||||
|
||||
// increase L to match nonce len
|
||||
if (L < (15 - aNonceLength))
|
||||
{
|
||||
L = 15 - aNonceLength;
|
||||
}
|
||||
|
||||
// decrease nonceLength to match L
|
||||
if (aNonceLength > (15 - L))
|
||||
{
|
||||
aNonceLength = 15 - L;
|
||||
}
|
||||
|
||||
// setup initial block
|
||||
|
||||
// write flags
|
||||
mBlock[0] = (static_cast<uint8_t>((aHeaderLength != 0) << 6) |
|
||||
static_cast<uint8_t>(((aTagLength - 2) >> 1) << 3) |
|
||||
static_cast<uint8_t>(L - 1));
|
||||
|
||||
// write nonce
|
||||
for (i = 0; i < aNonceLength; i++)
|
||||
{
|
||||
mBlock[1 + i] = nonceBytes[i];
|
||||
}
|
||||
|
||||
// write len
|
||||
len = aPlainTextLength;
|
||||
|
||||
for (i = sizeof(mBlock) - 1; i > aNonceLength; i--)
|
||||
{
|
||||
mBlock[i] = len;
|
||||
len >>= 8;
|
||||
}
|
||||
|
||||
// encrypt initial block
|
||||
otCryptoAesEcbEncrypt(mBlock, mBlock);
|
||||
|
||||
// process header
|
||||
if (aHeaderLength > 0)
|
||||
{
|
||||
// process length
|
||||
if (aHeaderLength < (65536U - 256U))
|
||||
{
|
||||
mBlock[blockLength++] ^= aHeaderLength >> 8;
|
||||
mBlock[blockLength++] ^= aHeaderLength >> 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mBlock[blockLength++] ^= 0xff;
|
||||
mBlock[blockLength++] ^= 0xfe;
|
||||
mBlock[blockLength++] ^= aHeaderLength >> 24;
|
||||
mBlock[blockLength++] ^= aHeaderLength >> 16;
|
||||
mBlock[blockLength++] ^= aHeaderLength >> 8;
|
||||
mBlock[blockLength++] ^= aHeaderLength >> 0;
|
||||
}
|
||||
}
|
||||
|
||||
// init counter
|
||||
mCtr[0] = L - 1;
|
||||
|
||||
for (i = 0; i < aNonceLength; i++)
|
||||
{
|
||||
mCtr[1 + i] = nonceBytes[i];
|
||||
}
|
||||
|
||||
for (i = i + 1; i < sizeof(mCtr); i++)
|
||||
{
|
||||
mCtr[i] = 0;
|
||||
}
|
||||
|
||||
mNonceLength = aNonceLength;
|
||||
mHeaderLength = aHeaderLength;
|
||||
mHeaderCur = 0;
|
||||
mPlainTextLength = aPlainTextLength;
|
||||
mPlainTextCur = 0;
|
||||
mBlockLength = blockLength;
|
||||
mCtrLength = sizeof(mCtrPad);
|
||||
mTagLength = aTagLength;
|
||||
}
|
||||
|
||||
void AesCcm::Header(const void *aHeader, uint32_t aHeaderLength)
|
||||
{
|
||||
const uint8_t *headerBytes = reinterpret_cast<const uint8_t *>(aHeader);
|
||||
|
||||
assert(mHeaderCur + aHeaderLength <= mHeaderLength);
|
||||
|
||||
// process header
|
||||
for (unsigned i = 0; i < aHeaderLength; i++)
|
||||
{
|
||||
if (mBlockLength == sizeof(mBlock))
|
||||
{
|
||||
otCryptoAesEcbEncrypt(mBlock, mBlock);
|
||||
mBlockLength = 0;
|
||||
}
|
||||
|
||||
mBlock[mBlockLength++] ^= headerBytes[i];
|
||||
}
|
||||
|
||||
mHeaderCur += aHeaderLength;
|
||||
|
||||
if (mHeaderCur == mHeaderLength)
|
||||
{
|
||||
// process remainder
|
||||
if (mBlockLength != 0)
|
||||
{
|
||||
otCryptoAesEcbEncrypt(mBlock, mBlock);
|
||||
}
|
||||
|
||||
mBlockLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AesCcm::Payload(void *plaintext, void *ciphertext, uint32_t len, bool aEncrypt)
|
||||
{
|
||||
uint8_t *plaintextBytes = reinterpret_cast<uint8_t *>(plaintext);
|
||||
uint8_t *ciphertextBytes = reinterpret_cast<uint8_t *>(ciphertext);
|
||||
uint8_t byte;
|
||||
|
||||
assert(mPlainTextCur + len <= mPlainTextLength);
|
||||
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
if (mCtrLength == 16)
|
||||
{
|
||||
for (int j = sizeof(mCtr) - 1; j > mNonceLength; j--)
|
||||
{
|
||||
if (++mCtr[j])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
otCryptoAesEcbEncrypt(mCtr, mCtrPad);
|
||||
mCtrLength = 0;
|
||||
}
|
||||
|
||||
if (aEncrypt)
|
||||
{
|
||||
byte = plaintextBytes[i];
|
||||
ciphertextBytes[i] = byte ^ mCtrPad[mCtrLength++];
|
||||
}
|
||||
else
|
||||
{
|
||||
byte = ciphertextBytes[i] ^ mCtrPad[mCtrLength++];
|
||||
plaintextBytes[i] = byte;
|
||||
}
|
||||
|
||||
if (mBlockLength == sizeof(mBlock))
|
||||
{
|
||||
otCryptoAesEcbEncrypt(mBlock, mBlock);
|
||||
mBlockLength = 0;
|
||||
}
|
||||
|
||||
mBlock[mBlockLength++] ^= byte;
|
||||
}
|
||||
|
||||
mPlainTextCur += len;
|
||||
|
||||
if (mPlainTextCur >= mPlainTextLength)
|
||||
{
|
||||
if (mBlockLength != 0)
|
||||
{
|
||||
otCryptoAesEcbEncrypt(mBlock, mBlock);
|
||||
}
|
||||
|
||||
// reset counter
|
||||
for (uint8_t i = mNonceLength + 1; i < sizeof(mCtr); i++)
|
||||
{
|
||||
mCtr[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AesCcm::Finalize(void *tag, uint8_t *aTagLength)
|
||||
{
|
||||
uint8_t *tagBytes = reinterpret_cast<uint8_t *>(tag);
|
||||
|
||||
assert(mPlainTextCur == mPlainTextLength);
|
||||
|
||||
if (mTagLength > 0)
|
||||
{
|
||||
otCryptoAesEcbEncrypt(mCtr, mCtrPad);
|
||||
|
||||
for (int i = 0; i < mTagLength; i++)
|
||||
{
|
||||
tagBytes[i] = mBlock[i] ^ mCtrPad[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (aTagLength)
|
||||
{
|
||||
*aTagLength = mTagLength;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Crypto
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for performing AES-CCM computations.
|
||||
*/
|
||||
|
||||
#ifndef AES_CCM_HPP_
|
||||
#define AES_CCM_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <crypto/aes_ecb.h>
|
||||
|
||||
namespace Thread {
|
||||
namespace Crypto {
|
||||
|
||||
/**
|
||||
* @addtogroup core-security
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements AES CCM computation.
|
||||
*
|
||||
*/
|
||||
class AesCcm
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method sets the key.
|
||||
*
|
||||
* @param[in] aKey A pointer to the key.
|
||||
* @param[in] aKeyLength Length of the key in bytes.
|
||||
*
|
||||
*/
|
||||
ThreadError SetKey(const uint8_t *aKey, uint16_t aKeyLength);
|
||||
|
||||
/**
|
||||
* This method initializes the AES CCM computation.
|
||||
*
|
||||
* @param[in] aHeaderLength Length of header in bytes.
|
||||
* @param[in] aPlainTextLength Length of plaintext in bytes.
|
||||
* @param[in] aTagLength Length of tag in bytes.
|
||||
* @param[in] aNonce A pointer to the nonce.
|
||||
* @param[in] aNonceLength Length of nonce in bytes.
|
||||
*
|
||||
*/
|
||||
void Init(uint32_t aHeaderLength, uint32_t aPlainTextLength, uint8_t aTagLength,
|
||||
const void *aNonce, uint8_t aNonceLength);
|
||||
|
||||
/**
|
||||
* This method processes the header.
|
||||
*
|
||||
* @param[in] aHeader A pointer to the header.
|
||||
* @param[in] aHeaderLength Lenth of header in bytes.
|
||||
*
|
||||
*/
|
||||
void Header(const void *aHeader, uint32_t aHeaderLength);
|
||||
|
||||
/**
|
||||
* This method processes the payload.
|
||||
*
|
||||
* @param[inout] aPlainText A pointer to the plaintext.
|
||||
* @param[inout] aCipherText A pointer to the ciphertext.
|
||||
* @param[in] aLength Payload length in bytes.
|
||||
* @param[in] aEncrypt TRUE on encrypt and FALSE on decrypt.
|
||||
*
|
||||
*/
|
||||
void Payload(void *aPlainText, void *aCipherText, uint32_t aLength, bool aEncrypt);
|
||||
|
||||
/**
|
||||
* This method generates the tag.
|
||||
*
|
||||
* @param[out] aTag A pointer to the tag.
|
||||
* @param[out] aTagLength Length of the tag in bytes.
|
||||
*
|
||||
*/
|
||||
void Finalize(void *aTag, uint8_t *aTagLength);
|
||||
|
||||
private:
|
||||
uint8_t mBlock[otAesBlockSize];
|
||||
uint8_t mCtr[otAesBlockSize];
|
||||
uint8_t mCtrPad[otAesBlockSize];
|
||||
uint8_t mNonceLength;
|
||||
uint32_t mHeaderLength;
|
||||
uint32_t mHeaderCur;
|
||||
uint32_t mPlainTextLength;
|
||||
uint32_t mPlainTextCur;
|
||||
uint16_t mBlockLength;
|
||||
uint16_t mCtrLength;
|
||||
uint8_t mTagLength;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Crypto
|
||||
} // namespace Thread
|
||||
|
||||
#endif // AES_CCM_HPP_
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for computing hashes.
|
||||
*/
|
||||
|
||||
#ifndef HASH_HPP_
|
||||
#define HASH_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
|
||||
namespace Thread {
|
||||
namespace Crypto {
|
||||
|
||||
/**
|
||||
* @addtogroup core-security
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements hash computations.
|
||||
*
|
||||
*/
|
||||
class Hash
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method returns the hash size.
|
||||
*
|
||||
* @returns The hash size.
|
||||
*
|
||||
*/
|
||||
virtual uint16_t GetSize(void) const = 0;
|
||||
|
||||
/**
|
||||
* This method initializes the hash computation.
|
||||
*
|
||||
*/
|
||||
virtual void Init(void) = 0;
|
||||
|
||||
/**
|
||||
* This method inputs data into the hash.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the input buffer.
|
||||
* @param[in] aBufLength The length of @p aBuf in bytes.
|
||||
*
|
||||
*/
|
||||
virtual void Input(const void *aBuf, uint16_t aBufLength) = 0;
|
||||
|
||||
/**
|
||||
* This method finalizes the hash computation.
|
||||
*
|
||||
* @param[out] aHash A pointer to the output buffer.
|
||||
*
|
||||
*/
|
||||
virtual void Finalize(uint8_t *aHash) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Crypto
|
||||
} // namespace Thread
|
||||
|
||||
#endif // HASH_HPP_
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for computing HMACs.
|
||||
*/
|
||||
|
||||
#ifndef HMAC_HPP_
|
||||
#define HMAC_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <crypto/hash.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Crypto {
|
||||
|
||||
/**
|
||||
* @addtogroup core-security
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements HMAC computation.
|
||||
*
|
||||
*/
|
||||
class Hmac
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor intializes the object.
|
||||
*
|
||||
*/
|
||||
explicit Hmac(Hash &aHash);
|
||||
|
||||
/**
|
||||
* This method sets the key.
|
||||
*
|
||||
* @param[in] aKey A pointer to the key.
|
||||
* @param[in] aKeyLength The key length in bytes.
|
||||
*
|
||||
*/
|
||||
void SetKey(const void *aKey, uint16_t aKeyLength);
|
||||
|
||||
/**
|
||||
* This method initializes the HMAC computation.
|
||||
*
|
||||
*/
|
||||
void Init(void);
|
||||
|
||||
/**
|
||||
* This method inputs bytes into the HMAC computation.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the input buffer.
|
||||
* @param[in] aBufLength The length of @p aBuf in bytes.
|
||||
*
|
||||
*/
|
||||
void Input(const void *aBuf, uint16_t aBufLength);
|
||||
|
||||
/**
|
||||
* This method finalizes the hash computation.
|
||||
*
|
||||
* @param[out] aHash A pointer to the output buffer.
|
||||
*
|
||||
*/
|
||||
void Finalize(uint8_t *aHash);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxKeyLength = 64,
|
||||
};
|
||||
uint8_t mKey[kMaxKeyLength];
|
||||
uint8_t mKeyLength = 0;
|
||||
Hash *mHash;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Crypto
|
||||
} // namespace Thread
|
||||
|
||||
#endif // CRYPTO_HMAC_HPP_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for the IEEE 802.15.4 MAC.
|
||||
*/
|
||||
|
||||
#ifndef MAC_HPP_
|
||||
#define MAC_HPP_
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <common/tasklet.hpp>
|
||||
#include <common/timer.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <mac/mac_whitelist.hpp>
|
||||
#include <platform/radio.h>
|
||||
#include <thread/key_manager.hpp>
|
||||
#include <thread/topology.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
namespace Mle { class MleRouter; }
|
||||
|
||||
/**
|
||||
* @addtogroup core-mac
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for the IEEE 802.15.4 MAC
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Mac {
|
||||
|
||||
/**
|
||||
* Protocol parameters and constants.
|
||||
*
|
||||
*/
|
||||
enum
|
||||
{
|
||||
kMinBE = 3, ///< macMinBE (IEEE 802.15.4-2006)
|
||||
kMaxBE = 6, ///< macMaxBE (IEEE 802.15.4-2006)
|
||||
kMaxCSMABackoffs = 12, ///< macMaxCSMABackoffs (IEEE 802.15.4-2006)
|
||||
kUnitBackoffPeriod = 20, ///< Number of symbols (IEEE 802.15.4-2006)
|
||||
|
||||
kMinBackoff = 16, ///< Minimum backoff (milliseconds).
|
||||
|
||||
kAckTimeout = 16, ///< Timeout for waiting on an ACK (milliseconds).
|
||||
kDataPollTimeout = 100, ///< Timeout for receivint Data Frame (milliseconds).
|
||||
kNonceSize = 13, ///< Size of IEEE 802.15.4 Nonce (bytes).
|
||||
|
||||
kScanChannelMaskAll = 0xffff,
|
||||
kScanDefaultInterval = 128, ///< Default interval between channels (milliseconds).
|
||||
|
||||
kNetworkNameSize = 16, ///< Size of Thread Network Name (bytes).
|
||||
kExtPanIdSize = 8, ///< Size of Thread Extended PAN ID.
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents an Active Scan result.
|
||||
*
|
||||
*/
|
||||
struct ActiveScanResult
|
||||
{
|
||||
char mNetworkName[kNetworkNameSize]; ///< The Thread Network Name.
|
||||
uint8_t mExtPanid[kExtPanIdSize]; ///< The Thread Extended PAN ID.
|
||||
uint8_t mExtAddr[ExtAddress::kLength]; ///< The IEEE 802.15.4 Extended Address.
|
||||
uint16_t mPanId; ///< The IEEE 802.15.4 PAN ID.
|
||||
uint8_t mChannel; ///< The IEEE 802.15.4 Channel.
|
||||
int8_t mRssi; ///< The RSSI in dBm.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements a MAC receiver client.
|
||||
*
|
||||
*/
|
||||
class Receiver
|
||||
{
|
||||
friend class Mac;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when a MAC frame is received.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aFrame A reference to the MAC frame.
|
||||
* @param[in] aError Any errors that occured during reception.
|
||||
*
|
||||
*/
|
||||
typedef void (*ReceiveFrameHandler)(void *aContext, Frame &aFrame, ThreadError aError);
|
||||
|
||||
/**
|
||||
* This constructor creates a MAC receiver client.
|
||||
*
|
||||
* @param[in] aReceiveFrameHandler A pointer to a function that is called on MAC frame reception.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
Receiver(ReceiveFrameHandler aReceiveFrameHandler, void *aContext) {
|
||||
mReceiveFrameHandler = aReceiveFrameHandler;
|
||||
mContext = aContext;
|
||||
mNext = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
void HandleReceivedFrame(Frame &frame, ThreadError error) { mReceiveFrameHandler(mContext, frame, error); }
|
||||
|
||||
ReceiveFrameHandler mReceiveFrameHandler;
|
||||
void *mContext;
|
||||
Receiver *mNext;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements a MAC sender client.
|
||||
*
|
||||
*/
|
||||
class Sender
|
||||
{
|
||||
friend class Mac;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when the MAC is about to transmit the frame.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aFrame A reference to the MAC frame buffer.
|
||||
*
|
||||
*/
|
||||
typedef ThreadError(*FrameRequestHandler)(void *aContext, Frame &aFrame);
|
||||
|
||||
/**
|
||||
* This function pointer is called when the MAC is done sending the frame.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aFrame A reference to the MAC frame buffer that was sent.
|
||||
*
|
||||
*/
|
||||
typedef void (*SentFrameHandler)(void *aContext, Frame &aFrame);
|
||||
|
||||
/**
|
||||
* This constructor creates a MAC sender client.
|
||||
*
|
||||
* @param[in] aFrameRequestHandler A pointer to a function that is called when about to send a MAC frame.
|
||||
* @param[in] aSentFrameHandler A pointer to a function that is called when done sending the frame.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
Sender(FrameRequestHandler aFrameRequestHandler, SentFrameHandler aSentFrameHandler, void *aContext) {
|
||||
mFrameRequestHandler = aFrameRequestHandler;
|
||||
mSentFrameHandler = aSentFrameHandler;
|
||||
mContext = aContext;
|
||||
mNext = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadError HandleFrameRequest(Frame &frame) { return mFrameRequestHandler(mContext, frame); }
|
||||
void HandleSentFrame(Frame &frame) { mSentFrameHandler(mContext, frame); }
|
||||
|
||||
FrameRequestHandler mFrameRequestHandler;
|
||||
SentFrameHandler mSentFrameHandler;
|
||||
void *mContext;
|
||||
Sender *mNext;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements the IEEE 802.15.4 MAC.
|
||||
*
|
||||
*/
|
||||
class Mac
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the MAC object.
|
||||
*
|
||||
* @param[in] aThreadNetif A reference to the network interface using this MAC.
|
||||
*
|
||||
*/
|
||||
explicit Mac(ThreadNetif &aThreadNetif);
|
||||
|
||||
/**
|
||||
* This method starts the MAC.
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the MAC.
|
||||
* @retval kThreadError_Busy The MAC could not be started.
|
||||
*
|
||||
*/
|
||||
ThreadError Start(void);
|
||||
|
||||
/**
|
||||
* This method stops the MAC.
|
||||
*
|
||||
* @retval kThreadError_None Successfully stopped the MAC.
|
||||
* @retval kThreadError_Busy The MAC could not be stopped.
|
||||
*
|
||||
*/
|
||||
ThreadError Stop(void);
|
||||
|
||||
/**
|
||||
* This function pointer is called on receiving an IEEE 802.15.4 Beacon during an Active Scan.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aResult A reference to the Active Scan result.
|
||||
*
|
||||
*/
|
||||
typedef void (*ActiveScanHandler)(void *aContext, ActiveScanResult *aResult);
|
||||
|
||||
/**
|
||||
* This method starts an IEEE 802.15.4 Active Scan.
|
||||
*
|
||||
* @param[in] aIntervalPerChannel The time in milliseconds to spend scanning each channel.
|
||||
* @param[in] aChannelMask A bit vector indicating which channels to scan.
|
||||
* @param[in] aHandler A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
ThreadError ActiveScan(uint16_t aIntervalPerChannel, uint16_t aChannelMask,
|
||||
ActiveScanHandler aHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not rx-on-when-idle is enabled.
|
||||
*
|
||||
* @retval TRUE If rx-on-when-idle is enabled.
|
||||
* @retval FALSE If rx-on-when-idle is not enabled.
|
||||
*/
|
||||
bool GetRxOnWhenIdle(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the rx-on-when-idle mode.
|
||||
*
|
||||
* @param[in] aRxOnWhenIdle The rx-on-when-idle mode.
|
||||
*
|
||||
*/
|
||||
void SetRxOnWhenIdle(bool aRxOnWhenIdle);
|
||||
|
||||
/**
|
||||
* This method registers a new MAC receiver client.
|
||||
*
|
||||
* @param[in] aReceiver A reference to the MAC receiver client.
|
||||
*
|
||||
* @retval kThreadError_None Successfully registered the receiver.
|
||||
* @retval kThreadError_Busy The receiver was already registered.
|
||||
*
|
||||
*/
|
||||
ThreadError RegisterReceiver(Receiver &aReceiver);
|
||||
|
||||
/**
|
||||
* This method registers a new MAC sender client.
|
||||
*
|
||||
* @param[in] aSender A reference to the MAC sender client.
|
||||
*
|
||||
* @retval kThreadError_None Successfully registered the sender.
|
||||
* @retval kThreadError_Busy The sender was already registered.
|
||||
*
|
||||
*/
|
||||
ThreadError SendFrameRequest(Sender &aSender);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the IEEE 802.15.4 Extended Address.
|
||||
*
|
||||
* @returns A pointer to the IEEE 802.15.4 Extended Address.
|
||||
*
|
||||
*/
|
||||
const ExtAddress *GetExtAddress(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Short Address.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 Short Address.
|
||||
*
|
||||
*/
|
||||
ShortAddress GetShortAddress(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 Short Address.
|
||||
*
|
||||
* @param[in] aShortAddress The IEEE 802.15.4 Short Address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the IEEE 802.15.4 Short Address.
|
||||
*
|
||||
*/
|
||||
ThreadError SetShortAddress(ShortAddress aShortAddress);
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Channel.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 Channel.
|
||||
*
|
||||
*/
|
||||
uint8_t GetChannel(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 Channel.
|
||||
*
|
||||
* @param[in] aChannel The IEEE 802.15.4 Channel.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the IEEE 802.15.4 Channel.
|
||||
*
|
||||
*/
|
||||
ThreadError SetChannel(uint8_t aChannel);
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Network Name.
|
||||
*
|
||||
* @returns A pointer to the IEEE 802.15.4 Network Name.
|
||||
*
|
||||
*/
|
||||
const char *GetNetworkName(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 Network Name.
|
||||
*
|
||||
* @param[in] aNetworkName A pointer to the IEEE 802.15.4 Network Name.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the IEEE 802.15.4 Network Name.
|
||||
*
|
||||
*/
|
||||
ThreadError SetNetworkName(const char *aNetworkName);
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 PAN ID.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 PAN ID.
|
||||
*
|
||||
*/
|
||||
uint16_t GetPanId(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 PAN ID.
|
||||
*
|
||||
* @param[in] aPanId The IEEE 802.15.4 PAN ID.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the IEEE 802.15.4 PAN ID.
|
||||
*
|
||||
*/
|
||||
ThreadError SetPanId(uint16_t aPanId);
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Extended PAN ID.
|
||||
*
|
||||
* @returns A pointer to the IEEE 802.15.4 Extended PAN ID.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetExtendedPanId(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 Extended PAN ID.
|
||||
*
|
||||
* @param[in] aExtPanId The IEEE 802.15.4 Extended PAN ID.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the IEEE 802.15.4 Extended PAN ID.
|
||||
*
|
||||
*/
|
||||
ThreadError SetExtendedPanId(const uint8_t *aExtPanId);
|
||||
|
||||
/**
|
||||
* This method returns the MAC whitelist filter.
|
||||
*
|
||||
* @returns A reference to the MAC whitelist filter.
|
||||
*
|
||||
*/
|
||||
Whitelist &GetWhitelist(void);
|
||||
|
||||
/**
|
||||
* This method is called to handle receive events.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
static void ReceiveDoneTask(void *aContext);
|
||||
|
||||
/**
|
||||
* This method is called to handle transmit events.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
static void TransmitDoneTask(void *aContext);
|
||||
|
||||
private:
|
||||
void GenerateNonce(const ExtAddress &aAddress, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce);
|
||||
void NextOperation(void);
|
||||
void ProcessTransmitSecurity(void);
|
||||
ThreadError ProcessReceiveSecurity(const Address &aSrcAddr, Neighbor *aNeighbor);
|
||||
void ScheduleNextTransmission(void);
|
||||
void SentFrame(bool aAcked);
|
||||
void SendBeaconRequest(Frame &aFrame);
|
||||
void SendBeacon(Frame &aFrame);
|
||||
void StartBackoff(void);
|
||||
void HandleBeaconFrame(void);
|
||||
ThreadError HandleMacCommand(void);
|
||||
|
||||
static void HandleAckTimer(void *aContext);
|
||||
void HandleAckTimer(void);
|
||||
static void HandleBeginTransmit(void *aContext);
|
||||
void HandleBeginTransmit(void);
|
||||
static void HandleReceiveTimer(void *aContext);
|
||||
void HandleReceiveTimer(void);
|
||||
|
||||
void StartCsmaBackoff(void);
|
||||
|
||||
void ReceiveDoneTask(void);
|
||||
void TransmitDoneTask(void);
|
||||
|
||||
Tasklet mBeginTransmit;
|
||||
Timer mAckTimer;
|
||||
Timer mBackoffTimer;
|
||||
Timer mReceiveTimer;
|
||||
|
||||
KeyManager &mKeyManager;
|
||||
Mle::MleRouter &mMle;
|
||||
|
||||
ExtAddress mExtAddress;
|
||||
ShortAddress mShortAddress;
|
||||
uint16_t mPanId;
|
||||
uint8_t mExtendedPanid[kExtPanIdSize];
|
||||
char mNetworkName[kNetworkNameSize];
|
||||
uint8_t mChannel;
|
||||
|
||||
Frame mSendFrame;
|
||||
Frame mReceiveFrame;
|
||||
Sender *mSendHead, *mSendTail;
|
||||
Receiver *mReceiveHead, *mReceiveTail;
|
||||
|
||||
enum
|
||||
{
|
||||
kStateDisabled = 0,
|
||||
kStateIdle,
|
||||
kStateActiveScan,
|
||||
kStateTransmitBeacon,
|
||||
kStateTransmitData,
|
||||
};
|
||||
uint8_t mState;
|
||||
|
||||
uint8_t mBeaconSequence;
|
||||
uint8_t mDataSequence;
|
||||
bool mRxOnWhenIdle;
|
||||
uint8_t mCsmaAttempts;
|
||||
bool mTransmitBeacon;
|
||||
|
||||
bool mActiveScanRequest;
|
||||
uint8_t mScanChannel;
|
||||
uint16_t mScanChannelMask;
|
||||
uint16_t mScanIntervalPerChannel;
|
||||
ActiveScanHandler mActiveScanHandler;
|
||||
void *mActiveScanContext;
|
||||
|
||||
Whitelist mWhitelist;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Mac
|
||||
} // namespace Thread
|
||||
|
||||
#endif // MAC_HPP_
|
||||
@@ -0,0 +1,827 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements IEEE 802.15.4 header generation and processing.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Mac {
|
||||
|
||||
void ExtAddress::Set(const Ip6::Address &aIpAddress)
|
||||
{
|
||||
memcpy(mBytes, aIpAddress.GetIid(), kLength);
|
||||
mBytes[0] ^= 0x02;
|
||||
}
|
||||
|
||||
ThreadError Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl)
|
||||
{
|
||||
uint8_t *bytes = GetPsdu();
|
||||
uint8_t length = 0;
|
||||
|
||||
// Frame Control Field
|
||||
bytes[0] = aFcf;
|
||||
bytes[1] = aFcf >> 8;
|
||||
length += kFcfSize;
|
||||
|
||||
// Sequence Number
|
||||
length += kDsnSize;
|
||||
|
||||
// Destinatino PAN + Address
|
||||
switch (aFcf & Frame::kFcfDstAddrMask)
|
||||
{
|
||||
case Frame::kFcfDstAddrNone:
|
||||
break;
|
||||
|
||||
case Frame::kFcfDstAddrShort:
|
||||
length += sizeof(PanId) + sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case Frame::kFcfDstAddrExt:
|
||||
length += sizeof(PanId) + sizeof(ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// Source PAN + Address
|
||||
switch (aFcf & Frame::kFcfSrcAddrMask)
|
||||
{
|
||||
case Frame::kFcfSrcAddrNone:
|
||||
break;
|
||||
|
||||
case Frame::kFcfSrcAddrShort:
|
||||
if ((aFcf & Frame::kFcfPanidCompression) == 0)
|
||||
{
|
||||
length += sizeof(PanId);
|
||||
}
|
||||
|
||||
length += sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case Frame::kFcfSrcAddrExt:
|
||||
if ((aFcf & Frame::kFcfPanidCompression) == 0)
|
||||
{
|
||||
length += sizeof(PanId);
|
||||
}
|
||||
|
||||
length += sizeof(ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// Security Header
|
||||
if (aFcf & Frame::kFcfSecurityEnabled)
|
||||
{
|
||||
bytes[length] = aSecurityControl;
|
||||
|
||||
if (aSecurityControl & kSecLevelMask)
|
||||
{
|
||||
length += 5;
|
||||
}
|
||||
|
||||
switch (aSecurityControl & kKeyIdModeMask)
|
||||
{
|
||||
case kKeyIdMode0:
|
||||
length += kKeyIdLengthMode0;
|
||||
break;
|
||||
|
||||
case kKeyIdMode1:
|
||||
length += kKeyIdLengthMode1;
|
||||
break;
|
||||
|
||||
case kKeyIdMode2:
|
||||
length += kKeyIdLengthMode2;
|
||||
break;
|
||||
|
||||
case kKeyIdMode3:
|
||||
length += kKeyIdLengthMode3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Command ID
|
||||
if ((aFcf & kFcfFrameTypeMask) == kFcfFrameMacCmd)
|
||||
{
|
||||
length += kCommandIdSize;
|
||||
}
|
||||
|
||||
SetPsduLength(length + GetFooterLength());
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
uint8_t Frame::GetType(void)
|
||||
{
|
||||
return GetPsdu()[0] & Frame::kFcfFrameTypeMask;
|
||||
}
|
||||
|
||||
bool Frame::GetSecurityEnabled(void)
|
||||
{
|
||||
return (GetPsdu()[0] & Frame::kFcfSecurityEnabled) != 0;
|
||||
}
|
||||
|
||||
bool Frame::GetAckRequest(void)
|
||||
{
|
||||
return (GetPsdu()[0] & Frame::kFcfAckRequest) != 0;
|
||||
}
|
||||
|
||||
void Frame::SetAckRequest(bool aAckRequest)
|
||||
{
|
||||
if (aAckRequest)
|
||||
{
|
||||
GetPsdu()[0] |= Frame::kFcfAckRequest;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetPsdu()[0] &= ~Frame::kFcfAckRequest;
|
||||
}
|
||||
}
|
||||
|
||||
bool Frame::GetFramePending(void)
|
||||
{
|
||||
return (GetPsdu()[0] & Frame::kFcfFramePending) != 0;
|
||||
}
|
||||
|
||||
void Frame::SetFramePending(bool aFramePending)
|
||||
{
|
||||
if (aFramePending)
|
||||
{
|
||||
GetPsdu()[0] |= Frame::kFcfFramePending;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetPsdu()[0] &= ~Frame::kFcfFramePending;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *Frame::FindSequence(void)
|
||||
{
|
||||
uint8_t *cur = GetPsdu();
|
||||
|
||||
// Frame Control Field
|
||||
cur += kFcfSize;
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
uint8_t Frame::GetSequence(void)
|
||||
{
|
||||
uint8_t *buf = FindSequence();
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
void Frame::SetSequence(uint8_t aSequence)
|
||||
{
|
||||
uint8_t *buf = FindSequence();
|
||||
buf[0] = aSequence;
|
||||
}
|
||||
|
||||
uint8_t *Frame::FindDstPanId(void)
|
||||
{
|
||||
uint8_t *cur = GetPsdu();
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
VerifyOrExit((fcf & Frame::kFcfDstAddrMask) != Frame::kFcfDstAddrNone, cur = NULL);
|
||||
|
||||
// Frame Control Field
|
||||
cur += kFcfSize;
|
||||
// Sequence Number
|
||||
cur += kDsnSize;
|
||||
|
||||
exit:
|
||||
return cur;
|
||||
}
|
||||
|
||||
ThreadError Frame::GetDstPanId(PanId &aPanId)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
|
||||
VerifyOrExit((buf = FindDstPanId()) != NULL, error = kThreadError_Parse);
|
||||
|
||||
aPanId = (static_cast<uint16_t>(buf[1]) << 8) | buf[0];
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetDstPanId(PanId aPanId)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
buf = FindDstPanId();
|
||||
assert(buf != NULL);
|
||||
|
||||
buf[0] = aPanId;
|
||||
buf[1] = aPanId >> 8;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
uint8_t *Frame::FindDstAddr(void)
|
||||
{
|
||||
uint8_t *cur = GetPsdu();
|
||||
|
||||
// Frame Control Field
|
||||
cur += kFcfSize;
|
||||
// Sequence Number
|
||||
cur += kDsnSize;
|
||||
// Destination PAN
|
||||
cur += sizeof(PanId);
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
ThreadError Frame::GetDstAddr(Address &aAddress)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
VerifyOrExit(buf = FindDstAddr(), error = kThreadError_Parse);
|
||||
|
||||
switch (fcf & Frame::kFcfDstAddrMask)
|
||||
{
|
||||
case Frame::kFcfDstAddrShort:
|
||||
aAddress.mLength = sizeof(ShortAddress);
|
||||
aAddress.mShortAddress = (static_cast<uint16_t>(buf[1]) << 8) | buf[0];
|
||||
break;
|
||||
|
||||
case Frame::kFcfDstAddrExt:
|
||||
aAddress.mLength = sizeof(ExtAddress);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(ExtAddress); i++)
|
||||
{
|
||||
aAddress.mExtAddress.mBytes[i] = buf[sizeof(ExtAddress) - 1 - i];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
aAddress.mLength = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetDstAddr(ShortAddress aShortAddress)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
assert((fcf & Frame::kFcfDstAddrMask) == Frame::kFcfDstAddrShort);
|
||||
|
||||
buf = FindDstAddr();
|
||||
assert(buf != NULL);
|
||||
|
||||
buf[0] = aShortAddress;
|
||||
buf[1] = aShortAddress >> 8;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetDstAddr(const ExtAddress &aExtAddress)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
assert((fcf & Frame::kFcfDstAddrMask) == Frame::kFcfDstAddrExt);
|
||||
|
||||
buf = FindDstAddr();
|
||||
assert(buf != NULL);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(ExtAddress); i++)
|
||||
{
|
||||
buf[i] = aExtAddress.mBytes[sizeof(ExtAddress) - 1 - i];
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
uint8_t *Frame::FindSrcPanId(void)
|
||||
{
|
||||
uint8_t *cur = GetPsdu();
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
VerifyOrExit((fcf & Frame::kFcfDstAddrMask) != Frame::kFcfDstAddrNone ||
|
||||
(fcf & Frame::kFcfSrcAddrMask) != Frame::kFcfSrcAddrNone, cur = NULL);
|
||||
|
||||
// Frame Control Field
|
||||
cur += kFcfSize;
|
||||
// Sequence Number
|
||||
cur += kDsnSize;
|
||||
|
||||
if ((fcf & Frame::kFcfPanidCompression) == 0)
|
||||
{
|
||||
// Destination PAN + Address
|
||||
switch (fcf & Frame::kFcfDstAddrMask)
|
||||
{
|
||||
case Frame::kFcfDstAddrShort:
|
||||
cur += sizeof(PanId) + sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case Frame::kFcfDstAddrExt:
|
||||
cur += sizeof(PanId) + sizeof(ExtAddress);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return cur;
|
||||
}
|
||||
|
||||
ThreadError Frame::GetSrcPanId(PanId &aPanId)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
|
||||
VerifyOrExit((buf = FindSrcPanId()) != NULL, error = kThreadError_Parse);
|
||||
|
||||
aPanId = (static_cast<uint16_t>(buf[1]) << 8) | buf[0];
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetSrcPanId(PanId aPanId)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
buf = FindSrcPanId();
|
||||
assert(buf != NULL);
|
||||
|
||||
buf[0] = aPanId;
|
||||
buf[1] = aPanId >> 8;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
uint8_t *Frame::FindSrcAddr(void)
|
||||
{
|
||||
uint8_t *cur = GetPsdu();
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
// Frame Control Field
|
||||
cur += kFcfSize;
|
||||
// Sequence Number
|
||||
cur += kDsnSize;
|
||||
|
||||
// Destination PAN + Address
|
||||
switch (fcf & Frame::kFcfDstAddrMask)
|
||||
{
|
||||
case Frame::kFcfDstAddrShort:
|
||||
cur += sizeof(PanId) + sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case Frame::kFcfDstAddrExt:
|
||||
cur += sizeof(PanId) + sizeof(ExtAddress);
|
||||
break;
|
||||
}
|
||||
|
||||
// Source PAN
|
||||
if ((fcf & Frame::kFcfPanidCompression) == 0)
|
||||
{
|
||||
cur += sizeof(PanId);
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
ThreadError Frame::GetSrcAddr(Address &address)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
VerifyOrExit((buf = FindSrcAddr()) != NULL, error = kThreadError_Parse);
|
||||
|
||||
switch (fcf & Frame::kFcfSrcAddrMask)
|
||||
{
|
||||
case Frame::kFcfSrcAddrShort:
|
||||
address.mLength = sizeof(ShortAddress);
|
||||
address.mShortAddress = (static_cast<uint16_t>(buf[1]) << 8) | buf[0];;
|
||||
break;
|
||||
|
||||
case Frame::kFcfSrcAddrExt:
|
||||
address.mLength = sizeof(ExtAddress);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(ExtAddress); i++)
|
||||
{
|
||||
address.mExtAddress.mBytes[i] = buf[sizeof(ExtAddress) - 1 - i];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
address.mLength = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetSrcAddr(ShortAddress aShortAddress)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
assert((fcf & Frame::kFcfSrcAddrMask) == Frame::kFcfSrcAddrShort);
|
||||
|
||||
buf = FindSrcAddr();
|
||||
assert(buf != NULL);
|
||||
|
||||
buf[0] = aShortAddress;
|
||||
buf[1] = aShortAddress >> 8;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetSrcAddr(const ExtAddress &aExtAddress)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
assert((fcf & Frame::kFcfSrcAddrMask) == Frame::kFcfSrcAddrExt);
|
||||
|
||||
buf = FindSrcAddr();
|
||||
assert(buf != NULL);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(aExtAddress); i++)
|
||||
{
|
||||
buf[i] = aExtAddress.mBytes[sizeof(aExtAddress) - 1 - i];
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
uint8_t *Frame::FindSecurityHeader(void)
|
||||
{
|
||||
uint8_t *cur = GetPsdu();
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
|
||||
VerifyOrExit((fcf & Frame::kFcfSecurityEnabled) != 0, cur = NULL);
|
||||
|
||||
// Frame Control Field
|
||||
cur += kFcfSize;
|
||||
// Sequence Number
|
||||
cur += kDsnSize;
|
||||
|
||||
// Destination PAN + Address
|
||||
switch (fcf & Frame::kFcfDstAddrMask)
|
||||
{
|
||||
case Frame::kFcfDstAddrShort:
|
||||
cur += sizeof(PanId) + sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case Frame::kFcfDstAddrExt:
|
||||
cur += sizeof(PanId) + sizeof(ExtAddress);
|
||||
break;
|
||||
}
|
||||
|
||||
// Source PAN + Address
|
||||
switch (fcf & Frame::kFcfSrcAddrMask)
|
||||
{
|
||||
case Frame::kFcfSrcAddrShort:
|
||||
if ((fcf & Frame::kFcfPanidCompression) == 0)
|
||||
{
|
||||
cur += sizeof(PanId);
|
||||
}
|
||||
|
||||
cur += sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case Frame::kFcfSrcAddrExt:
|
||||
if ((fcf & Frame::kFcfPanidCompression) == 0)
|
||||
{
|
||||
cur += sizeof(PanId);
|
||||
}
|
||||
|
||||
cur += sizeof(ExtAddress);
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return cur;
|
||||
}
|
||||
|
||||
ThreadError Frame::GetSecurityLevel(uint8_t &aSecurityLevel)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
|
||||
VerifyOrExit((buf = FindSecurityHeader()) != NULL, error = kThreadError_Parse);
|
||||
|
||||
aSecurityLevel = buf[0] & kSecLevelMask;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Frame::GetFrameCounter(uint32_t &aFrameCounter)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
|
||||
VerifyOrExit((buf = FindSecurityHeader()) != NULL, error = kThreadError_Parse);
|
||||
|
||||
// Security Control
|
||||
buf += kSecurityControlSize;
|
||||
|
||||
aFrameCounter = ((static_cast<uint32_t>(buf[3]) << 24) |
|
||||
(static_cast<uint32_t>(buf[2]) << 16) |
|
||||
(static_cast<uint32_t>(buf[1]) << 8) |
|
||||
(static_cast<uint32_t>(buf[0])));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetFrameCounter(uint32_t aFrameCounter)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
buf = FindSecurityHeader();
|
||||
assert(buf != NULL);
|
||||
|
||||
// Security Control
|
||||
buf += kSecurityControlSize;
|
||||
|
||||
buf[0] = aFrameCounter;
|
||||
buf[1] = aFrameCounter >> 8;
|
||||
buf[2] = aFrameCounter >> 16;
|
||||
buf[3] = aFrameCounter >> 24;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Frame::GetKeyId(uint8_t &aKeyId)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
|
||||
VerifyOrExit((buf = FindSecurityHeader()) != NULL, error = kThreadError_Parse);
|
||||
|
||||
// Security Control + Frame Counter
|
||||
buf += kSecurityControlSize + kFrameCounterSize;
|
||||
|
||||
aKeyId = buf[0];
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetKeyId(uint8_t aKeyId)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
buf = FindSecurityHeader();
|
||||
assert(buf != NULL);
|
||||
|
||||
// Security Control + Frame Counter
|
||||
buf += kSecurityControlSize + kFrameCounterSize;
|
||||
|
||||
buf[0] = aKeyId;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Frame::GetCommandId(uint8_t &aCommandId)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
|
||||
VerifyOrExit((buf = GetPayload()) != NULL, error = kThreadError_Parse);
|
||||
aCommandId = buf[-1];
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Frame::SetCommandId(uint8_t aCommandId)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
|
||||
VerifyOrExit((buf = GetPayload()) != NULL, error = kThreadError_Parse);
|
||||
buf[-1] = aCommandId;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t Frame::GetLength() const
|
||||
{
|
||||
return GetPsduLength();
|
||||
}
|
||||
|
||||
ThreadError Frame::SetLength(uint8_t aLength)
|
||||
{
|
||||
SetPsduLength(aLength);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
uint8_t Frame::GetHeaderLength(void)
|
||||
{
|
||||
return GetPayload() - GetPsdu();
|
||||
}
|
||||
|
||||
uint8_t Frame::GetFooterLength(void)
|
||||
{
|
||||
uint8_t footerLength = 0;
|
||||
uint8_t *cur;
|
||||
|
||||
VerifyOrExit((cur = FindSecurityHeader()) != NULL, ;);
|
||||
|
||||
switch (cur[0] & kSecLevelMask)
|
||||
{
|
||||
case kSecNone:
|
||||
case kSecEnc:
|
||||
footerLength += kMic0Size;
|
||||
break;
|
||||
|
||||
case kSecMic32:
|
||||
case kSecEncMic32:
|
||||
footerLength += kMic32Size;
|
||||
break;
|
||||
|
||||
case kSecMic64:
|
||||
case kSecEncMic64:
|
||||
footerLength += kMic64Size;
|
||||
break;
|
||||
|
||||
case kSecMic128:
|
||||
case kSecEncMic128:
|
||||
footerLength += kMic128Size;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
// Frame Check Sequence
|
||||
footerLength += kFcsSize;
|
||||
|
||||
return footerLength;
|
||||
}
|
||||
|
||||
uint8_t Frame::GetMaxPayloadLength(void)
|
||||
{
|
||||
return kMTU - (GetHeaderLength() + GetFooterLength());
|
||||
}
|
||||
|
||||
uint8_t Frame::GetPayloadLength(void)
|
||||
{
|
||||
return GetPsduLength() - (GetHeaderLength() + GetFooterLength());
|
||||
}
|
||||
|
||||
ThreadError Frame::SetPayloadLength(uint8_t aLength)
|
||||
{
|
||||
SetPsduLength(GetHeaderLength() + GetFooterLength() + aLength);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
uint8_t *Frame::GetHeader(void)
|
||||
{
|
||||
return GetPsdu();
|
||||
}
|
||||
|
||||
uint8_t *Frame::GetPayload(void)
|
||||
{
|
||||
uint8_t *cur = GetPsdu();
|
||||
uint16_t fcf = (static_cast<uint16_t>(GetPsdu()[1]) << 8) | GetPsdu()[0];
|
||||
uint8_t securityControl;
|
||||
|
||||
// Frame Control
|
||||
cur += kFcfSize;
|
||||
// Sequence Number
|
||||
cur += kDsnSize;
|
||||
|
||||
// Destination PAN + Address
|
||||
switch (fcf & Frame::kFcfDstAddrMask)
|
||||
{
|
||||
case Frame::kFcfDstAddrNone:
|
||||
break;
|
||||
|
||||
case Frame::kFcfDstAddrShort:
|
||||
cur += sizeof(PanId) + sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case Frame::kFcfDstAddrExt:
|
||||
cur += sizeof(PanId) + sizeof(ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(cur = NULL);
|
||||
}
|
||||
|
||||
// Source PAN + Address
|
||||
switch (fcf & Frame::kFcfSrcAddrMask)
|
||||
{
|
||||
case Frame::kFcfSrcAddrNone:
|
||||
break;
|
||||
|
||||
case Frame::kFcfSrcAddrShort:
|
||||
if ((fcf & Frame::kFcfPanidCompression) == 0)
|
||||
{
|
||||
cur += sizeof(PanId);
|
||||
}
|
||||
|
||||
cur += sizeof(ShortAddress);
|
||||
break;
|
||||
|
||||
case Frame::kFcfSrcAddrExt:
|
||||
if ((fcf & Frame::kFcfPanidCompression) == 0)
|
||||
{
|
||||
cur += sizeof(PanId);
|
||||
}
|
||||
|
||||
cur += sizeof(ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(cur = NULL);
|
||||
}
|
||||
|
||||
// Security Control + Frame Counter + Key Identifier
|
||||
if ((fcf & Frame::kFcfSecurityEnabled) != 0)
|
||||
{
|
||||
securityControl = *cur;
|
||||
|
||||
if (securityControl & kSecLevelMask)
|
||||
{
|
||||
cur += kSecurityControlSize + kFrameCounterSize;
|
||||
}
|
||||
|
||||
switch (securityControl & kKeyIdModeMask)
|
||||
{
|
||||
case kKeyIdMode0:
|
||||
cur += kKeyIdLengthMode0;
|
||||
break;
|
||||
|
||||
case kKeyIdMode1:
|
||||
cur += kKeyIdLengthMode1;
|
||||
break;
|
||||
|
||||
case kKeyIdMode2:
|
||||
cur += kKeyIdLengthMode2;
|
||||
break;
|
||||
|
||||
case kKeyIdMode3:
|
||||
cur += kKeyIdLengthMode3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Command ID
|
||||
if ((fcf & kFcfFrameTypeMask) == kFcfFrameMacCmd)
|
||||
{
|
||||
cur += kCommandIdSize;
|
||||
}
|
||||
|
||||
exit:
|
||||
return cur;
|
||||
}
|
||||
|
||||
uint8_t *Frame::GetFooter(void)
|
||||
{
|
||||
return GetPsdu() + GetPsduLength() - GetFooterLength();
|
||||
}
|
||||
|
||||
} // namespace Mac
|
||||
} // namespace Thread
|
||||
|
||||
@@ -0,0 +1,594 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for generating and processing IEEE 802.15.4 MAC frames.
|
||||
*/
|
||||
|
||||
#ifndef MAC_FRAME_HPP_
|
||||
#define MAC_FRAME_HPP_
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <platform/radio.h>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
namespace Ip6 { class Address; }
|
||||
|
||||
namespace Mac {
|
||||
|
||||
/**
|
||||
* @addtogroup core-mac
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
kShortAddrBroadcast = 0xffff,
|
||||
kShortAddrInvalid = 0xfffe,
|
||||
kPanIdBroadcast = 0xffff,
|
||||
};
|
||||
|
||||
/**
|
||||
* This type represents the IEEE 802.15.4 PAN ID.
|
||||
*
|
||||
*/
|
||||
typedef uint16_t PanId;
|
||||
|
||||
/**
|
||||
* This type represents the IEEE 802.15.4 Short Address.
|
||||
*
|
||||
*/
|
||||
typedef uint16_t ShortAddress;
|
||||
|
||||
/**
|
||||
* This structure represents an IEEE 802.15.4 Extended Address.
|
||||
*
|
||||
*/
|
||||
class ExtAddress
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method converts an IPv6 Interface Identifer to an IEEE 802.15.4 Extended Address.
|
||||
*
|
||||
* @param[in] aIpAddress A reference to the IPv6 address.
|
||||
*
|
||||
*/
|
||||
void Set(const Ip6::Address &aIpAddress);
|
||||
|
||||
enum
|
||||
{
|
||||
kLength = 8, ///< Size of IEEE 802.15.4 Extended Address in bytes.
|
||||
};
|
||||
uint8_t mBytes[kLength]; ///< The IEEE 802.15.4 Extended Address bytes.
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents an IEEE 802.15.4 Short or Extended Address.
|
||||
*
|
||||
*/
|
||||
struct Address
|
||||
{
|
||||
uint8_t mLength; ///< Length of address in bytes.
|
||||
union
|
||||
{
|
||||
ShortAddress mShortAddress; ///< The IEEE 802.15.4 Short Address.
|
||||
ExtAddress mExtAddress; ///< The IEEE 802.15.4 Extended Address.
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements IEEE 802.15.4 MAC frame generation and parsing.
|
||||
*
|
||||
*/
|
||||
class Frame: public RadioPacket
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kMTU = 127,
|
||||
kFcfSize = sizeof(uint16_t),
|
||||
kDsnSize = sizeof(uint8_t),
|
||||
kSecurityControlSize = sizeof(uint8_t),
|
||||
kFrameCounterSize = sizeof(uint32_t),
|
||||
kCommandIdSize = sizeof(uint8_t),
|
||||
kFcsSize = sizeof(uint16_t),
|
||||
|
||||
kFcfFrameBeacon = 0 << 0,
|
||||
kFcfFrameData = 1 << 0,
|
||||
kFcfFrameAck = 2 << 0,
|
||||
kFcfFrameMacCmd = 3 << 0,
|
||||
kFcfFrameTypeMask = 7 << 0,
|
||||
kFcfSecurityEnabled = 1 << 3,
|
||||
kFcfFramePending = 1 << 4,
|
||||
kFcfAckRequest = 1 << 5,
|
||||
kFcfPanidCompression = 1 << 6,
|
||||
kFcfDstAddrNone = 0 << 10,
|
||||
kFcfDstAddrShort = 2 << 10,
|
||||
kFcfDstAddrExt = 3 << 10,
|
||||
kFcfDstAddrMask = 3 << 10,
|
||||
kFcfFrameVersion2006 = 1 << 12,
|
||||
kFcfFrameVersionMask = 3 << 13,
|
||||
kFcfSrcAddrNone = 0 << 14,
|
||||
kFcfSrcAddrShort = 2 << 14,
|
||||
kFcfSrcAddrExt = 3 << 14,
|
||||
kFcfSrcAddrMask = 3 << 14,
|
||||
|
||||
kSecNone = 0 << 0,
|
||||
kSecMic32 = 1 << 0,
|
||||
kSecMic64 = 2 << 0,
|
||||
kSecMic128 = 3 << 0,
|
||||
kSecEnc = 4 << 0,
|
||||
kSecEncMic32 = 5 << 0,
|
||||
kSecEncMic64 = 6 << 0,
|
||||
kSecEncMic128 = 7 << 0,
|
||||
kSecLevelMask = 7 << 0,
|
||||
|
||||
kMic0Size = 0,
|
||||
kMic32Size = 32 / CHAR_BIT,
|
||||
kMic64Size = 64 / CHAR_BIT,
|
||||
kMic128Size = 128 / CHAR_BIT,
|
||||
kMaxMicSize = kMic128Size,
|
||||
|
||||
kKeyIdMode0 = 0 << 3,
|
||||
kKeyIdMode1 = 1 << 3,
|
||||
kKeyIdMode2 = 2 << 3,
|
||||
kKeyIdMode3 = 3 << 3,
|
||||
kKeyIdModeMask = 3 << 3,
|
||||
|
||||
kMacCmdAssociationRequest = 1,
|
||||
kMacCmdAssociationResponse = 2,
|
||||
kMacCmdDisassociationNotification = 3,
|
||||
kMacCmdDataRequest = 4,
|
||||
kMacCmdPanidConflictNotification = 5,
|
||||
kMacCmdOrphanNotification = 6,
|
||||
kMacCmdBeaconRequest = 7,
|
||||
kMacCmdCoordinatorRealignment = 8,
|
||||
kMacCmdGtsRequest = 9,
|
||||
};
|
||||
|
||||
/**
|
||||
* This method initializes the MAC header.
|
||||
*
|
||||
* @param[in] aFcf The Frame Control field.
|
||||
* @param[in] aSecCtl The Security Control field.
|
||||
*
|
||||
* @retval kThreadError_None Successfully initialized the MAC header.
|
||||
* @retval kThreadError_InvalidArgs Invalid values for @p aFcf and/or @p aSecCtl.
|
||||
*
|
||||
*/
|
||||
ThreadError InitMacHeader(uint16_t aFcf, uint8_t aSecCtl);
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Frame Type.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 Frame Type.
|
||||
*
|
||||
*/
|
||||
uint8_t GetType(void);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not security is enabled.
|
||||
*
|
||||
* @retval TRUE If security is enabled.
|
||||
* @retval FALSE If security is not enabled.
|
||||
*
|
||||
*/
|
||||
bool GetSecurityEnabled(void);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the Frame Pending bit is set.
|
||||
*
|
||||
* @retval TRUE If the Frame Pending bit is set.
|
||||
* @retval FALSE If the Frame Pending bit is not set.
|
||||
*
|
||||
*/
|
||||
bool GetFramePending(void);
|
||||
|
||||
/**
|
||||
* This method sets the Frame Pending bit.
|
||||
*
|
||||
* @param[in] aFramePending The Frame Pending bit.
|
||||
*
|
||||
*/
|
||||
void SetFramePending(bool aFramePending);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the Ack Request bit is set.
|
||||
*
|
||||
* @retval TRUE If the Ack Request bit is set.
|
||||
* @retval FALSE If the Ack Request bit is not set.
|
||||
*
|
||||
*/
|
||||
bool GetAckRequest(void);
|
||||
|
||||
/**
|
||||
* This method sets the Ack Request bit.
|
||||
*
|
||||
* @param[in] aAckRequest The Ack Request bit.
|
||||
*
|
||||
*/
|
||||
void SetAckRequest(bool aAckRequest);
|
||||
|
||||
/**
|
||||
* This method returns the Sequence Number value.
|
||||
*
|
||||
* @returns The Sequence Number value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetSequence(void);
|
||||
|
||||
/**
|
||||
* This method sets the Sequence Number value.
|
||||
*
|
||||
* @param[in] aSequence The Sequence Number value.
|
||||
*
|
||||
*/
|
||||
void SetSequence(uint8_t aSequence);
|
||||
|
||||
/**
|
||||
* This method gets the Destination PAN Identifier.
|
||||
*
|
||||
* @param[out] aPanId The Destination PAN Identifier.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the Destination PAN Identifier.
|
||||
*
|
||||
*/
|
||||
ThreadError GetDstPanId(PanId &aPanId);
|
||||
|
||||
/**
|
||||
* This method sets the Destination PAN Identifier.
|
||||
*
|
||||
* @param[in] aPanId The Destination PAN Identifier.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Destination PAN Identifier.
|
||||
*
|
||||
*/
|
||||
ThreadError SetDstPanId(PanId aPanId);
|
||||
|
||||
/**
|
||||
* This method gets the Destination Address.
|
||||
*
|
||||
* @param[out] aAddress The Destination Address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the Destination Address.
|
||||
*
|
||||
*/
|
||||
ThreadError GetDstAddr(Address &aAddress);
|
||||
|
||||
/**
|
||||
* This method sets the Destination Address.
|
||||
*
|
||||
* @param[in] aShortAddress The Destination Address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Destination Address.
|
||||
*
|
||||
*/
|
||||
ThreadError SetDstAddr(ShortAddress aShortAddress);
|
||||
|
||||
/**
|
||||
* This method sets the Destination Address.
|
||||
*
|
||||
* @param[in] aExtAddress The Destination Address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Destination Address.
|
||||
*
|
||||
*/
|
||||
ThreadError SetDstAddr(const ExtAddress &aExtAddress);
|
||||
|
||||
/**
|
||||
* This method gets the Source PAN Identifier.
|
||||
*
|
||||
* @param[out] aPanId The Source PAN Identifier.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the Source PAN Identifier.
|
||||
*
|
||||
*/
|
||||
ThreadError GetSrcPanId(PanId &aPanId);
|
||||
|
||||
/**
|
||||
* This method sets the Source PAN Identifier.
|
||||
*
|
||||
* @param[in] aPanId The Source PAN Identifier.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Source PAN Identifier.
|
||||
*
|
||||
*/
|
||||
ThreadError SetSrcPanId(PanId aPanId);
|
||||
|
||||
/**
|
||||
* This method gets the Source Address.
|
||||
*
|
||||
* @param[out] aAddress The Source Address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the Source Address.
|
||||
*
|
||||
*/
|
||||
ThreadError GetSrcAddr(Address &aAddress);
|
||||
|
||||
/**
|
||||
* This method gets the Source Address.
|
||||
*
|
||||
* @param[in] aShortAddress The Source Address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Source Address.
|
||||
*
|
||||
*/
|
||||
ThreadError SetSrcAddr(ShortAddress aShortAddress);
|
||||
|
||||
/**
|
||||
* This method gets the Source Address.
|
||||
*
|
||||
* @param[in] aExtAddress The Source Address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Source Address.
|
||||
*
|
||||
*/
|
||||
ThreadError SetSrcAddr(const ExtAddress &aExtAddress);
|
||||
|
||||
/**
|
||||
* This method gets the Security Level Identifier.
|
||||
*
|
||||
* @param[out] aSecurityLevel The Security Level Identifier.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the Security Level Identifier.
|
||||
*
|
||||
*/
|
||||
ThreadError GetSecurityLevel(uint8_t &aSecurityLevel);
|
||||
|
||||
/**
|
||||
* This method gets the Frame Counter.
|
||||
*
|
||||
* @param[out] aFrameCounter The Frame Counter.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the Frame Counter.
|
||||
*
|
||||
*/
|
||||
ThreadError GetFrameCounter(uint32_t &aFrameCounter);
|
||||
|
||||
/**
|
||||
* This method sets the Frame Counter.
|
||||
*
|
||||
* @param[in] aFrameCounter The Frame Counter.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Frame Counter.
|
||||
*
|
||||
*/
|
||||
ThreadError SetFrameCounter(uint32_t aFrameCounter);
|
||||
|
||||
/**
|
||||
* This method gets the Key Identifier.
|
||||
*
|
||||
* @param[out] aKeyId The Key Identifier.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the Key Identifier.
|
||||
*
|
||||
*/
|
||||
ThreadError GetKeyId(uint8_t &aKeyId);
|
||||
|
||||
/**
|
||||
* This method sets the Key Identifier.
|
||||
*
|
||||
* @param[in] aKeyId The Key Identifier.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Key Identifier.
|
||||
*
|
||||
*/
|
||||
ThreadError SetKeyId(uint8_t aKeyId);
|
||||
|
||||
/**
|
||||
* This method gets the Command ID.
|
||||
*
|
||||
* @param[out] aCommandId The Command ID.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the Command ID.
|
||||
*
|
||||
*/
|
||||
ThreadError GetCommandId(uint8_t &aCommandId);
|
||||
|
||||
/**
|
||||
* This method sets the Command ID.
|
||||
*
|
||||
* @param[in] aCommandId The Command ID.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Command ID.
|
||||
*
|
||||
*/
|
||||
ThreadError SetCommandId(uint8_t aCommandId);
|
||||
|
||||
/**
|
||||
* This method returns the MAC Frame Length.
|
||||
*
|
||||
* @returns The MAC Frame Length.
|
||||
*
|
||||
*/
|
||||
uint8_t GetLength(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the MAC Frame Length.
|
||||
*
|
||||
* @param[in] aLength The MAC Frame Length.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the MAC Frame Length.
|
||||
* @retval kThreadError_InvalidArgs The @p aLength value was invalid.
|
||||
*
|
||||
*/
|
||||
ThreadError SetLength(uint8_t aLength);
|
||||
|
||||
/**
|
||||
* This method returns the MAC header size.
|
||||
*
|
||||
* @returns The MAC header size.
|
||||
*
|
||||
*/
|
||||
uint8_t GetHeaderLength(void);
|
||||
|
||||
/**
|
||||
* This method returns the MAC footer size.
|
||||
*
|
||||
* @returns The MAC footer size.
|
||||
*
|
||||
*/
|
||||
uint8_t GetFooterLength(void);
|
||||
|
||||
/**
|
||||
* This method returns the current MAC Payload length.
|
||||
*
|
||||
* @returns The current MAC Payload length.
|
||||
*
|
||||
*/
|
||||
uint8_t GetPayloadLength(void);
|
||||
|
||||
/**
|
||||
* This method returns the maximum MAC Payload length for the given MAC header and footer.
|
||||
*
|
||||
* @returns The maximum MAC Payload length for the given MAC header and footer.
|
||||
*
|
||||
*/
|
||||
uint8_t GetMaxPayloadLength(void);
|
||||
|
||||
/**
|
||||
* This method sets the MAC Payload length.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the MAC Payload length.
|
||||
* @retval kThreadError_InvalidArgs The @p aLength value was invalid.
|
||||
*
|
||||
*/
|
||||
ThreadError SetPayloadLength(uint8_t aLength);
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 channel used for transmission or reception.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 channel used for transmission or reception.
|
||||
*
|
||||
*/
|
||||
uint8_t GetChannel(void) const { return mChannel; }
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 channel used for transmission or reception.
|
||||
*
|
||||
* @param[in] aChannel The IEEE 802.15.4 channel used for transmission or reception.
|
||||
*
|
||||
*/
|
||||
void SetChannel(uint8_t aChannel) { mChannel = aChannel; }
|
||||
|
||||
/**
|
||||
* This method returns the transmit/receive power in dBm used for transmission or reception.
|
||||
*
|
||||
* @returns The transmit/receive power in dBm used for transmission or reception.
|
||||
*
|
||||
*/
|
||||
int8_t GetPower(void) const { return mPower; }
|
||||
|
||||
/**
|
||||
* This method sets the transmit/receive power in dBm used for transmission or reception.
|
||||
*
|
||||
* @param[in] aPower The transmit/receive power in dBm used for transmission or reception.
|
||||
*
|
||||
*/
|
||||
void SetPower(int8_t aPower) { mPower = aPower; }
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 PSDU length.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 PSDU length.
|
||||
*
|
||||
*/
|
||||
uint8_t GetPsduLength(void) const { return mLength; }
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 PSDU length.
|
||||
*
|
||||
* @param[in] aLength The IEEE 802.15.4 PSDU length.
|
||||
*
|
||||
*/
|
||||
void SetPsduLength(uint8_t aLength) { mLength = aLength; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the PSDU.
|
||||
*
|
||||
* @returns A pointer to the PSDU.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetPsdu(void) { return mPsdu; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the MAC Header.
|
||||
*
|
||||
* @returns A pointer to the MAC Header.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetHeader(void);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the MAC Payload.
|
||||
*
|
||||
* @returns A pointer to the MAC Payload.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetPayload(void);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the MAC Footer.
|
||||
*
|
||||
* @returns A pointer to the MAC Footer.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetFooter(void);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kKeyIdLengthMode0 = 0, ///< Mode 0 Key ID Length in bytes (IEEE 802.15.4-2006)
|
||||
kKeyIdLengthMode1 = 1, ///< Mode 1 Key ID Length in bytes (IEEE 802.15.4-2006)
|
||||
kKeyIdLengthMode2 = 5, ///< Mode 2 Key ID Length in bytes (IEEE 802.15.4-2006)
|
||||
kKeyIdLengthMode3 = 9, ///< Mode 3 Key ID Length in bytes (IEEE 802.15.4-2006)
|
||||
};
|
||||
|
||||
uint8_t *FindSequence(void);
|
||||
uint8_t *FindDstPanId(void);
|
||||
uint8_t *FindDstAddr(void);
|
||||
uint8_t *FindSrcPanId(void);
|
||||
uint8_t *FindSrcAddr(void);
|
||||
uint8_t *FindSecurityHeader(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Mac
|
||||
} // namespace Thread
|
||||
|
||||
#endif // MAC_FRAME_HPP_
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements whitelist IEEE 802.15.4 frame filtering based on MAC address.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <mac/mac_whitelist.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Mac {
|
||||
|
||||
Whitelist::Whitelist(void)
|
||||
{
|
||||
mEnabled = false;
|
||||
|
||||
for (int i = 0; i < kMaxEntries; i++)
|
||||
{
|
||||
mWhitelist[i].mValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Whitelist::Enable(void)
|
||||
{
|
||||
mEnabled = true;
|
||||
}
|
||||
|
||||
void Whitelist::Disable(void)
|
||||
{
|
||||
mEnabled = false;
|
||||
}
|
||||
|
||||
bool Whitelist::IsEnabled(void) const
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
int Whitelist::GetMaxEntries(void) const
|
||||
{
|
||||
return kMaxEntries;
|
||||
}
|
||||
|
||||
const Whitelist::Entry *Whitelist::GetEntries(void) const
|
||||
{
|
||||
return mWhitelist;
|
||||
}
|
||||
|
||||
Whitelist::Entry *Whitelist::Add(const ExtAddress &address)
|
||||
{
|
||||
Entry *rval;
|
||||
|
||||
VerifyOrExit((rval = Find(address)) == NULL, ;);
|
||||
|
||||
for (int i = 0; i < kMaxEntries; i++)
|
||||
{
|
||||
if (mWhitelist[i].mValid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&mWhitelist[i], &address, sizeof(mWhitelist[i]));
|
||||
mWhitelist[i].mValid = true;
|
||||
mWhitelist[i].mConstantRssi = false;
|
||||
ExitNow(rval = &mWhitelist[i]);
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
void Whitelist::Clear(void)
|
||||
{
|
||||
for (int i = 0; i < kMaxEntries; i++)
|
||||
{
|
||||
mWhitelist[i].mValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Whitelist::Remove(const ExtAddress &address)
|
||||
{
|
||||
Entry *entry;
|
||||
|
||||
VerifyOrExit((entry = Find(address)) != NULL, ;);
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
Whitelist::Entry *Whitelist::Find(const ExtAddress &address)
|
||||
{
|
||||
Entry *rval = NULL;
|
||||
|
||||
for (int i = 0; i < kMaxEntries; i++)
|
||||
{
|
||||
if (!mWhitelist[i].mValid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(&mWhitelist[i].mExtAddress, &address, sizeof(mWhitelist[i].mExtAddress)) == 0)
|
||||
{
|
||||
ExitNow(rval = &mWhitelist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
void Whitelist::ClearConstantRssi(Entry &aEntry)
|
||||
{
|
||||
aEntry.mConstantRssi = false;
|
||||
}
|
||||
|
||||
ThreadError Whitelist::GetConstantRssi(Entry &aEntry, int8_t &rssi) const
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(aEntry.mValid && aEntry.mConstantRssi, error = kThreadError_Error);
|
||||
rssi = aEntry.mRssi;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Whitelist::SetConstantRssi(Entry &aEntry, int8_t aRssi)
|
||||
{
|
||||
aEntry.mConstantRssi = true;
|
||||
aEntry.mRssi = aRssi;
|
||||
}
|
||||
|
||||
} // namespace Mac
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for IEEE 802.15.4 frame filtering based on MAC address.
|
||||
*/
|
||||
|
||||
#ifndef MAC_WHITELIST_HPP_
|
||||
#define MAC_WHITELIST_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <mac/mac_frame.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Mac {
|
||||
|
||||
/**
|
||||
* @addtogroup core-mac
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements whitelist filtering on IEEE 802.15.4 frames.
|
||||
*
|
||||
*/
|
||||
class Whitelist
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kMaxEntries = 32,
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents a whitelist entry.
|
||||
*
|
||||
*/
|
||||
struct Entry
|
||||
{
|
||||
ExtAddress mExtAddress; ///< The IEEE 802.15.4 Extended Address.
|
||||
int8_t mRssi; ///< The constant RSSI value.
|
||||
bool mValid : 1; ///< TRUE if the entry is valid, FALSE otherwise.
|
||||
bool mConstantRssi : 1; ///< TRUE if the constant RSSI value is used, FALSE otherwise.
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes the whitelist filter.
|
||||
*
|
||||
*/
|
||||
Whitelist(void);
|
||||
|
||||
/**
|
||||
* This method enables the whitelist filter.
|
||||
*
|
||||
*/
|
||||
void Enable(void);
|
||||
|
||||
/**
|
||||
* This method disables the whitelist filter.
|
||||
*
|
||||
*/
|
||||
void Disable(void);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the whitelist filter is enabled.
|
||||
*
|
||||
* @retval TRUE If the whitelist filter is enabled.
|
||||
* @retval FALSE If the whitelist filter is disabled.
|
||||
*
|
||||
*/
|
||||
bool IsEnabled(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the maximum number of whitelist entries.
|
||||
*
|
||||
* @returns The maximum number of whitelist entries.
|
||||
*
|
||||
*/
|
||||
int GetMaxEntries(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the whitelist entries.
|
||||
*
|
||||
* @returns The whitelist entries.
|
||||
*
|
||||
*/
|
||||
const Entry *GetEntries(void) const;
|
||||
|
||||
/**
|
||||
* This method adds an Extended Address to the whitelist filter.
|
||||
*
|
||||
* @param[in] aAddress A reference to the Extended Address.
|
||||
*
|
||||
* @returns A pointer to the whitelist entry or NULL if there are no available entries.
|
||||
*
|
||||
*/
|
||||
Entry *Add(const ExtAddress &aAddress);
|
||||
|
||||
/**
|
||||
* This method removes an Extended Address to the whitelist filter.
|
||||
*
|
||||
* @param[in] aAddress A reference to the Extended Address.
|
||||
*
|
||||
*/
|
||||
void Remove(const ExtAddress &aAddress);
|
||||
|
||||
/**
|
||||
* This method removes all entries from the whitelist filter.
|
||||
*
|
||||
*/
|
||||
void Clear(void);
|
||||
|
||||
/**
|
||||
* This method finds a whitelist entry.
|
||||
*
|
||||
* @param[in] aAddress A reference to the Extended Address.
|
||||
*
|
||||
* @returns A pointer to the whitelist entry or NULL if the entry could not be found.
|
||||
*
|
||||
*/
|
||||
Entry *Find(const ExtAddress &aAddress);
|
||||
|
||||
/**
|
||||
* This method clears the constant RSSI value and uses the measured value provided by the radio instead.
|
||||
*
|
||||
* @param[in] aEntry A reference to the whitelist entry.
|
||||
*
|
||||
*/
|
||||
void ClearConstantRssi(Entry &aEntry);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the constant RSSI is set.
|
||||
*
|
||||
* @param[in] aEntry A reference to the whitelist entry.
|
||||
* @param[out] aRssi A reference to the RSSI variable.
|
||||
*
|
||||
* @retval kThreadError_None A constant RSSI is set and written to @p aRssi.
|
||||
* @retval kThreadError_InvalidArg A constnat RSSI was not set.
|
||||
*
|
||||
*/
|
||||
ThreadError GetConstantRssi(Entry &aEntry, int8_t &aRssi) const;
|
||||
|
||||
/**
|
||||
* This method sets a constant RSSI value for all received messages matching @p aEntry.
|
||||
*
|
||||
* @param[in] aEntry A reference to the whitelist entry.
|
||||
* @param[in] aRssi An RSSI value in dBm.
|
||||
*
|
||||
*/
|
||||
void SetConstantRssi(Entry &aEntry, int8_t aRssi);
|
||||
|
||||
private:
|
||||
Entry mWhitelist[kMaxEntries];
|
||||
|
||||
bool mEnabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Mac
|
||||
} // namespace Thread
|
||||
|
||||
#endif // MAC_WHITELIST_HPP_
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements ICMPv6.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <net/icmp6.hpp>
|
||||
#include <net/ip6.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
uint16_t IcmpEcho::sNextId = 1;
|
||||
IcmpEcho *IcmpEcho::sEchoClients = NULL;
|
||||
IcmpHandler *IcmpHandler::sHandlers = NULL;
|
||||
|
||||
IcmpEcho::IcmpEcho(EchoReplyHandler aHandler, void *aContext)
|
||||
{
|
||||
mHandler = aHandler;
|
||||
mContext = aContext;
|
||||
mId = sNextId++;
|
||||
mSeq = 0;
|
||||
mNext = sEchoClients;
|
||||
sEchoClients = this;
|
||||
}
|
||||
|
||||
ThreadError IcmpEcho::SendEchoRequest(const SockAddr &aDestination,
|
||||
const void *aPayload, uint16_t aPayloadLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
MessageInfo messageInfo;
|
||||
Message *message;
|
||||
IcmpHeader icmp6Header;
|
||||
|
||||
VerifyOrExit((message = Ip6::NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
SuccessOrExit(error = message->SetLength(sizeof(icmp6Header) + aPayloadLength));
|
||||
|
||||
message->Write(sizeof(icmp6Header), aPayloadLength, aPayload);
|
||||
|
||||
icmp6Header.Init();
|
||||
icmp6Header.SetType(IcmpHeader::kTypeEchoRequest);
|
||||
icmp6Header.SetId(mId);
|
||||
icmp6Header.SetSequence(mSeq++);
|
||||
message->Write(0, sizeof(icmp6Header), &icmp6Header);
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.GetPeerAddr() = aDestination.GetAddress();
|
||||
messageInfo.mInterfaceId = aDestination.mScopeId;
|
||||
|
||||
SuccessOrExit(error = Ip6::SendDatagram(*message, messageInfo, kProtoIcmp6));
|
||||
otLogInfoIcmp("Sent echo request\n");
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Icmp::RegisterCallbacks(IcmpHandler &aHandler)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
for (IcmpHandler *cur = IcmpHandler::sHandlers; cur; cur = cur->mNext)
|
||||
{
|
||||
if (cur == &aHandler)
|
||||
{
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
}
|
||||
}
|
||||
|
||||
aHandler.mNext = IcmpHandler::sHandlers;
|
||||
IcmpHandler::sHandlers = &aHandler;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Icmp::SendError(const Address &aDestination, IcmpHeader::Type aType, IcmpHeader::Code aCode,
|
||||
const Header &aHeader)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
MessageInfo messageInfo;
|
||||
Message *message;
|
||||
IcmpHeader icmp6Header;
|
||||
|
||||
VerifyOrExit((message = Ip6::NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
SuccessOrExit(error = message->SetLength(sizeof(icmp6Header) + sizeof(aHeader)));
|
||||
|
||||
message->Write(sizeof(icmp6Header), sizeof(aHeader), &aHeader);
|
||||
|
||||
icmp6Header.Init();
|
||||
icmp6Header.SetType(aType);
|
||||
icmp6Header.SetCode(aCode);
|
||||
message->Write(0, sizeof(icmp6Header), &icmp6Header);
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.mPeerAddr = aDestination;
|
||||
|
||||
SuccessOrExit(error = Ip6::SendDatagram(*message, messageInfo, kProtoIcmp6));
|
||||
|
||||
otLogInfoIcmp("Sent ICMPv6 Error\n");
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Icmp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint16_t payloadLength;
|
||||
IcmpHeader icmp6Header;
|
||||
uint16_t checksum;
|
||||
|
||||
payloadLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
|
||||
// check length
|
||||
VerifyOrExit(payloadLength >= IcmpHeader::GetDataOffset(), error = kThreadError_Drop);
|
||||
aMessage.Read(aMessage.GetOffset(), sizeof(icmp6Header), &icmp6Header);
|
||||
|
||||
// verify checksum
|
||||
checksum = Ip6::ComputePseudoheaderChecksum(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(),
|
||||
payloadLength, kProtoIcmp6);
|
||||
checksum = aMessage.UpdateChecksum(checksum, aMessage.GetOffset(), payloadLength);
|
||||
VerifyOrExit(checksum == 0xffff, ;);
|
||||
|
||||
switch (icmp6Header.GetType())
|
||||
{
|
||||
case IcmpHeader::kTypeEchoRequest:
|
||||
return HandleEchoRequest(aMessage, aMessageInfo);
|
||||
|
||||
case IcmpHeader::kTypeEchoReply:
|
||||
return HandleEchoReply(aMessage, aMessageInfo, icmp6Header);
|
||||
|
||||
case IcmpHeader::kTypeDstUnreach:
|
||||
return HandleDstUnreach(aMessage, aMessageInfo, icmp6Header);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Icmp::HandleDstUnreach(Message &aMessage, const MessageInfo &aMessageInfo,
|
||||
const IcmpHeader &aIcmpheader)
|
||||
{
|
||||
aMessage.MoveOffset(sizeof(aIcmpheader));
|
||||
|
||||
for (IcmpHandler *handler = IcmpHandler::sHandlers; handler; handler = handler->mNext)
|
||||
{
|
||||
handler->HandleDstUnreach(aMessage, aMessageInfo, aIcmpheader);
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
IcmpHeader icmp6Header;
|
||||
Message *replyMessage;
|
||||
MessageInfo replyMessageInfo;
|
||||
uint16_t payloadLength;
|
||||
|
||||
payloadLength = aRequestMessage.GetLength() - aRequestMessage.GetOffset() - IcmpHeader::GetDataOffset();
|
||||
|
||||
otLogInfoIcmp("Received Echo Request\n");
|
||||
|
||||
icmp6Header.Init();
|
||||
icmp6Header.SetType(IcmpHeader::kTypeEchoReply);
|
||||
|
||||
VerifyOrExit((replyMessage = Ip6::NewMessage(0)) != NULL, otLogDebgIcmp("icmp fail\n"));
|
||||
SuccessOrExit(replyMessage->SetLength(IcmpHeader::GetDataOffset() + payloadLength));
|
||||
|
||||
replyMessage->Write(0, IcmpHeader::GetDataOffset(), &icmp6Header);
|
||||
aRequestMessage.CopyTo(aRequestMessage.GetOffset() + IcmpHeader::GetDataOffset(),
|
||||
IcmpHeader::GetDataOffset(), payloadLength, *replyMessage);
|
||||
|
||||
memset(&replyMessageInfo, 0, sizeof(replyMessageInfo));
|
||||
replyMessageInfo.GetPeerAddr() = aMessageInfo.GetPeerAddr();
|
||||
|
||||
if (!aMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
replyMessageInfo.GetSockAddr() = aMessageInfo.GetSockAddr();
|
||||
}
|
||||
|
||||
replyMessageInfo.mInterfaceId = aMessageInfo.mInterfaceId;
|
||||
|
||||
SuccessOrExit(error = Ip6::SendDatagram(*replyMessage, replyMessageInfo, kProtoIcmp6));
|
||||
|
||||
otLogInfoIcmp("Sent Echo Reply\n");
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Icmp::HandleEchoReply(Message &aMessage, const MessageInfo &aMessageInfo,
|
||||
const IcmpHeader &aIcmpheader)
|
||||
{
|
||||
uint16_t id = aIcmpheader.GetId();
|
||||
|
||||
for (IcmpEcho *client = IcmpEcho::sEchoClients; client; client = client->mNext)
|
||||
{
|
||||
if (client->mId == id)
|
||||
{
|
||||
client->HandleEchoReply(aMessage, aMessageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Icmp::UpdateChecksum(Message &aMessage, uint16_t aChecksum)
|
||||
{
|
||||
aChecksum = aMessage.UpdateChecksum(aChecksum, aMessage.GetOffset(),
|
||||
aMessage.GetLength() - aMessage.GetOffset());
|
||||
|
||||
if (aChecksum != 0xffff)
|
||||
{
|
||||
aChecksum = ~aChecksum;
|
||||
}
|
||||
|
||||
aChecksum = HostSwap16(aChecksum);
|
||||
aMessage.Write(aMessage.GetOffset() + IcmpHeader::GetChecksumOffset(), sizeof(aChecksum), &aChecksum);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for ICMPv6.
|
||||
*/
|
||||
|
||||
#ifndef ICMP6_HPP_
|
||||
#define ICMP6_HPP_
|
||||
|
||||
#include <common/encoding.hpp>
|
||||
#include <net/ip6.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
/**
|
||||
* @addtogroup core-ip6-icmp6
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for ICMPv6.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
kIcmp6DataSize = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents an ICMPv6 header.
|
||||
*
|
||||
*/
|
||||
struct IcmpHeaderPoD
|
||||
{
|
||||
uint8_t mType; ///< Type
|
||||
uint8_t mCode; ///< Code
|
||||
uint16_t mChecksum; ///< Checksum
|
||||
union
|
||||
{
|
||||
uint8_t m8[kIcmp6DataSize / sizeof(uint8_t)];
|
||||
uint16_t m16[kIcmp6DataSize / sizeof(uint16_t)];
|
||||
uint32_t m32[kIcmp6DataSize / sizeof(uint32_t)];
|
||||
} mData; ///< Message-specific data
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements ICMPv6 header generation and parsing.
|
||||
*
|
||||
*/
|
||||
class IcmpHeader: private IcmpHeaderPoD
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the ICMPv6 header to all zeros.
|
||||
*
|
||||
*/
|
||||
void Init() { mType = 0; mCode = 0; mChecksum = 0; mData.m32[0] = 0; }
|
||||
|
||||
/**
|
||||
* ICMPv6 Message Types
|
||||
*
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
kTypeDstUnreach = 0, ///< Destination Unreachable
|
||||
kTypeEchoRequest = 128, ///< Echo Request
|
||||
kTypeEchoReply = 129, ///< Echo Reply
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns the ICMPv6 message type.
|
||||
*
|
||||
* @returns The ICMPv6 message type.
|
||||
*
|
||||
*/
|
||||
Type GetType() const { return static_cast<Type>(mType); }
|
||||
|
||||
/**
|
||||
* This method sets the ICMPv6 message type.
|
||||
*
|
||||
* @param[in] aType The ICMPv6 message type.
|
||||
*
|
||||
*/
|
||||
void SetType(Type aType) { mType = static_cast<uint8_t>(aType); }
|
||||
|
||||
/**
|
||||
* ICMPv6 Message Codes
|
||||
*
|
||||
*/
|
||||
enum Code
|
||||
{
|
||||
kCodeDstUnreachNoRoute = 0, ///< Destination Unreachable No Route
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns the ICMPv6 message code.
|
||||
*
|
||||
* @returns The ICMPv6 message code.
|
||||
*
|
||||
*/
|
||||
Code GetCode() const { return static_cast<Code>(mCode); }
|
||||
|
||||
/**
|
||||
* This method sets the ICMPv6 message code.
|
||||
*
|
||||
* @param[in] aCode The ICMPv6 message code.
|
||||
*/
|
||||
void SetCode(Code aCode) { mCode = static_cast<uint8_t>(aCode); }
|
||||
|
||||
/**
|
||||
* This method returns the ICMPv6 message checksum.
|
||||
*
|
||||
* @returns The ICMPv6 message checksum.
|
||||
*
|
||||
*/
|
||||
uint16_t GetChecksum() const { return HostSwap16(mChecksum); }
|
||||
|
||||
/**
|
||||
* This method sets the ICMPv6 message checksum.
|
||||
*
|
||||
* @param[in] aChecksum The ICMPv6 message checksum.
|
||||
*
|
||||
*/
|
||||
void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
|
||||
|
||||
/**
|
||||
* This method returns the ICMPv6 message ID for Echo Requests and Replies.
|
||||
*
|
||||
* @returns The ICMPv6 message ID.
|
||||
*
|
||||
*/
|
||||
uint16_t GetId() const { return HostSwap16(mData.m16[0]); }
|
||||
|
||||
/**
|
||||
* This method sets the ICMPv6 message ID for Echo Requests and Replies.
|
||||
*
|
||||
* @param[in] aId The ICMPv6 message ID.
|
||||
*
|
||||
*/
|
||||
void SetId(uint16_t aId) { mData.m16[0] = HostSwap16(aId); }
|
||||
|
||||
/**
|
||||
* This method returns the ICMPv6 message sequence for Echo Requests and Replies.
|
||||
*
|
||||
* @returns The ICMPv6 message sequence.
|
||||
*
|
||||
*/
|
||||
uint16_t GetSequence() const { return HostSwap16(mData.m16[1]); }
|
||||
|
||||
/**
|
||||
* This method sets the ICMPv6 message sequence for Echo Requests and Replies.
|
||||
*
|
||||
* @param[in] aSequence The ICMPv6 message sequence.
|
||||
*
|
||||
*/
|
||||
void SetSequence(uint16_t aSequence) { mData.m16[1] = HostSwap16(aSequence); }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset of the Checksum field in the ICMPv6 header.
|
||||
*
|
||||
* @returns The byte offset of the Checksum field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetChecksumOffset() { return offsetof(IcmpHeaderPoD, mChecksum); }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset of the ICMPv6 payload.
|
||||
*
|
||||
* @returns The Byte offset of the ICMPv6 payload.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetDataOffset() { return offsetof(IcmpHeaderPoD, mData); }
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements an ICMPv6 echo client.
|
||||
*
|
||||
*/
|
||||
class IcmpEcho
|
||||
{
|
||||
friend class Icmp;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when receiving an ICMPv6 Echo Reply in response to an Echo Request.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aMessage A reference to the received message.
|
||||
* @param[in] aMessageInfo A reference to message information associated with @p aMessage.
|
||||
*
|
||||
*/
|
||||
typedef void (*EchoReplyHandler)(void *aContext, Message &aMessage, const MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This constructor creates an ICMPv6 echo client.
|
||||
*
|
||||
* @param[in] aHandler A pointer to a function that is called when receiving an ICMPv6 Echo Reply.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
IcmpEcho(EchoReplyHandler aHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* This method sends an ICMPv6 Echo Request message.
|
||||
*
|
||||
* @param[in] aDestination The socket address of the destination.
|
||||
* @param[in] aPayload A pointer to the data payload to send.
|
||||
* @param[in] aPayloadLength The number of data payoad bytes.
|
||||
*
|
||||
* @retval kThreadError_None An ICMPv6 Echo Request message was enqueued.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers available to generate an ICMPv6 Echo Request message.
|
||||
*
|
||||
*/
|
||||
ThreadError SendEchoRequest(const SockAddr &aDestination, const void *aPayload, uint16_t aPayloadLength);
|
||||
|
||||
private:
|
||||
void HandleEchoReply(Message &message, const MessageInfo &messageInfo) {
|
||||
mHandler(mContext, message, messageInfo);
|
||||
}
|
||||
|
||||
EchoReplyHandler mHandler;
|
||||
void *mContext;
|
||||
uint16_t mId;
|
||||
uint16_t mSeq;
|
||||
IcmpEcho *mNext;
|
||||
|
||||
static uint16_t sNextId;
|
||||
static IcmpEcho *sEchoClients;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements ICMPv6 message handlers.
|
||||
*
|
||||
*/
|
||||
class IcmpHandler
|
||||
{
|
||||
friend class Icmp;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when receiving an ICMPv6 Destination Unreachable message.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aMessage A reference to the received message.
|
||||
* @param[in] aMessageInfo A reference to message information associated with @p aMessage.
|
||||
* @param[in] aIcmpHeader A reference to the receievd ICMPv6 header.
|
||||
*
|
||||
*/
|
||||
typedef void (*DstUnreachHandler)(void *aContext, Message &aMesage, const MessageInfo &aMessageInfo,
|
||||
const IcmpHeader &aIcmpHeader);
|
||||
|
||||
/**
|
||||
* This constructor creates an ICMPv6 message handler.
|
||||
*
|
||||
* @param[in] aDstUnreachHandler A pointer to the function that is called when receiving a Destination
|
||||
* Unreachable message.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
IcmpHandler(DstUnreachHandler aDstUnreachHandler, void *aContext) {
|
||||
mDstUnreachHandler = aDstUnreachHandler;
|
||||
mContext = aContext;
|
||||
}
|
||||
|
||||
private:
|
||||
void HandleDstUnreach(Message &message, const MessageInfo &messageInfo, const IcmpHeader &icmp6Header) {
|
||||
mDstUnreachHandler(mContext, message, messageInfo, icmp6Header);
|
||||
}
|
||||
|
||||
DstUnreachHandler mDstUnreachHandler;
|
||||
void *mContext;
|
||||
IcmpHandler *mNext;
|
||||
|
||||
static IcmpHandler *sHandlers;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements ICMPv6.
|
||||
*
|
||||
*/
|
||||
class Icmp
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This static method registers ICMPv6 handlers.
|
||||
*
|
||||
* @param[in] aHandler A reference to the ICMPv6 handler.
|
||||
*
|
||||
* @retval kThreadError_None Successfully registered the ICMPv6 handler.
|
||||
* @retval kThreadError_Busy The ICMPv6 handler is already registered.
|
||||
*
|
||||
*/
|
||||
static ThreadError RegisterCallbacks(IcmpHandler &aHandler);
|
||||
|
||||
/**
|
||||
* This static method sends an ICMPv6 error message.
|
||||
*
|
||||
* @param[in] aDestination The IPv6 destination address.
|
||||
* @param[in] aType The ICMPv6 message type.
|
||||
* @param[in] aCode The ICMPv6 message code.
|
||||
* @param[in] aHeader The IPv6 header of the error-causing message.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the ICMPv6 error message.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers available.
|
||||
*
|
||||
*/
|
||||
static ThreadError SendError(const Address &aDestination, IcmpHeader::Type aType, IcmpHeader::Code aCode,
|
||||
const Header &aHeader);
|
||||
|
||||
/**
|
||||
* This static method handles an ICMPv6 message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the ICMPv6 mesasge.
|
||||
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
|
||||
*
|
||||
* @retval kThreadError_None Successfully processed the ICMPv6 message.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers available to generate the reply.
|
||||
* @retval kThreadError_Drop The ICMPv6 message was invalid and dropped.
|
||||
*
|
||||
*/
|
||||
static ThreadError HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This static method updates the ICMPv6 checksum.
|
||||
*
|
||||
* @param[in] aMessage A reference to the ICMPv6 message.
|
||||
* @param[in] aPseudoHeaderChecksum The pseudo-header checksum value.
|
||||
*
|
||||
* @retval kThreadError_None Successfully updated the ICMPv6 checksum.
|
||||
* @retval kThreadError_InvalidArgs The message was invalid.
|
||||
*
|
||||
*/
|
||||
static ThreadError UpdateChecksum(Message &aMessage, uint16_t aPseudoHeaderChecksum);
|
||||
|
||||
private:
|
||||
static ThreadError HandleDstUnreach(Message &aMessage, const MessageInfo &aMessageInfo,
|
||||
const IcmpHeader &aIcmpHeader);
|
||||
static ThreadError HandleEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo);
|
||||
static ThreadError HandleEchoReply(Message &aMessage, const MessageInfo &aMessageInfo,
|
||||
const IcmpHeader &aIcmpHeader);
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NET_ICMP6_HPP_
|
||||
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements IPv6 networking.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <net/icmp6.hpp>
|
||||
#include <net/ip6.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
#include <net/ip6_mpl.hpp>
|
||||
#include <net/ip6_routes.hpp>
|
||||
#include <net/netif.hpp>
|
||||
#include <net/udp6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
static Mpl sMpl;
|
||||
static Ip6::NcpReceivedDatagramHandler sNcpReceivedHandler = NULL;
|
||||
static void *sNcpReceivedHandlerContext = NULL;
|
||||
|
||||
static ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo);
|
||||
|
||||
Message *Ip6::NewMessage(uint16_t reserved)
|
||||
{
|
||||
return Message::New(Message::kTypeIp6,
|
||||
sizeof(Header) + sizeof(HopByHopHeader) + sizeof(OptionMpl) + reserved);
|
||||
}
|
||||
|
||||
uint16_t Ip6::UpdateChecksum(uint16_t checksum, uint16_t val)
|
||||
{
|
||||
uint16_t result = checksum + val;
|
||||
return result + (result < checksum);
|
||||
}
|
||||
|
||||
uint16_t Ip6::UpdateChecksum(uint16_t checksum, const void *buf, uint16_t len)
|
||||
{
|
||||
const uint8_t *bytes = reinterpret_cast<const uint8_t *>(buf);
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
checksum = Ip6::UpdateChecksum(checksum, (i & 1) ? bytes[i] : (static_cast<uint16_t>(bytes[i])) << 8);
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
uint16_t Ip6::UpdateChecksum(uint16_t checksum, const Address &address)
|
||||
{
|
||||
return Ip6::UpdateChecksum(checksum, address.m8, sizeof(address));
|
||||
}
|
||||
|
||||
uint16_t Ip6::ComputePseudoheaderChecksum(const Address &src, const Address &dst, uint16_t length, IpProto proto)
|
||||
{
|
||||
uint16_t checksum;
|
||||
|
||||
checksum = Ip6::UpdateChecksum(0, length);
|
||||
checksum = Ip6::UpdateChecksum(checksum, proto);
|
||||
checksum = UpdateChecksum(checksum, src);
|
||||
checksum = UpdateChecksum(checksum, dst);
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
void Ip6::SetNcpReceivedHandler(NcpReceivedDatagramHandler handler, void *context)
|
||||
{
|
||||
sNcpReceivedHandler = handler;
|
||||
sNcpReceivedHandlerContext = context;
|
||||
}
|
||||
|
||||
ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
HopByHopHeader hbhHeader;
|
||||
OptionMpl mplOption;
|
||||
|
||||
hbhHeader.SetNextHeader(nextHeader);
|
||||
hbhHeader.SetLength(0);
|
||||
sMpl.InitOption(mplOption, HostSwap16(header.GetSource().m16[7]));
|
||||
SuccessOrExit(error = message.Prepend(&mplOption, sizeof(mplOption)));
|
||||
SuccessOrExit(error = message.Prepend(&hbhHeader, sizeof(hbhHeader)));
|
||||
header.SetPayloadLength(sizeof(hbhHeader) + sizeof(mplOption) + payloadLength);
|
||||
header.SetNextHeader(kProtoHopOpts);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Ip6::SendDatagram(Message &message, MessageInfo &messageInfo, IpProto ipproto)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Header header;
|
||||
uint16_t payloadLength = message.GetLength();
|
||||
uint16_t checksum;
|
||||
const NetifUnicastAddress *source;
|
||||
|
||||
header.Init();
|
||||
header.SetPayloadLength(payloadLength);
|
||||
header.SetNextHeader(ipproto);
|
||||
header.SetHopLimit(messageInfo.mHopLimit ? messageInfo.mHopLimit : kDefaultHopLimit);
|
||||
|
||||
if (messageInfo.GetSockAddr().IsUnspecified())
|
||||
{
|
||||
VerifyOrExit((source = Netif::SelectSourceAddress(messageInfo)) != NULL, error = kThreadError_Error);
|
||||
header.SetSource(source->GetAddress());
|
||||
}
|
||||
else
|
||||
{
|
||||
header.SetSource(messageInfo.GetSockAddr());
|
||||
}
|
||||
|
||||
header.SetDestination(messageInfo.GetPeerAddr());
|
||||
|
||||
if (header.GetDestination().IsLinkLocal() || header.GetDestination().IsLinkLocalMulticast())
|
||||
{
|
||||
VerifyOrExit(messageInfo.mInterfaceId != 0, error = kThreadError_Drop);
|
||||
}
|
||||
|
||||
if (messageInfo.GetPeerAddr().IsRealmLocalMulticast())
|
||||
{
|
||||
SuccessOrExit(error = AddMplOption(message, header, ipproto, payloadLength));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = message.Prepend(&header, sizeof(header)));
|
||||
|
||||
// compute checksum
|
||||
checksum = ComputePseudoheaderChecksum(header.GetSource(), header.GetDestination(),
|
||||
payloadLength, ipproto);
|
||||
|
||||
switch (ipproto)
|
||||
{
|
||||
case kProtoUdp:
|
||||
SuccessOrExit(error = Udp::UpdateChecksum(message, checksum));
|
||||
break;
|
||||
|
||||
case kProtoIcmp6:
|
||||
SuccessOrExit(error = Icmp::UpdateChecksum(message, checksum));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None)
|
||||
{
|
||||
Message::Free(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = HandleDatagram(message, NULL, messageInfo.mInterfaceId, NULL, false);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError HandleOptions(Message &message)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
HopByHopHeader hbhHeader;
|
||||
OptionHeader optionHeader;
|
||||
uint16_t endOffset;
|
||||
|
||||
message.Read(message.GetOffset(), sizeof(hbhHeader), &hbhHeader);
|
||||
endOffset = message.GetOffset() + (hbhHeader.GetLength() + 1) * 8;
|
||||
|
||||
message.MoveOffset(sizeof(optionHeader));
|
||||
|
||||
while (message.GetOffset() < endOffset)
|
||||
{
|
||||
message.Read(message.GetOffset(), sizeof(optionHeader), &optionHeader);
|
||||
|
||||
switch (optionHeader.GetType())
|
||||
{
|
||||
case OptionMpl::kType:
|
||||
SuccessOrExit(error = sMpl.ProcessOption(message));
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (optionHeader.GetAction())
|
||||
{
|
||||
case OptionHeader::kActionSkip:
|
||||
break;
|
||||
|
||||
case OptionHeader::kActionDiscard:
|
||||
ExitNow(error = kThreadError_Drop);
|
||||
|
||||
case OptionHeader::kActionForceIcmp:
|
||||
// TODO: send icmp error
|
||||
ExitNow(error = kThreadError_Drop);
|
||||
|
||||
case OptionHeader::kActionIcmp:
|
||||
// TODO: send icmp error
|
||||
ExitNow(error = kThreadError_Drop);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
message.MoveOffset(sizeof(optionHeader) + optionHeader.GetLength());
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError HandleFragment(Message &message)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
FragmentHeader fragmentHeader;
|
||||
|
||||
message.Read(message.GetOffset(), sizeof(fragmentHeader), &fragmentHeader);
|
||||
|
||||
VerifyOrExit(fragmentHeader.GetOffset() == 0 && fragmentHeader.IsMoreFlagSet() == false,
|
||||
error = kThreadError_Drop);
|
||||
|
||||
message.MoveOffset(sizeof(fragmentHeader));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError HandleExtensionHeaders(Message &message, uint8_t &nextHeader, bool receive)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ExtensionHeader extensionHeader;
|
||||
|
||||
while (receive == true || nextHeader == kProtoHopOpts)
|
||||
{
|
||||
VerifyOrExit(message.GetOffset() <= message.GetLength(), error = kThreadError_Drop);
|
||||
|
||||
message.Read(message.GetOffset(), sizeof(extensionHeader), &extensionHeader);
|
||||
|
||||
switch (nextHeader)
|
||||
{
|
||||
case kProtoHopOpts:
|
||||
SuccessOrExit(error = HandleOptions(message));
|
||||
break;
|
||||
|
||||
case kProtoFragment:
|
||||
SuccessOrExit(error = HandleFragment(message));
|
||||
break;
|
||||
|
||||
case kProtoDstOpts:
|
||||
SuccessOrExit(error = HandleOptions(message));
|
||||
break;
|
||||
|
||||
case kProtoIp6:
|
||||
case kProtoRouting:
|
||||
case kProtoNone:
|
||||
ExitNow(error = kThreadError_Drop);
|
||||
|
||||
default:
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
nextHeader = extensionHeader.GetNextHeader();
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError HandlePayload(Message &message, MessageInfo &messageInfo, uint8_t ipproto)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
switch (ipproto)
|
||||
{
|
||||
case kProtoUdp:
|
||||
ExitNow(error = Udp::HandleMessage(message, messageInfo));
|
||||
|
||||
case kProtoIcmp6:
|
||||
ExitNow(error = Icmp::HandleMessage(message, messageInfo));
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, uint8_t interfaceId, const void *linkMessageInfo,
|
||||
bool fromNcpHost)
|
||||
{
|
||||
ThreadError error = kThreadError_Drop;
|
||||
MessageInfo messageInfo;
|
||||
Header header;
|
||||
uint16_t payloadLength;
|
||||
bool receive = false;
|
||||
bool forward = false;
|
||||
uint8_t nextHeader;
|
||||
uint8_t hopLimit;
|
||||
|
||||
#if 0
|
||||
uint8_t buf[1024];
|
||||
message.Read(0, sizeof(buf), buf);
|
||||
dump("handle datagram", buf, message.GetLength());
|
||||
#endif
|
||||
|
||||
// check message length
|
||||
VerifyOrExit(message.GetLength() >= sizeof(header), ;);
|
||||
message.Read(0, sizeof(header), &header);
|
||||
payloadLength = header.GetPayloadLength();
|
||||
|
||||
// check Version
|
||||
VerifyOrExit(header.IsVersion6(), ;);
|
||||
|
||||
// check Payload Length
|
||||
VerifyOrExit(sizeof(header) + payloadLength == message.GetLength() &&
|
||||
sizeof(header) + payloadLength <= Ip6::kMaxDatagramLength, ;);
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.GetPeerAddr() = header.GetSource();
|
||||
messageInfo.GetSockAddr() = header.GetDestination();
|
||||
messageInfo.mInterfaceId = interfaceId;
|
||||
messageInfo.mHopLimit = header.GetHopLimit();
|
||||
messageInfo.mLinkInfo = linkMessageInfo;
|
||||
|
||||
// determine destination of packet
|
||||
if (header.GetDestination().IsMulticast())
|
||||
{
|
||||
if (netif != NULL && netif->IsMulticastSubscribed(header.GetDestination()))
|
||||
{
|
||||
receive = true;
|
||||
}
|
||||
|
||||
if (header.GetDestination().GetScope() > Address::kLinkLocalScope)
|
||||
{
|
||||
forward = true;
|
||||
}
|
||||
else if (netif == NULL)
|
||||
{
|
||||
forward = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Netif::IsUnicastAddress(header.GetDestination()))
|
||||
{
|
||||
receive = true;
|
||||
}
|
||||
else if (!header.GetDestination().IsLinkLocal())
|
||||
{
|
||||
forward = true;
|
||||
}
|
||||
else if (netif == NULL)
|
||||
{
|
||||
forward = true;
|
||||
}
|
||||
}
|
||||
|
||||
message.SetOffset(sizeof(header));
|
||||
|
||||
// process IPv6 Extension Headers
|
||||
nextHeader = header.GetNextHeader();
|
||||
SuccessOrExit(HandleExtensionHeaders(message, nextHeader, receive));
|
||||
|
||||
// process IPv6 Payload
|
||||
if (receive)
|
||||
{
|
||||
SuccessOrExit(HandlePayload(message, messageInfo, nextHeader));
|
||||
|
||||
if (sNcpReceivedHandler != NULL && fromNcpHost == false)
|
||||
{
|
||||
sNcpReceivedHandler(sNcpReceivedHandlerContext, message);
|
||||
ExitNow(error = kThreadError_None);
|
||||
}
|
||||
}
|
||||
|
||||
if (forward)
|
||||
{
|
||||
if (netif != NULL)
|
||||
{
|
||||
header.SetHopLimit(header.GetHopLimit() - 1);
|
||||
}
|
||||
|
||||
if (header.GetHopLimit() == 0)
|
||||
{
|
||||
// send time exceeded
|
||||
}
|
||||
else
|
||||
{
|
||||
hopLimit = header.GetHopLimit();
|
||||
message.Write(Header::GetHopLimitOffset(), Header::GetHopLimitSize(), &hopLimit);
|
||||
SuccessOrExit(ForwardMessage(message, messageInfo));
|
||||
ExitNow(error = kThreadError_None);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error == kThreadError_Drop)
|
||||
{
|
||||
Message::Free(message);
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
int interfaceId;
|
||||
Netif *netif;
|
||||
|
||||
if (messageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
// multicast
|
||||
interfaceId = messageInfo.mInterfaceId;
|
||||
}
|
||||
else if (messageInfo.GetSockAddr().IsLinkLocal())
|
||||
{
|
||||
// on-link link-local address
|
||||
interfaceId = messageInfo.mInterfaceId;
|
||||
}
|
||||
else if ((interfaceId = Netif::GetOnLinkNetif(messageInfo.GetSockAddr())) > 0)
|
||||
{
|
||||
// on-link global address
|
||||
;
|
||||
}
|
||||
else if ((interfaceId = Routes::Lookup(messageInfo.GetPeerAddr(), messageInfo.GetSockAddr())) > 0)
|
||||
{
|
||||
// route
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
otDumpDebgIp6("no route", &messageInfo.GetSockAddr(), 16);
|
||||
ExitNow(error = kThreadError_NoRoute);
|
||||
}
|
||||
|
||||
// submit message to interface
|
||||
VerifyOrExit((netif = Netif::GetNetifById(interfaceId)) != NULL, error = kThreadError_NoRoute);
|
||||
SuccessOrExit(error = netif->SendMessage(message));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for IPv6 packet processing.
|
||||
*/
|
||||
|
||||
#ifndef IP6_HPP_
|
||||
#define IP6_HPP_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <common/encoding.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
#include <net/netif.hpp>
|
||||
#include <net/socket.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
|
||||
namespace Thread {
|
||||
|
||||
/**
|
||||
* @namespace Thread::Ip6
|
||||
*
|
||||
* @brief
|
||||
* This namespace includes definitions for IPv6 networking.
|
||||
*
|
||||
*/
|
||||
namespace Ip6 {
|
||||
|
||||
/**
|
||||
* @addtogroup core-ipv6
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for the IPv6 network layer.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @defgroup core-ip6-icmp6 ICMPv6
|
||||
* @defgroup core-ip6-ip6 IPv6
|
||||
* @defgroup core-ip6-mpl MPL
|
||||
* @defgroup core-ip6-netif Network Interfaces
|
||||
*
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup core-ip6-ip6
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for core IPv6 networking.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Internet Protocol Numbers
|
||||
*/
|
||||
enum IpProto
|
||||
{
|
||||
kProtoHopOpts = 0, ///< IPv6 Hop-by-Hop Option
|
||||
kProtoUdp = 17, ///< User Datagram
|
||||
kProtoIp6 = 41, ///< IPv6 encapsulation
|
||||
kProtoRouting = 43, ///< Routing Header for IPv6
|
||||
kProtoFragment = 44, ///< Fragment Header for IPv6
|
||||
kProtoIcmp6 = 58, ///< ICMP for IPv6
|
||||
kProtoNone = 59, ///< No Next Header for IPv6
|
||||
kProtoDstOpts = 60, ///< Destination Options for IPv6
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kVersionClassFlowSize = 4, ///< Combined size of Version, Class, Flow Label in bytes.
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents an IPv6 header.
|
||||
*
|
||||
*/
|
||||
struct HeaderPoD
|
||||
{
|
||||
union
|
||||
{
|
||||
uint8_t m8[kVersionClassFlowSize / sizeof(uint8_t)];
|
||||
uint16_t m16[kVersionClassFlowSize / sizeof(uint16_t)];
|
||||
uint32_t m32[kVersionClassFlowSize / sizeof(uint32_t)];
|
||||
} mVersionClassFlow; ///< Version, Class, Flow Label
|
||||
uint16_t mPayloadLength; ///< Payload Length
|
||||
uint8_t mNextHeader; ///< Next Header
|
||||
uint8_t mHopLimit; ///< Hop Limit
|
||||
otIp6Address mSource; ///< Source
|
||||
otIp6Address mDestination; ///< Destination
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements IPv6 header generation and parsing.
|
||||
*
|
||||
*/
|
||||
class Header: private HeaderPoD
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the IPv6 header.
|
||||
*
|
||||
*/
|
||||
void Init() { mVersionClassFlow.m32[0] = 0; mVersionClassFlow.m8[0] = kVersion6; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 Version is set to 6.
|
||||
*
|
||||
* @retval TRUE If the IPv6 Version is set to 6.
|
||||
* @retval FALSE If the IPv6 Version is not set to 6.
|
||||
*
|
||||
*/
|
||||
bool IsVersion6() const { return (mVersionClassFlow.m8[0] & kVersionMask) == kVersion6; }
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Payload Length value.
|
||||
*
|
||||
* @returns The IPv6 Payload Length value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetPayloadLength() { return HostSwap16(mPayloadLength); }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Payload Length value.
|
||||
*
|
||||
* @param[in] aLength The IPv6 Payload Length value.
|
||||
*
|
||||
*/
|
||||
void SetPayloadLength(uint16_t aLength) { mPayloadLength = HostSwap16(aLength); }
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Next Header value.
|
||||
*
|
||||
* @returns The IPv6 Next Header value.
|
||||
*
|
||||
*/
|
||||
IpProto GetNextHeader() const { return static_cast<IpProto>(mNextHeader); }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Next Header value.
|
||||
*
|
||||
* @param[in] aNextHeader The IPv6 Next Header value.
|
||||
*
|
||||
*/
|
||||
void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast<uint8_t>(aNextHeader); }
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Hop Limit value.
|
||||
*
|
||||
* @returns The IPv6 Hop Limit value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetHopLimit() const { return mHopLimit; }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Hop Limit value.
|
||||
*
|
||||
* @param[in] aHopLimit The IPv6 Hop Limit value.
|
||||
*
|
||||
*/
|
||||
void SetHopLimit(uint8_t aHopLimit) { mHopLimit = aHopLimit; }
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Source address.
|
||||
*
|
||||
* @returns A reference to the IPv6 Source address.
|
||||
*
|
||||
*/
|
||||
Address &GetSource() { return static_cast<Address &>(mSource); }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Source address.
|
||||
*
|
||||
* @param[in] aSource A reference to the IPv6 Source address.
|
||||
*
|
||||
*/
|
||||
void SetSource(const Address &aSource) { mSource = aSource; }
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Destination address.
|
||||
*
|
||||
* @returns A reference to the IPv6 Destination address.
|
||||
*
|
||||
*/
|
||||
Address &GetDestination() { return static_cast<Address &>(mDestination); }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Destination address.
|
||||
*
|
||||
* @param[in] aDestination A reference to the IPv6 Destination address.
|
||||
*
|
||||
*/
|
||||
void SetDestination(const Address &aDestination) { mDestination = aDestination; }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset of the IPv6 Payload Length field.
|
||||
*
|
||||
* @returns The byte offset of the IPv6 Payload Length field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetPayloadLengthOffset() { return offsetof(HeaderPoD, mPayloadLength); }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset of the IPv6 Hop Limit field.
|
||||
*
|
||||
* @returns The byte offset of the IPv6 Hop Limit field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetHopLimitOffset() { return offsetof(HeaderPoD, mHopLimit); }
|
||||
|
||||
/**
|
||||
* This static method returns the size of the IPv6 Hop Limit field.
|
||||
*
|
||||
* @returns The size of the IPv6 Hop Limit field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetHopLimitSize() { return sizeof(uint8_t); }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset of the IPv6 Destination field.
|
||||
*
|
||||
* @returns The byte offset of the IPv6 Destination field.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetDestinationOffset() { return offsetof(HeaderPoD, mDestination); }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kVersion6 = 0x60,
|
||||
kVersionMask = 0xf0,
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements IPv6 Extension Header generation and processing.
|
||||
*
|
||||
*/
|
||||
class ExtensionHeader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method returns the IPv6 Next Header value.
|
||||
*
|
||||
* @returns The IPv6 Next Header value.
|
||||
*
|
||||
*/
|
||||
IpProto GetNextHeader() const { return static_cast<IpProto>(mNextHeader); }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Next Header value.
|
||||
*
|
||||
* @param[in] aNextHeader The IPv6 Next Header value.
|
||||
*
|
||||
*/
|
||||
void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast<uint8_t>(aNextHeader); }
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Header Extension Length value.
|
||||
*
|
||||
* @returns The IPv6 Header Extension Length value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetLength() const { return mLength; }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Header Extension Length value.
|
||||
*
|
||||
* @param[in] aLength The IPv6 Header Extension Length value.
|
||||
*
|
||||
*/
|
||||
void SetLength(uint16_t aLength) { mLength = aLength; }
|
||||
|
||||
private:
|
||||
uint8_t mNextHeader;
|
||||
uint8_t mLength;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements IPv6 Hop-by-Hop Options Header generation and parsing.
|
||||
*
|
||||
*/
|
||||
class HopByHopHeader: public ExtensionHeader
|
||||
{
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements IPv6 Options generation and parsing.
|
||||
*
|
||||
*/
|
||||
class OptionHeader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method returns the IPv6 Option Type value.
|
||||
*
|
||||
* @returns The IPv6 Option Type value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetType() const { return mType; }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Option Type value.
|
||||
*
|
||||
* @param[in] aType The IPv6 Option Type value.
|
||||
*
|
||||
*/
|
||||
void SetType(uint8_t aType) { mType = aType; }
|
||||
|
||||
/**
|
||||
* IPv6 Option Type actions for unrecognized IPv6 Options.
|
||||
*
|
||||
*/
|
||||
enum Action
|
||||
{
|
||||
kActionSkip = 0x00, ///< skip over this option and continue processing the header
|
||||
kActionDiscard = 0x40, ///< discard the packet
|
||||
kActionForceIcmp = 0x80, ///< discard the packet and forcibly send an ICMP Parameter Problem
|
||||
kActionIcmp = 0xc0, ///< discard packet and conditionally send an ICMP Parameter Problem
|
||||
kActionMask = 0xc0, ///< mask for action bits
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Option action for unrecognized IPv6 Options.
|
||||
*
|
||||
* @returns The IPv6 Option action for unrecognized IPv6 Options.
|
||||
*
|
||||
*/
|
||||
Action GetAction() const { return static_cast<Action>(mType & kActionMask); }
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Option Length value.
|
||||
*
|
||||
* @returns The IPv6 Option Length value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetLength() const { return mLength; }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Option Length value.
|
||||
*
|
||||
* @param[in] aLength The IPv6 Option Length value.
|
||||
*
|
||||
*/
|
||||
void SetLength(uint8_t aLength) { mLength = aLength; }
|
||||
|
||||
private:
|
||||
uint8_t mType;
|
||||
uint8_t mLength;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements IPv6 Fragment Header generation and parsing.
|
||||
*
|
||||
*/
|
||||
class FragmentHeader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the IPv6 Fragment header.
|
||||
*
|
||||
*/
|
||||
void Init() { mReserved = 0; mIdentification = 0; }
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Next Header value.
|
||||
*
|
||||
* @returns The IPv6 Next Header value.
|
||||
*
|
||||
*/
|
||||
IpProto GetNextHeader() const { return static_cast<IpProto>(mNextHeader); }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Next Header value.
|
||||
*
|
||||
* @param[in] aNextHeader The IPv6 Next Header value.
|
||||
*
|
||||
*/
|
||||
void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast<uint8_t>(aNextHeader); }
|
||||
|
||||
/**
|
||||
* This method returns the Fragment Offset value.
|
||||
*
|
||||
* @returns The Fragment Offset value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetOffset() { return (HostSwap16(mOffsetMore) & kOffsetMask) >> kOffsetOffset; }
|
||||
|
||||
/**
|
||||
* This method sets the Fragment Offset value.
|
||||
*
|
||||
* @param[in] aOffset The Fragment Offset value.
|
||||
*/
|
||||
void SetOffset(uint16_t aOffset) {
|
||||
mOffsetMore = HostSwap16((HostSwap16(mOffsetMore) & kOffsetMask) | (aOffset << kOffsetOffset));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the M flag value.
|
||||
*
|
||||
* @returns The M flag value.
|
||||
*
|
||||
*/
|
||||
bool IsMoreFlagSet() { return HostSwap16(mOffsetMore) & kMoreFlag; }
|
||||
|
||||
/**
|
||||
* This method clears the M flag value.
|
||||
*
|
||||
*/
|
||||
void ClearMoreFlag() { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) & ~kMoreFlag); }
|
||||
|
||||
/**
|
||||
* This method sets the M flag value.
|
||||
*
|
||||
*/
|
||||
void SetMoreFlag() { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) | kMoreFlag); }
|
||||
|
||||
private:
|
||||
uint8_t mNextHeader;
|
||||
uint8_t mReserved;
|
||||
|
||||
enum
|
||||
{
|
||||
kOffsetOffset = 3,
|
||||
kOffsetMask = 0xfff8,
|
||||
kMoreFlag = 1,
|
||||
};
|
||||
uint16_t mOffsetMore;
|
||||
uint32_t mIdentification;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements the core IPv6 message processing.
|
||||
*
|
||||
*/
|
||||
class Ip6
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kDefaultHopLimit = 64,
|
||||
kMaxDatagramLength = 1500,
|
||||
};
|
||||
|
||||
/**
|
||||
* This static method allocates a new message buffer from the buffer pool.
|
||||
*
|
||||
* @param[in] aReserved The number of header bytes to reserve following the IPv6 header.
|
||||
*
|
||||
* @returns A pointer to the message or NULL if insufficient message buffers are available.
|
||||
*
|
||||
*/
|
||||
static Message *NewMessage(uint16_t aReserved);
|
||||
|
||||
/**
|
||||
* This static method sends an IPv6 datagram.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
|
||||
* @param[in] aIpProto The Internet Protocol value.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the message into an output interface.
|
||||
* @retval kThreadError_NoBufs Insufficient available buffer to add the IPv6 headers.
|
||||
*
|
||||
*/
|
||||
static ThreadError SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, IpProto aIpProto);
|
||||
|
||||
/**
|
||||
* This static method processes a received IPv6 datagram.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
* @param[in] aNetif A pointer to the network interface that received the message.
|
||||
* @param[in] aInterfaceId The interface identier of the network interface that received the message.
|
||||
* @param[in] aLinkMessageInfo A pointer to link-specific message information.
|
||||
* @param[in] aFromNcpHost TRUE if the message was submited by the NCP host, FALSE otherwise.
|
||||
*
|
||||
* @retval kThreadError_None Successfully processed the message.
|
||||
* @retval kThreadError_Drop Message processing failed and the message should be dropped.
|
||||
*
|
||||
*/
|
||||
static ThreadError HandleDatagram(Message &aMessage, Netif *aNetif, uint8_t aInterfaceId,
|
||||
const void *aLinkMessageInfo, bool aFromNcpHost);
|
||||
|
||||
/**
|
||||
* This static method updates a checksum.
|
||||
*
|
||||
* @param[in] aChecksum The checksum value to update.
|
||||
* @param[in] aValue The 16-bit value to update @p aChecksum with.
|
||||
*
|
||||
* @returns The updated checksum.
|
||||
*
|
||||
*/
|
||||
static uint16_t UpdateChecksum(uint16_t aChecksum, uint16_t aValue);
|
||||
|
||||
|
||||
/**
|
||||
* This static method updates a checksum.
|
||||
*
|
||||
* @param[in] aChecksum The checksum value to update.
|
||||
* @param[in] aBuf A pointer to a buffer.
|
||||
* @param[in] aLength The number of bytes in @p aBuf.
|
||||
*
|
||||
* @returns The updated checksum.
|
||||
*
|
||||
*/
|
||||
static uint16_t UpdateChecksum(uint16_t aChecksum, const void *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* This static method updates a checksum.
|
||||
*
|
||||
* @param[in] aChecksum The checksum value to update.
|
||||
* @param[in] aAddress A reference to an IPv6 address.
|
||||
*
|
||||
* @returns The updated checksum.
|
||||
*
|
||||
*/
|
||||
static uint16_t UpdateChecksum(uint16_t aChecksum, const Address &aAddress);
|
||||
|
||||
/**
|
||||
* This static method computes the pseudoheader checksum.
|
||||
*
|
||||
* @param[in] aSource A reference to the IPv6 source address.
|
||||
* @param[in] aDestination A reference to the IPv6 destination address.
|
||||
* @param[in] aLength The IPv6 Payload Length value.
|
||||
* @param[in] aProto The IPv6 Next Header value.
|
||||
*
|
||||
* @returns The psuedoheader checksum.
|
||||
*
|
||||
*/
|
||||
static uint16_t ComputePseudoheaderChecksum(const Address &aSource, const Address &aDestination,
|
||||
uint16_t aLength, IpProto aProto);
|
||||
|
||||
/**
|
||||
* This function pointer is called when an IPv6 message is received.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aMessage A reference to the IPv6 message.
|
||||
*
|
||||
*/
|
||||
typedef void (*NcpReceivedDatagramHandler)(void *aContext, Message &aMessage);
|
||||
|
||||
/**
|
||||
* This method sets the NCP receive handler.
|
||||
*
|
||||
* @param[in] aHandler A pointer to a function that is called when IPv6 messages are received.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
static void SetNcpReceivedHandler(NcpReceivedDatagramHandler aHandler, void *aContext);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NET_IP6_HPP_
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements IPv6 addresses.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/encoding.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
using Thread::Encoding::BigEndian::HostSwap32;
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
bool Address::IsUnspecified(void) const
|
||||
{
|
||||
return (m32[0] == 0 && m32[1] == 0 && m32[2] == 0 && m32[3] == 0);
|
||||
}
|
||||
|
||||
bool Address::IsLoopback(void) const
|
||||
{
|
||||
return (m32[0] == 0 && m32[1] == 0 && m32[2] == 0 && m32[3] == HostSwap32(1));
|
||||
}
|
||||
|
||||
bool Address::IsLinkLocal(void) const
|
||||
{
|
||||
return (m8[0] == 0xfe) && ((m8[1] & 0xc0) == 0x80);
|
||||
}
|
||||
|
||||
bool Address::IsMulticast(void) const
|
||||
{
|
||||
return m8[0] == 0xff;
|
||||
}
|
||||
|
||||
bool Address::IsLinkLocalMulticast(void) const
|
||||
{
|
||||
return IsMulticast() && (GetScope() == kLinkLocalScope);
|
||||
}
|
||||
|
||||
bool Address::IsLinkLocalAllNodesMulticast(void) const
|
||||
{
|
||||
return (m32[0] == HostSwap32(0xff020000) && m32[1] == 0 &&
|
||||
m32[2] == 0 && m32[3] == HostSwap32(0x01));
|
||||
}
|
||||
|
||||
bool Address::IsLinkLocalAllRoutersMulticast(void) const
|
||||
{
|
||||
return (m32[0] == HostSwap32(0xff020000) && m32[1] == 0 &&
|
||||
m32[2] == 0 && m32[3] == HostSwap32(0x02));
|
||||
}
|
||||
|
||||
bool Address::IsRealmLocalMulticast(void) const
|
||||
{
|
||||
return IsMulticast() && (GetScope() == kRealmLocalScope);
|
||||
}
|
||||
|
||||
bool Address::IsRealmLocalAllNodesMulticast(void) const
|
||||
{
|
||||
return (m32[0] == HostSwap32(0xff030000) && m32[1] == 0 &&
|
||||
m32[2] == 0 && m32[3] == HostSwap32(0x01));
|
||||
}
|
||||
|
||||
bool Address::IsRealmLocalAllRoutersMulticast(void) const
|
||||
{
|
||||
return (m32[0] == HostSwap32(0xff030000) && m32[1] == 0 &&
|
||||
m32[2] == 0 && m32[3] == HostSwap32(0x02));
|
||||
}
|
||||
|
||||
const uint8_t *Address::GetIid(void) const
|
||||
{
|
||||
return m8 + kInterfaceIdentifierOffset;
|
||||
}
|
||||
|
||||
uint8_t *Address::GetIid(void)
|
||||
{
|
||||
return m8 + kInterfaceIdentifierOffset;
|
||||
}
|
||||
|
||||
void Address::SetIid(const uint8_t *aIid)
|
||||
{
|
||||
memcpy(m8 + kInterfaceIdentifierOffset, aIid, kInterfaceIdentifierSize);
|
||||
}
|
||||
|
||||
void Address::SetIid(const Mac::ExtAddress &aEui64)
|
||||
{
|
||||
memcpy(m8 + kInterfaceIdentifierOffset, aEui64.mBytes, kInterfaceIdentifierSize);
|
||||
m8[kInterfaceIdentifierOffset] ^= 0x02;
|
||||
}
|
||||
|
||||
uint8_t Address::GetScope(void) const
|
||||
{
|
||||
if (IsMulticast())
|
||||
{
|
||||
return m8[1] & 0xf;
|
||||
}
|
||||
else if (IsLinkLocal())
|
||||
{
|
||||
return kLinkLocalScope;
|
||||
}
|
||||
else if (IsLoopback())
|
||||
{
|
||||
return kNodeLocalScope;
|
||||
}
|
||||
|
||||
return kGlobalScope;
|
||||
}
|
||||
|
||||
uint8_t Address::PrefixMatch(const Address &aOther) const
|
||||
{
|
||||
uint8_t rval = 0;
|
||||
uint8_t diff;
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(Address); i++)
|
||||
{
|
||||
diff = m8[i] ^ aOther.m8[i];
|
||||
|
||||
if (diff == 0)
|
||||
{
|
||||
rval += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((diff & 0x80) == 0)
|
||||
{
|
||||
rval++;
|
||||
diff <<= 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool Address::operator==(const Address &aOther) const
|
||||
{
|
||||
return memcmp(m8, aOther.m8, sizeof(m8)) == 0;
|
||||
}
|
||||
|
||||
bool Address::operator!=(const Address &aOther) const
|
||||
{
|
||||
return memcmp(m8, aOther.m8, sizeof(m8)) != 0;
|
||||
}
|
||||
|
||||
ThreadError Address::FromString(const char *aBuf)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *dst = reinterpret_cast<uint8_t *>(m8);
|
||||
uint8_t *endp = reinterpret_cast<uint8_t *>(m8 + 15);
|
||||
uint8_t *colonp = NULL;
|
||||
uint16_t val = 0;
|
||||
uint8_t count = 0;
|
||||
bool first = true;
|
||||
uint8_t ch;
|
||||
uint8_t d;
|
||||
|
||||
memset(m8, 0, 16);
|
||||
|
||||
dst--;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ch = *aBuf++;
|
||||
d = ch & 0xf;
|
||||
|
||||
if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F'))
|
||||
{
|
||||
d += 9;
|
||||
}
|
||||
else if (ch == ':' || ch == '\0' || ch == ' ')
|
||||
{
|
||||
if (count)
|
||||
{
|
||||
VerifyOrExit(dst + 2 <= endp, error = kThreadError_Parse);
|
||||
*(dst + 1) = static_cast<uint8_t>(val >> 8);
|
||||
*(dst + 2) = static_cast<uint8_t>(val);
|
||||
dst += 2;
|
||||
count = 0;
|
||||
val = 0;
|
||||
}
|
||||
else if (ch == ':')
|
||||
{
|
||||
VerifyOrExit(colonp == NULL || first, error = kThreadError_Parse);
|
||||
colonp = dst;
|
||||
}
|
||||
|
||||
if (ch == '\0' || ch == ' ')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit('0' <= ch && ch <= '9', error = kThreadError_Parse);
|
||||
}
|
||||
|
||||
first = false;
|
||||
val = (val << 4) | d;
|
||||
VerifyOrExit(++count <= 4, error = kThreadError_Parse);
|
||||
}
|
||||
|
||||
while (colonp && dst > colonp)
|
||||
{
|
||||
*endp-- = *dst--;
|
||||
}
|
||||
|
||||
while (endp > dst)
|
||||
{
|
||||
*endp-- = 0;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
const char *Address::ToString(char *aBuf, uint16_t aSize) const
|
||||
{
|
||||
snprintf(aBuf, aSize, "%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
HostSwap16(m16[0]), HostSwap16(m16[1]),
|
||||
HostSwap16(m16[2]), HostSwap16(m16[3]),
|
||||
HostSwap16(m16[4]), HostSwap16(m16[5]),
|
||||
HostSwap16(m16[6]), HostSwap16(m16[7]));
|
||||
return aBuf;
|
||||
}
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for IPv6 addresses.
|
||||
*/
|
||||
|
||||
#ifndef IP6_ADDRESS_HPP_
|
||||
#define IP6_ADDRESS_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
/**
|
||||
* @addtogroup core-ip6-ip6
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements an IPv6 address object.
|
||||
*
|
||||
*/
|
||||
class Address: public otIp6Address
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constants
|
||||
*
|
||||
*/
|
||||
enum
|
||||
{
|
||||
kInterfaceIdentifierSize = 8, ///< Interface Identifier size in bytes.
|
||||
};
|
||||
|
||||
/**
|
||||
* IPv6 Address Scopes
|
||||
*/
|
||||
enum
|
||||
{
|
||||
kNodeLocalScope = 0, ///< Node-Local scope
|
||||
kInterfaceLocalScope = 1, ///< Interface-Local scope
|
||||
kLinkLocalScope = 2, ///< Link-Local scope
|
||||
kRealmLocalScope = 3, ///< Realm-Local scope
|
||||
kAdminLocalScope = 4, ///< Admin-Local scope
|
||||
kSiteLocalScope = 5, ///< Site-Local scope
|
||||
kOrgLocalScope = 8, ///< Organization-Local scope
|
||||
kGlobalScope = 14, ///< Global scope
|
||||
};
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is the Unspecified Address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is the Unspecified Address.
|
||||
* @retval FALSE If the IPv6 address is not the Unspecified Address.
|
||||
*
|
||||
*/
|
||||
bool IsUnspecified(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is the Loopback Address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is the Loopback Address.
|
||||
* @retval FALSE If the IPv6 address is not the Loopback Address.
|
||||
*
|
||||
*/
|
||||
bool IsLoopback(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address scope is Interafce-Local.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address scope is Interface-Local.
|
||||
* @retval FALSE If the IPv6 address scope is not Interface-Local.
|
||||
*
|
||||
*/
|
||||
bool IsInterfaceLocal(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address scope is Link-Local.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address scope is Link-Local.
|
||||
* @retval FALSE If the IPv6 address scope is not Link-Local.
|
||||
*
|
||||
*/
|
||||
bool IsLinkLocal(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is multicast address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a multicast address.
|
||||
* @retval FALSE If the IPv6 address scope is not a multicast address.
|
||||
*
|
||||
*/
|
||||
bool IsMulticast(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is a link-local multicast address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a link-local multicast address.
|
||||
* @retval FALSE If the IPv6 address scope is not a link-local multicast address.
|
||||
*
|
||||
*/
|
||||
bool IsLinkLocalMulticast(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is a link-local all nodes multicast address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a link-local all nodes multicast address.
|
||||
* @retval FALSE If the IPv6 address scope is not a link-local all nodes multicast address.
|
||||
*
|
||||
*/
|
||||
bool IsLinkLocalAllNodesMulticast(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is a link-local all routers multicast address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a link-local all routers multicast address.
|
||||
* @retval FALSE If the IPv6 address scope is not a link-local all routers multicast address.
|
||||
*
|
||||
*/
|
||||
bool IsLinkLocalAllRoutersMulticast(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is a realm-local multicast address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a realm-local multicast address.
|
||||
* @retval FALSE If the IPv6 address scope is not a realm-local multicast address.
|
||||
*
|
||||
*/
|
||||
bool IsRealmLocalMulticast(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is a realm-local all nodes multicast address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a realm-local all nodes multicast address.
|
||||
* @retval FALSE If the IPv6 address scope is not a realm-local all nodes multicast address.
|
||||
*
|
||||
*/
|
||||
bool IsRealmLocalAllNodesMulticast(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is a realm-local all routers multicast address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a realm-local all routers multicast address.
|
||||
* @retval FALSE If the IPv6 address scope is not a realm-local all routers multicast address.
|
||||
*
|
||||
*/
|
||||
bool IsRealmLocalAllRoutersMulticast(void) const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Interface Identifier.
|
||||
*
|
||||
* @returns A pointer to the Interface Identifier.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetIid(void) const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Interface Identifier.
|
||||
*
|
||||
* @returns A pointer to the Interface Identifier.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetIid(void);
|
||||
|
||||
/**
|
||||
* This method sets the Interface Identifier.
|
||||
*
|
||||
* @param[in] aIid A reference to the Interface Identifier.
|
||||
*
|
||||
*/
|
||||
void SetIid(const uint8_t *aIid);
|
||||
|
||||
/**
|
||||
* This method sets the Interface Identifier.
|
||||
*
|
||||
* @param[in] aEui64 A reference to the IEEE EUI-64 address.
|
||||
*
|
||||
*/
|
||||
void SetIid(const Mac::ExtAddress &aEui64);
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 address scope.
|
||||
*
|
||||
* @returns The IPv6 address scope.
|
||||
*
|
||||
*/
|
||||
uint8_t GetScope(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the number of IPv6 prefix bits that match.
|
||||
*
|
||||
* @param[in] aOther The IPv6 address to match against.
|
||||
*
|
||||
* @returns The number of IPv6 prefix bits that match.
|
||||
*
|
||||
*/
|
||||
uint8_t PrefixMatch(const Address &aOther) const;
|
||||
|
||||
/**
|
||||
* This method evaluates whether or not the IPv6 addresses match.
|
||||
*
|
||||
* @param[in] aOther The IPv6 address to compare.
|
||||
*
|
||||
* @retval TRUE If the IPv6 addresses match.
|
||||
* @retval FALSE If the IPv6 addresses do not match.
|
||||
*
|
||||
*/
|
||||
bool operator==(const Address &aOther) const;
|
||||
|
||||
/**
|
||||
* This method evaluates whether or not the IPv6 addresses differ.
|
||||
*
|
||||
* @param[in] aOther The IPv6 address to compare.
|
||||
*
|
||||
* @retval TRUE If the IPv6 addresses differ.
|
||||
* @retval FALSE If the IPv6 addresses do not differ.
|
||||
*
|
||||
*/
|
||||
bool operator!=(const Address &aOther) const;
|
||||
|
||||
/**
|
||||
* This method converts an IPv6 address string to binary.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the NULL-terminated string.
|
||||
*
|
||||
* @retval kThreadError_None Successfully parsed the IPv6 address string.
|
||||
* @retval kTheradError_InvalidArgs Failed to parse the IPv6 address string.
|
||||
*
|
||||
*/
|
||||
ThreadError FromString(const char *aBuf);
|
||||
|
||||
/**
|
||||
* This method converts an IPv6 address object to a NULL-terminated string.
|
||||
*
|
||||
* @param[out] aBuf A pointer to the buffer.
|
||||
* @param[in] aSize The maximum size of the buffer.
|
||||
*
|
||||
* @returns A pointer to the buffer.
|
||||
*
|
||||
*/
|
||||
const char *ToString(char *aBuf, uint16_t aSize) const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kInterfaceIdentifierOffset = 8, ///< Interface Identifier offset in bytes.
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NET_IP6_ADDRESS_HPP_
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements MPL.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <net/ip6_mpl.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
Mpl::Mpl():
|
||||
mTimer(&HandleTimer, this)
|
||||
{
|
||||
memset(mEntries, 0, sizeof(mEntries));
|
||||
mSequence = 0;
|
||||
}
|
||||
|
||||
void Mpl::InitOption(OptionMpl &aOption, uint16_t aSeed)
|
||||
{
|
||||
aOption.Init();
|
||||
aOption.SetSeedLength(OptionMpl::kSeedLength2);
|
||||
aOption.SetSequence(mSequence++);
|
||||
aOption.SetSeed(aSeed);
|
||||
}
|
||||
|
||||
ThreadError Mpl::ProcessOption(const Message &aMessage)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
OptionMpl option;
|
||||
MplEntry *entry = NULL;
|
||||
int8_t diff;
|
||||
|
||||
VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(option), &option) == sizeof(option) &&
|
||||
option.GetLength() == sizeof(OptionMpl) - sizeof(OptionHeader),
|
||||
error = kThreadError_Drop);
|
||||
|
||||
for (int i = 0; i < kNumEntries; i++)
|
||||
{
|
||||
if (mEntries[i].mLifetime == 0)
|
||||
{
|
||||
entry = &mEntries[i];
|
||||
}
|
||||
else if (mEntries[i].mSeed == option.GetSeed())
|
||||
{
|
||||
entry = &mEntries[i];
|
||||
diff = option.GetSequence() - entry->mSequence;
|
||||
|
||||
if (diff <= 0)
|
||||
{
|
||||
error = kThreadError_Drop;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrExit(entry != NULL, error = kThreadError_Drop);
|
||||
|
||||
entry->mSeed = option.GetSeed();
|
||||
entry->mSequence = option.GetSequence();
|
||||
entry->mLifetime = kLifetime;
|
||||
mTimer.Start(1000);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Mpl::HandleTimer(void *aContext)
|
||||
{
|
||||
Mpl *obj = reinterpret_cast<Mpl *>(aContext);
|
||||
obj->HandleTimer();
|
||||
}
|
||||
|
||||
void Mpl::HandleTimer()
|
||||
{
|
||||
bool startTimer = false;
|
||||
|
||||
for (int i = 0; i < kNumEntries; i++)
|
||||
{
|
||||
if (mEntries[i].mLifetime > 0)
|
||||
{
|
||||
mEntries[i].mLifetime--;
|
||||
startTimer = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (startTimer)
|
||||
{
|
||||
mTimer.Start(1000);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef IP6_MPL_HPP_
|
||||
#define IP6_MPL_HPP_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for MPL.
|
||||
*/
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <common/message.hpp>
|
||||
#include <common/timer.hpp>
|
||||
#include <net/ip6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
/**
|
||||
* @addtogroup core-ip6-mpl
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for MPL.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements MPL header generation and parsing.
|
||||
*
|
||||
*/
|
||||
class OptionMpl: public OptionHeader
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kType = 0x6d, /* 01 1 01101 */
|
||||
};
|
||||
|
||||
/**
|
||||
* This method initializes the MPL header.
|
||||
*
|
||||
*/
|
||||
void Init() {
|
||||
OptionHeader::SetType(kType);
|
||||
OptionHeader::SetLength(sizeof(*this) - sizeof(OptionHeader));
|
||||
}
|
||||
|
||||
/**
|
||||
* MPL Seed lengths.
|
||||
*/
|
||||
enum SeedLength
|
||||
{
|
||||
kSeedLength0 = 0 << 6, ///< 0-byte MPL Seed Length.
|
||||
kSeedLength2 = 1 << 6, ///< 2-byte MPL Seed Length.
|
||||
kSeedLength8 = 2 << 6, ///< 8-byte MPL Seed Length.
|
||||
kSeedLength16 = 3 << 6, ///< 16-byte MPL Seed Length.
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns the MPL Seed Length value.
|
||||
*
|
||||
* @returns The MPL Seed Length value.
|
||||
*
|
||||
*/
|
||||
SeedLength GetSeedLength() { return static_cast<SeedLength>(mControl & kSeedLengthMask); }
|
||||
|
||||
/**
|
||||
* This method sets the MPL Seed Length value.
|
||||
*
|
||||
* @param[in] aSeedLength The MPL Seed Length.
|
||||
*
|
||||
*/
|
||||
void SetSeedLength(SeedLength aSeedLength) { mControl = (mControl & ~kSeedLengthMask) | aSeedLength; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the MPL M flag is set.
|
||||
*
|
||||
* @retval TRUE If the MPL M flag is set.
|
||||
* @retval FALSE If the MPL M flag is not set.
|
||||
*
|
||||
*/
|
||||
bool IsMaxFlagSet() { return mControl & kMaxFlag; }
|
||||
|
||||
/**
|
||||
* This method clears the MPL M flag.
|
||||
*
|
||||
*/
|
||||
void ClearMaxFlag() { mControl &= ~kMaxFlag; }
|
||||
|
||||
/**
|
||||
* This method sets the MPL M flag.
|
||||
*
|
||||
*/
|
||||
void SetMaxFlag() { mControl |= kMaxFlag; }
|
||||
|
||||
/**
|
||||
* This method returns the MPL Sequence value.
|
||||
*
|
||||
* @returns The MPL Sequence value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetSequence() const { return mSequence; }
|
||||
|
||||
/**
|
||||
* This method sets the MPL Sequence value.
|
||||
*
|
||||
* @param[in] aSequence The MPL Sequence value.
|
||||
*/
|
||||
void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
|
||||
|
||||
/**
|
||||
* This method returns the MPL Seed value.
|
||||
*
|
||||
* @returns The MPL Seed value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetSeed() const { return HostSwap16(mSeed); }
|
||||
|
||||
/**
|
||||
* This method sets the MPL Seed value.
|
||||
*
|
||||
* @param[in] aSeed The MPL Seed value.
|
||||
*/
|
||||
void SetSeed(uint16_t aSeed) { mSeed = HostSwap16(aSeed); }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kSeedLengthMask = 3 << 6,
|
||||
kMaxFlag = 1 << 5,
|
||||
};
|
||||
uint8_t mControl;
|
||||
uint8_t mSequence;
|
||||
uint16_t mSeed;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements MPL message processing.
|
||||
*
|
||||
*/
|
||||
class Mpl
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the MPL object.
|
||||
*
|
||||
*/
|
||||
Mpl(void);
|
||||
|
||||
/**
|
||||
* This method initializes the MPL option.
|
||||
*
|
||||
* @param[in] aOption A reference to the MPL header to initialize.
|
||||
* @param[in] aSeed The MPL Seed value to use.
|
||||
*
|
||||
*/
|
||||
void InitOption(OptionMpl &aOption, uint16_t aSeed);
|
||||
|
||||
/**
|
||||
* This method processes an MPL option.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
* @retval kThreadError_None Successfully processed the MPL option.
|
||||
* @retval kThreadError_Drop The MPL message is a duplicate and should be dropped.
|
||||
*
|
||||
*/
|
||||
ThreadError ProcessOption(const Message &aMessage);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kNumEntries = OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES,
|
||||
kLifetime = OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME,
|
||||
};
|
||||
|
||||
static void HandleTimer(void *context);
|
||||
void HandleTimer();
|
||||
|
||||
Timer mTimer;
|
||||
uint8_t mSequence;
|
||||
|
||||
struct MplEntry
|
||||
{
|
||||
uint16_t mSeed;
|
||||
uint8_t mSequence;
|
||||
uint8_t mLifetime;
|
||||
};
|
||||
MplEntry mEntries[kNumEntries];
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NET_IP6_MPL_HPP_
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements IPv6 route tables.
|
||||
*/
|
||||
|
||||
#include <net/ip6_routes.hpp>
|
||||
#include <net/netif.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/message.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
static Route *sRoutes = NULL;
|
||||
|
||||
ThreadError Routes::Add(Route &aRoute)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
for (Route *cur = sRoutes; cur; cur = cur->mNext)
|
||||
{
|
||||
VerifyOrExit(cur != &aRoute, error = kThreadError_Busy);
|
||||
}
|
||||
|
||||
aRoute.mNext = sRoutes;
|
||||
sRoutes = &aRoute;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Routes::Remove(Route &aRoute)
|
||||
{
|
||||
if (&aRoute == sRoutes)
|
||||
{
|
||||
sRoutes = aRoute.mNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Route *cur = sRoutes; cur; cur = cur->mNext)
|
||||
{
|
||||
if (cur->mNext == &aRoute)
|
||||
{
|
||||
cur->mNext = aRoute.mNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aRoute.mNext = NULL;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
int Routes::Lookup(const Address &aSource, const Address &aDestination)
|
||||
{
|
||||
int maxPrefixMatch = -1;
|
||||
uint8_t prefixMatch;
|
||||
int rval = -1;
|
||||
|
||||
for (Route *cur = sRoutes; cur; cur = cur->mNext)
|
||||
{
|
||||
prefixMatch = cur->mPrefix.PrefixMatch(aDestination);
|
||||
|
||||
if (prefixMatch < cur->mPrefixLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefixMatch > cur->mPrefixLength)
|
||||
{
|
||||
prefixMatch = cur->mPrefixLength;
|
||||
}
|
||||
|
||||
if (maxPrefixMatch > prefixMatch)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
maxPrefixMatch = prefixMatch;
|
||||
rval = cur->mInterfaceId;
|
||||
}
|
||||
|
||||
for (Netif *netif = Netif::GetNetifList(); netif; netif = netif->GetNext())
|
||||
{
|
||||
if (netif->RouteLookup(aSource, aDestination, &prefixMatch) == kThreadError_None &&
|
||||
prefixMatch > maxPrefixMatch)
|
||||
{
|
||||
maxPrefixMatch = prefixMatch;
|
||||
rval = netif->GetInterfaceId();
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef IP6_ROUTES_HPP_
|
||||
#define IP6_ROUTES_HPP_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for manipulating IPv6 routing tables.
|
||||
*/
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <common/message.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
/**
|
||||
* @addtogroup core-ip6-ip6
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This structure represents an IPv6 route.
|
||||
*
|
||||
*/
|
||||
struct Route
|
||||
{
|
||||
Address mPrefix; ///< The IPv6 prefix.
|
||||
uint8_t mPrefixLength; ///< The IPv6 prefix length.
|
||||
uint8_t mInterfaceId; ///< The interface identifier.
|
||||
struct Route *mNext; ///< A pointer to the next IPv6 route.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements IPv6 route management.
|
||||
*
|
||||
*/
|
||||
class Routes
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This static method adds an IPv6 route.
|
||||
*
|
||||
* @param[in] aRoute A reference to the IPv6 route.
|
||||
*
|
||||
* @retval kThreadError_None Successfully added the route.
|
||||
* @retval kThreadError_Busy The route was already added.
|
||||
*
|
||||
*/
|
||||
static ThreadError Add(Route &aRoute);
|
||||
|
||||
/**
|
||||
* This static method removes an IPv6 route.
|
||||
*
|
||||
* @param[in] aRoute A reference to the IPv6 route.
|
||||
*
|
||||
* @retval kThreadError_None Successfully removed the route.
|
||||
* @retval kThreadError_InvalidArgs The route was not added.
|
||||
*
|
||||
*/
|
||||
static ThreadError Remove(Route &aRoute);
|
||||
|
||||
/**
|
||||
* This static method performs source-destination route lookup.
|
||||
*
|
||||
* @param[in] aSource The IPv6 source address.
|
||||
* @param[in] aDestination The IPv6 destination address.
|
||||
*
|
||||
* @returns The interface identifier for the best route or -1 if no route is available.
|
||||
*
|
||||
*/
|
||||
static int Lookup(const Address &aSource, const Address &aDestination);
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NET_IP6_ROUTES_HPP_
|
||||
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements IPv6 network interfaces.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <net/netif.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
Netif *Netif::sNetifListHead = NULL;
|
||||
int Netif::sNextInterfaceId = 1;
|
||||
|
||||
Netif::Netif() :
|
||||
mUnicastChangedTask(&HandleUnicastChangedTask, this)
|
||||
{
|
||||
mHandlers = NULL;
|
||||
mUnicastAddresses = NULL;
|
||||
mMulticastAddresses = NULL;
|
||||
mInterfaceId = -1;
|
||||
mAllRoutersSubscribed = false;
|
||||
mNext = NULL;
|
||||
}
|
||||
|
||||
ThreadError Netif::RegisterHandler(NetifHandler &aHandler)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
for (NetifHandler *cur = mHandlers; cur; cur = cur->mNext)
|
||||
{
|
||||
if (cur == &aHandler)
|
||||
{
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
}
|
||||
}
|
||||
|
||||
aHandler.mNext = mHandlers;
|
||||
mHandlers = &aHandler;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Netif::AddNetif()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Netif *netif;
|
||||
|
||||
if (sNetifListHead == NULL)
|
||||
{
|
||||
sNetifListHead = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
netif = sNetifListHead;
|
||||
|
||||
do
|
||||
{
|
||||
if (netif == this)
|
||||
{
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
}
|
||||
}
|
||||
while (netif->mNext);
|
||||
|
||||
netif->mNext = this;
|
||||
}
|
||||
|
||||
mNext = NULL;
|
||||
|
||||
if (mInterfaceId < 0)
|
||||
{
|
||||
mInterfaceId = sNextInterfaceId++;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Netif::RemoveNetif()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(sNetifListHead != NULL, error = kThreadError_Busy);
|
||||
|
||||
if (sNetifListHead == this)
|
||||
{
|
||||
sNetifListHead = mNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Netif *netif = sNetifListHead; netif->mNext; netif = netif->mNext)
|
||||
{
|
||||
if (netif->mNext != this)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
netif->mNext = mNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mNext = NULL;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Netif *Netif::GetNext() const
|
||||
{
|
||||
return mNext;
|
||||
}
|
||||
|
||||
Netif *Netif::GetNetifById(uint8_t aInterfaceId)
|
||||
{
|
||||
Netif *netif;
|
||||
|
||||
for (netif = sNetifListHead; netif; netif = netif->mNext)
|
||||
{
|
||||
if (netif->mInterfaceId == aInterfaceId)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return netif;
|
||||
}
|
||||
|
||||
Netif *Netif::GetNetifByName(char *aName)
|
||||
{
|
||||
Netif *netif;
|
||||
|
||||
for (netif = sNetifListHead; netif; netif = netif->mNext)
|
||||
{
|
||||
if (strcmp(netif->GetName(), aName) == 0)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return netif;
|
||||
}
|
||||
|
||||
int Netif::GetInterfaceId() const
|
||||
{
|
||||
return mInterfaceId;
|
||||
}
|
||||
|
||||
bool Netif::IsMulticastSubscribed(const Address &aAddress) const
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
if (aAddress.IsLinkLocalAllNodesMulticast() || aAddress.IsRealmLocalAllNodesMulticast())
|
||||
{
|
||||
ExitNow(rval = true);
|
||||
}
|
||||
else if (aAddress.IsLinkLocalAllRoutersMulticast() || aAddress.IsRealmLocalAllRoutersMulticast())
|
||||
{
|
||||
ExitNow(rval = mAllRoutersSubscribed);
|
||||
}
|
||||
|
||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->mNext)
|
||||
{
|
||||
if (memcmp(&cur->mAddress, &aAddress, sizeof(cur->mAddress)) == 0)
|
||||
{
|
||||
ExitNow(rval = true);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
void Netif::SubscribeAllRoutersMulticast()
|
||||
{
|
||||
mAllRoutersSubscribed = true;
|
||||
}
|
||||
|
||||
void Netif::UnsubscribeAllRoutersMulticast()
|
||||
{
|
||||
mAllRoutersSubscribed = false;
|
||||
}
|
||||
|
||||
ThreadError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->mNext)
|
||||
{
|
||||
if (cur == &aAddress)
|
||||
{
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
}
|
||||
}
|
||||
|
||||
aAddress.mNext = mMulticastAddresses;
|
||||
mMulticastAddresses = &aAddress;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Netif::UnsubscribeMulticast(const NetifMulticastAddress &aAddress)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
if (mMulticastAddresses == &aAddress)
|
||||
{
|
||||
mMulticastAddresses = mMulticastAddresses->mNext;
|
||||
ExitNow();
|
||||
}
|
||||
else if (mMulticastAddresses != NULL)
|
||||
{
|
||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur->mNext; cur = cur->mNext)
|
||||
{
|
||||
if (cur->mNext == &aAddress)
|
||||
{
|
||||
cur->mNext = aAddress.mNext;
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExitNow(error = kThreadError_Error);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
const NetifUnicastAddress *Netif::GetUnicastAddresses() const
|
||||
{
|
||||
return mUnicastAddresses;
|
||||
}
|
||||
|
||||
ThreadError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
for (NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext())
|
||||
{
|
||||
if (cur == &aAddress)
|
||||
{
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
}
|
||||
}
|
||||
|
||||
aAddress.mNext = mUnicastAddresses;
|
||||
mUnicastAddresses = &aAddress;
|
||||
|
||||
mUnicastChangedTask.Post();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Netif::RemoveUnicastAddress(const NetifUnicastAddress &aAddress)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
if (mUnicastAddresses == &aAddress)
|
||||
{
|
||||
mUnicastAddresses = mUnicastAddresses->GetNext();
|
||||
ExitNow();
|
||||
}
|
||||
else if (mUnicastAddresses != NULL)
|
||||
{
|
||||
for (NetifUnicastAddress *cur = mUnicastAddresses; cur->GetNext(); cur = cur->GetNext())
|
||||
{
|
||||
if (cur->mNext == &aAddress)
|
||||
{
|
||||
cur->mNext = aAddress.mNext;
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExitNow(error = kThreadError_Error);
|
||||
|
||||
exit:
|
||||
mUnicastChangedTask.Post();
|
||||
return error;
|
||||
}
|
||||
|
||||
Netif *Netif::GetNetifList()
|
||||
{
|
||||
return sNetifListHead;
|
||||
}
|
||||
|
||||
bool Netif::IsUnicastAddress(const Address &aAddress)
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
for (Netif *netif = sNetifListHead; netif; netif = netif->mNext)
|
||||
{
|
||||
for (NetifUnicastAddress *cur = netif->mUnicastAddresses; cur; cur = cur->GetNext())
|
||||
{
|
||||
if (cur->GetAddress() == aAddress)
|
||||
{
|
||||
ExitNow(rval = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
const NetifUnicastAddress *Netif::SelectSourceAddress(MessageInfo &aMessageInfo)
|
||||
{
|
||||
Address *destination = &aMessageInfo.GetPeerAddr();
|
||||
int interfaceId = aMessageInfo.mInterfaceId;
|
||||
const NetifUnicastAddress *rvalAddr = NULL;
|
||||
const Address *candidateAddr;
|
||||
uint8_t candidateId;
|
||||
uint8_t rvalIface = 0;
|
||||
|
||||
for (Netif *netif = GetNetifList(); netif; netif = netif->mNext)
|
||||
{
|
||||
candidateId = netif->GetInterfaceId();
|
||||
|
||||
for (const NetifUnicastAddress *addr = netif->GetUnicastAddresses(); addr; addr = addr->GetNext())
|
||||
{
|
||||
candidateAddr = &addr->GetAddress();
|
||||
|
||||
if (destination->IsLinkLocal() || destination->IsMulticast())
|
||||
{
|
||||
if (interfaceId != candidateId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (rvalAddr == NULL)
|
||||
{
|
||||
// Rule 0: Prefer any address
|
||||
rvalAddr = addr;
|
||||
rvalIface = candidateId;
|
||||
}
|
||||
else if (*candidateAddr == *destination)
|
||||
{
|
||||
// Rule 1: Prefer same address
|
||||
rvalAddr = addr;
|
||||
rvalIface = candidateId;
|
||||
goto exit;
|
||||
}
|
||||
else if (candidateAddr->GetScope() < rvalAddr->GetAddress().GetScope())
|
||||
{
|
||||
// Rule 2: Prefer appropriate scope
|
||||
if (candidateAddr->GetScope() >= destination->GetScope())
|
||||
{
|
||||
rvalAddr = addr;
|
||||
rvalIface = candidateId;
|
||||
}
|
||||
}
|
||||
else if (candidateAddr->GetScope() > rvalAddr->GetAddress().GetScope())
|
||||
{
|
||||
if (rvalAddr->GetAddress().GetScope() < destination->GetScope())
|
||||
{
|
||||
rvalAddr = addr;
|
||||
rvalIface = candidateId;
|
||||
}
|
||||
}
|
||||
else if (addr->mPreferredLifetime != 0 && rvalAddr->mPreferredLifetime == 0)
|
||||
{
|
||||
// Rule 3: Avoid deprecated addresses
|
||||
rvalAddr = addr;
|
||||
rvalIface = candidateId;
|
||||
}
|
||||
else if (aMessageInfo.mInterfaceId != 0 && aMessageInfo.mInterfaceId == candidateId &&
|
||||
rvalIface != candidateId)
|
||||
{
|
||||
// Rule 4: Prefer home address
|
||||
// Rule 5: Prefer outgoing interface
|
||||
rvalAddr = addr;
|
||||
rvalIface = candidateId;
|
||||
}
|
||||
else if (destination->PrefixMatch(*candidateAddr) > destination->PrefixMatch(rvalAddr->GetAddress()))
|
||||
{
|
||||
// Rule 6: Prefer matching label
|
||||
// Rule 7: Prefer public address
|
||||
// Rule 8: Use longest prefix matching
|
||||
rvalAddr = addr;
|
||||
rvalIface = candidateId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
aMessageInfo.mInterfaceId = rvalIface;
|
||||
return rvalAddr;
|
||||
}
|
||||
|
||||
int Netif::GetOnLinkNetif(const Address &aAddress)
|
||||
{
|
||||
int rval = -1;
|
||||
|
||||
for (Netif *netif = sNetifListHead; netif; netif = netif->mNext)
|
||||
{
|
||||
for (NetifUnicastAddress *cur = netif->mUnicastAddresses; cur; cur = cur->GetNext())
|
||||
{
|
||||
if (cur->GetAddress().PrefixMatch(aAddress) >= cur->mPrefixLength)
|
||||
{
|
||||
ExitNow(rval = netif->mInterfaceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
void Netif::HandleUnicastChangedTask(void *aContext)
|
||||
{
|
||||
Netif *obj = reinterpret_cast<Netif *>(aContext);
|
||||
obj->HandleUnicastChangedTask();
|
||||
}
|
||||
|
||||
void Netif::HandleUnicastChangedTask()
|
||||
{
|
||||
for (NetifHandler *handler = mHandlers; handler; handler = handler->mNext)
|
||||
{
|
||||
handler->HandleUnicastAddressesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for IPv6 network interfaces.
|
||||
*/
|
||||
|
||||
#ifndef NET_NETIF_HPP_
|
||||
#define NET_NETIF_HPP_
|
||||
|
||||
#include <common/message.hpp>
|
||||
#include <common/tasklet.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
#include <net/socket.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
/**
|
||||
* @addtogroup core-ip6-netif
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for IPv6 network interfaces.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class represents an IPv6 Link Address.
|
||||
*
|
||||
*/
|
||||
class LinkAddress
|
||||
{
|
||||
public :
|
||||
/**
|
||||
* Hardware types.
|
||||
*
|
||||
*/
|
||||
enum HardwareType
|
||||
{
|
||||
kEui64 = 27,
|
||||
};
|
||||
HardwareType mType; ///< Link address type.
|
||||
uint8_t mLength; ///< Length of link address.
|
||||
Mac::ExtAddress mExtAddress; ///< Link address.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements an IPv6 network interface unicast address.
|
||||
*
|
||||
*/
|
||||
class NetifUnicastAddress: public otNetifAddress
|
||||
{
|
||||
friend class Netif;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This method returns the unicast address.
|
||||
*
|
||||
* @returns The unicast address.
|
||||
*
|
||||
*/
|
||||
const Address &GetAddress(void) const { return *static_cast<const Address *>(&mAddress); }
|
||||
|
||||
/**
|
||||
* This method returns the unicast address.
|
||||
*
|
||||
* @returns The unicast address.
|
||||
*
|
||||
*/
|
||||
Address &GetAddress(void) { return *static_cast<Address *>(&mAddress); }
|
||||
|
||||
/**
|
||||
* This method returns the next unicast address assigned to the interface.
|
||||
*
|
||||
* @returns A pointer to the next unicast address.
|
||||
*
|
||||
*/
|
||||
const NetifUnicastAddress *GetNext(void) const { return static_cast<const NetifUnicastAddress *>(mNext); }
|
||||
|
||||
/**
|
||||
* This method returns the next unicast address assigned to the interface.
|
||||
*
|
||||
* @returns A pointer to the next unicast address.
|
||||
*
|
||||
*/
|
||||
NetifUnicastAddress *GetNext(void) { return static_cast<NetifUnicastAddress *>(mNext); }
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements an IPv6 network interface multicast address.
|
||||
*
|
||||
*/
|
||||
class NetifMulticastAddress
|
||||
{
|
||||
friend class Netif;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This method returns the multicast address.
|
||||
*
|
||||
* @returns The multicast address.
|
||||
*
|
||||
*/
|
||||
const Address &GetAddress(void) const { return *static_cast<const Address *>(&mAddress); }
|
||||
|
||||
/**
|
||||
* This method returns the multicast address.
|
||||
*
|
||||
* @returns The multicast address.
|
||||
*
|
||||
*/
|
||||
Address &GetAddress(void) { return *static_cast<Address *>(&mAddress); }
|
||||
|
||||
/**
|
||||
* This method returns the next multicast address assigned to the interface.
|
||||
*
|
||||
* @returns A pointer to the next multicast address.
|
||||
*
|
||||
*/
|
||||
const NetifMulticastAddress *GetNext(void) const { return mNext; }
|
||||
|
||||
private:
|
||||
Address mAddress;
|
||||
NetifMulticastAddress *mNext;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements network interface handlers.
|
||||
*
|
||||
*/
|
||||
class NetifHandler
|
||||
{
|
||||
friend class Netif;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when the set of assigned unicast addresses change.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
typedef void (*UnicastAddressesChangedHandler)(void *aContext);
|
||||
|
||||
/**
|
||||
* This constructor initializes the network interface handlers.
|
||||
*
|
||||
* @param[in] aHandler A pointer to a function that is called when the set of assigned unicast addresses
|
||||
* change.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
NetifHandler(UnicastAddressesChangedHandler aHandler, void *aContext) {
|
||||
mUnicastHandler = aHandler;
|
||||
mContext = aContext;
|
||||
}
|
||||
|
||||
private:
|
||||
void HandleUnicastAddressesChanged(void) { mUnicastHandler(mContext); }
|
||||
|
||||
UnicastAddressesChangedHandler mUnicastHandler;
|
||||
void *mContext;
|
||||
NetifHandler *mNext;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements an IPv6 network interface.
|
||||
*
|
||||
*/
|
||||
class Netif
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the network interface.
|
||||
*
|
||||
*/
|
||||
Netif(void);
|
||||
|
||||
/**
|
||||
* This method enables the network interface.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enabled the network interface.
|
||||
* @retval KThreadError_Busy The network interface was already enabled.
|
||||
*
|
||||
*/
|
||||
ThreadError AddNetif(void);
|
||||
|
||||
/**
|
||||
* This method disables the network interface.
|
||||
*
|
||||
* @retval kThreadError_None Successfully disabled the network interface.
|
||||
* @retval KThreadError_Busy The network interface was already disabled.
|
||||
*
|
||||
*/
|
||||
ThreadError RemoveNetif(void);
|
||||
|
||||
/**
|
||||
* This method returns the next network interface in the list.
|
||||
*
|
||||
* @returns A pointer to the next network interface.
|
||||
*/
|
||||
Netif *GetNext(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the network interface identifier.
|
||||
*
|
||||
* @returns The network interface identifier.
|
||||
*
|
||||
*/
|
||||
int GetInterfaceId(void) const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the list of unicast addresses.
|
||||
*
|
||||
* @returns A pointer to the list of unicast addresses.
|
||||
*
|
||||
*/
|
||||
const NetifUnicastAddress *GetUnicastAddresses(void) const;
|
||||
|
||||
/**
|
||||
* This method adds a unicast address to the network interface.
|
||||
*
|
||||
* @param[in] aAddress A reference to the unicast address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully added the unicast address.
|
||||
* @retval kThreadError_Busy The unicast address was already added.
|
||||
*
|
||||
*/
|
||||
ThreadError AddUnicastAddress(NetifUnicastAddress &aAddress);
|
||||
|
||||
/**
|
||||
* This method removes a unicast address from the network interface.
|
||||
*
|
||||
* @param[in] aAddress A reference to the unicast address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully removed the unicast address.
|
||||
* @retval kThreadError_Busy The unicast address was already removed.
|
||||
*
|
||||
*/
|
||||
ThreadError RemoveUnicastAddress(const NetifUnicastAddress &aAddress);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the network interface is subscribed to a multicast address.
|
||||
*
|
||||
* @param[in] aAddress The multicast address to check.
|
||||
*
|
||||
* @retval TRUE If the network interface is subscribed to @p aAddress.
|
||||
* @retval FALSE If the network interface is not subscribed to @p aAddress.
|
||||
*
|
||||
*/
|
||||
bool IsMulticastSubscribed(const Address &aAddress) const;
|
||||
|
||||
/**
|
||||
* This method subscribes the network interface to the link-local and realm-local all routers address.
|
||||
*
|
||||
*/
|
||||
void SubscribeAllRoutersMulticast(void);
|
||||
|
||||
/**
|
||||
* This method unsubscribes the network interface to the link-local and realm-local all routers address.
|
||||
*
|
||||
*/
|
||||
void UnsubscribeAllRoutersMulticast(void);
|
||||
|
||||
/**
|
||||
* This method subscribes the network interface to a multicast address.
|
||||
*
|
||||
* @param[in] aAddress A reference to the multicast address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully subscribed to @p aAddress.
|
||||
* @retval kThreadError_Busy The multicast address is already subscribed.
|
||||
*
|
||||
*/
|
||||
ThreadError SubscribeMulticast(NetifMulticastAddress &aAddress);
|
||||
|
||||
/**
|
||||
* This method unsubscribes the network interface to a multicast address.
|
||||
*
|
||||
* @param[in] aAddress A reference to the multicast address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully unsubscribed to @p aAddress.
|
||||
* @retval kThreadError_Busy The multicast address is already unsubscribed.
|
||||
*
|
||||
*/
|
||||
ThreadError UnsubscribeMulticast(const NetifMulticastAddress &aAddress);
|
||||
|
||||
/**
|
||||
* This method registers a network interface handler.
|
||||
*
|
||||
* @param[in] aHandler A reference to the handler.
|
||||
*
|
||||
* @retval kThreadError_None Successfully registered the handler.
|
||||
* @retval kThreadError_Busy The handler was already registered.
|
||||
*/
|
||||
ThreadError RegisterHandler(NetifHandler &aHandler);
|
||||
|
||||
/**
|
||||
* This virtual method enqueues an IPv6 messages on this network interface.
|
||||
*
|
||||
* @param[in] aMessage A reference to the IPv6 message.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the IPv6 message.
|
||||
*
|
||||
*/
|
||||
virtual ThreadError SendMessage(Message &aMessage) = 0;
|
||||
|
||||
/**
|
||||
* This virtual method returns a NULL-termianted string that names the network interface.
|
||||
*
|
||||
* @returns A NULL-terminated string that names the network interface.
|
||||
*
|
||||
*/
|
||||
virtual const char *GetName(void) const = 0;
|
||||
|
||||
/**
|
||||
* This virtual method fills out @p aAddress with the link address.
|
||||
*
|
||||
* @param[out] aAddress A reference to the link address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully retrieved the link address.
|
||||
*
|
||||
*/
|
||||
virtual ThreadError GetLinkAddress(LinkAddress &aAddress) const = 0;
|
||||
|
||||
/**
|
||||
* This virtual method performs a source-destination route lookup.
|
||||
*
|
||||
* @param[in] aSource A reference to the IPv6 source address.
|
||||
* @param[in] aDestination A reference to the IPv6 destinationa ddress.
|
||||
* @param[out] aPrefixMatch The longest prefix match result.
|
||||
*
|
||||
* @retval kThreadError_None Successfully found a route.
|
||||
* @retval kThreadError_NoRoute No route to destination.
|
||||
*
|
||||
*/
|
||||
virtual ThreadError RouteLookup(const Address &aSource, const Address &aDestination,
|
||||
uint8_t *aPrefixMatch) = 0;
|
||||
|
||||
/**
|
||||
* This static method returns the network interface list.
|
||||
*
|
||||
* @returns A pointer to the network interface list.
|
||||
*
|
||||
*/
|
||||
static Netif *GetNetifList(void);
|
||||
|
||||
/**
|
||||
* This static method returns the network interface identified by @p aInterfaceId.
|
||||
*
|
||||
* @param[in] aInterfaceId The network interface ID.
|
||||
*
|
||||
* @returns A pointer to the network interface or NULL if none is found.
|
||||
*
|
||||
*/
|
||||
static Netif *GetNetifById(uint8_t aInterfaceId);
|
||||
|
||||
/**
|
||||
* This static method returns the network interface identified by @p aName.
|
||||
*
|
||||
* @param[in] aName A pointer to a NULL-terminated string.
|
||||
*
|
||||
* @returns A pointer to the network interface or NULL if none is found.
|
||||
*
|
||||
*/
|
||||
static Netif *GetNetifByName(char *aName);
|
||||
|
||||
/**
|
||||
* This static method indicates whether or not @p aAddress is assigned to a network interfacfe.
|
||||
*
|
||||
* @param[in] aAddress A reference to the IPv6 address.
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is assigned to a network interface.
|
||||
* @retval FALSE If the IPv6 address is not assigned to any network interface.
|
||||
*
|
||||
*/
|
||||
static bool IsUnicastAddress(const Address &aAddress);
|
||||
|
||||
/**
|
||||
* This static method perform default source address selection.
|
||||
*
|
||||
* @param[in] aMessageInfo A reference to the message information.
|
||||
*
|
||||
* @returns A pointer to the selected IPv6 source address or NULL if no source address was found.
|
||||
*
|
||||
*/
|
||||
static const NetifUnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This static method determines which network interface @p aAddress is on-link, if any.
|
||||
*
|
||||
* @param[in] aAddress A reference to the IPv6 address.
|
||||
*
|
||||
* @returns The network interafce identifier for the on-link interface or -1 if none is found.
|
||||
*
|
||||
*/
|
||||
static int GetOnLinkNetif(const Address &aAddress);
|
||||
|
||||
private:
|
||||
static void HandleUnicastChangedTask(void *aContext);
|
||||
void HandleUnicastChangedTask(void);
|
||||
|
||||
NetifHandler *mHandlers;
|
||||
NetifUnicastAddress *mUnicastAddresses;
|
||||
NetifMulticastAddress *mMulticastAddresses;
|
||||
int mInterfaceId;
|
||||
bool mAllRoutersSubscribed;
|
||||
Tasklet mUnicastChangedTask;
|
||||
Netif *mNext;
|
||||
|
||||
static Netif *sNetifListHead;
|
||||
static int sNextInterfaceId;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NET_NETIF_HPP_
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for IPv6 sockets.
|
||||
*/
|
||||
|
||||
#ifndef NET_SOCKET_HPP_
|
||||
#define NET_SOCKET_HPP_
|
||||
|
||||
#include <openthread.h>
|
||||
#include <net/ip6_address.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
/**
|
||||
* @addtogroup core-ip6-ip6
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements message information for an IPv6 message.
|
||||
*
|
||||
*/
|
||||
class MessageInfo: public otMessageInfo
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method returns a reference to the local socket address.
|
||||
*
|
||||
* @returns A reference to the local socket address.
|
||||
*
|
||||
*/
|
||||
Address &GetSockAddr(void) { return *static_cast<Address *>(&mSockAddr);}
|
||||
|
||||
/**
|
||||
* This method returns a reference to the local socket address.
|
||||
*
|
||||
* @returns A reference to the local socket address.
|
||||
*
|
||||
*/
|
||||
const Address &GetSockAddr(void) const { return *static_cast<const Address *>(&mSockAddr);}
|
||||
|
||||
/**
|
||||
* This method returns a reference to the peer socket address.
|
||||
*
|
||||
* @returns A reference to the peer socket address.
|
||||
*
|
||||
*/
|
||||
Address &GetPeerAddr(void) { return *static_cast<Address *>(&mPeerAddr);}
|
||||
|
||||
/**
|
||||
* This method returns a reference to the peer socket address.
|
||||
*
|
||||
* @returns A reference to the peer socket address.
|
||||
*
|
||||
*/
|
||||
const Address &GetPeerAddr(void) const { return *static_cast<const Address *>(&mPeerAddr);}
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements a socket address.
|
||||
*
|
||||
*/
|
||||
class SockAddr: public otSockAddr
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
*/
|
||||
SockAddr(void) { memset(&mAddress, 0, sizeof(mAddress)), mPort = 0, mScopeId = 0; }
|
||||
|
||||
/**
|
||||
* This method returns a reference to the IPv6 address.
|
||||
*
|
||||
* @returns A reference to the IPv6 address.
|
||||
*
|
||||
*/
|
||||
Address &GetAddress(void) { return *static_cast<Address *>(&mAddress); }
|
||||
|
||||
/**
|
||||
* This method returns a reference to the IPv6 address.
|
||||
*
|
||||
* @returns A reference to the IPv6 address.
|
||||
*
|
||||
*/
|
||||
const Address &GetAddress(void) const { return *static_cast<const Address *>(&mAddress); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NET_SOCKET_HPP_
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements UDP/IPv6 sockets.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/encoding.hpp>
|
||||
#include <net/ip6.hpp>
|
||||
#include <net/udp6.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
UdpSocket *Udp::sSockets = NULL;
|
||||
uint16_t Udp::sEphemeralPort = kDynamicPortMin;
|
||||
|
||||
ThreadError UdpSocket::Open(otUdpReceive aHandler, void *aContext)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
for (UdpSocket *cur = Udp::sSockets; cur; cur = cur->GetNext())
|
||||
{
|
||||
if (cur == this)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
memset(&mSockName, 0, sizeof(mSockName));
|
||||
memset(&mPeerName, 0, sizeof(mPeerName));
|
||||
mHandler = aHandler;
|
||||
mContext = aContext;
|
||||
|
||||
SetNext(Udp::sSockets);
|
||||
Udp::sSockets = this;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError UdpSocket::Bind(const SockAddr &aSockAddr)
|
||||
{
|
||||
mSockName = aSockAddr;
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError UdpSocket::Close(void)
|
||||
{
|
||||
if (Udp::sSockets == this)
|
||||
{
|
||||
Udp::sSockets = Udp::sSockets->GetNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (UdpSocket *socket = Udp::sSockets; socket; socket = socket->GetNext())
|
||||
{
|
||||
if (socket->GetNext() == this)
|
||||
{
|
||||
socket->SetNext(GetNext());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset(&mSockName, 0, sizeof(mSockName));
|
||||
memset(&mPeerName, 0, sizeof(mPeerName));
|
||||
SetNext(NULL);
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError UdpSocket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
MessageInfo messageInfoLocal;
|
||||
UdpHeader udpHeader;
|
||||
|
||||
messageInfoLocal = aMessageInfo;
|
||||
|
||||
if (messageInfoLocal.GetSockAddr().IsUnspecified())
|
||||
{
|
||||
messageInfoLocal.GetSockAddr() = GetSockName().GetAddress();
|
||||
}
|
||||
|
||||
if (GetSockName().mPort == 0)
|
||||
{
|
||||
GetSockName().mPort = Udp::sEphemeralPort;
|
||||
|
||||
if (Udp::sEphemeralPort < Udp::kDynamicPortMax)
|
||||
{
|
||||
Udp::sEphemeralPort++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Udp::sEphemeralPort = Udp::kDynamicPortMin;
|
||||
}
|
||||
}
|
||||
|
||||
udpHeader.SetSourcePort(GetSockName().mPort);
|
||||
udpHeader.SetDestinationPort(messageInfoLocal.mPeerPort);
|
||||
udpHeader.SetLength(sizeof(udpHeader) + aMessage.GetLength());
|
||||
udpHeader.SetChecksum(0);
|
||||
|
||||
SuccessOrExit(error = aMessage.Prepend(&udpHeader, sizeof(udpHeader)));
|
||||
aMessage.SetOffset(0);
|
||||
SuccessOrExit(error = Ip6::SendDatagram(aMessage, messageInfoLocal, kProtoUdp));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Message *Udp::NewMessage(uint16_t aReserved)
|
||||
{
|
||||
return Ip6::NewMessage(sizeof(UdpHeader) + aReserved);
|
||||
}
|
||||
|
||||
ThreadError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
UdpHeader udpHeader;
|
||||
uint16_t payloadLength;
|
||||
uint16_t checksum;
|
||||
|
||||
payloadLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
|
||||
// check length
|
||||
VerifyOrExit(payloadLength >= sizeof(UdpHeader), error = kThreadError_Parse);
|
||||
|
||||
// verify checksum
|
||||
checksum = Ip6::ComputePseudoheaderChecksum(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(),
|
||||
payloadLength, kProtoUdp);
|
||||
checksum = aMessage.UpdateChecksum(checksum, aMessage.GetOffset(), payloadLength);
|
||||
VerifyOrExit(checksum == 0xffff, ;);
|
||||
|
||||
aMessage.Read(aMessage.GetOffset(), sizeof(udpHeader), &udpHeader);
|
||||
aMessage.MoveOffset(sizeof(udpHeader));
|
||||
aMessageInfo.mPeerPort = udpHeader.GetSourcePort();
|
||||
aMessageInfo.mSockPort = udpHeader.GetDestinationPort();
|
||||
|
||||
// find socket
|
||||
for (UdpSocket *socket = Udp::sSockets; socket; socket = socket->GetNext())
|
||||
{
|
||||
if (socket->GetSockName().mPort != udpHeader.GetDestinationPort())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (socket->GetSockName().mScopeId != 0 &&
|
||||
socket->GetSockName().mScopeId != aMessageInfo.mInterfaceId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!aMessageInfo.GetSockAddr().IsMulticast() &&
|
||||
!socket->GetSockName().GetAddress().IsUnspecified() &&
|
||||
socket->GetSockName().GetAddress() != aMessageInfo.GetSockAddr())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// verify source if connected socket
|
||||
if (socket->GetPeerName().mPort != 0)
|
||||
{
|
||||
if (socket->GetPeerName().mPort != udpHeader.GetSourcePort())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!socket->GetPeerName().GetAddress().IsUnspecified() &&
|
||||
socket->GetPeerName().GetAddress() != aMessageInfo.GetPeerAddr())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
socket->HandleUdpReceive(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Udp::UpdateChecksum(Message &aMessage, uint16_t aChecksum)
|
||||
{
|
||||
aChecksum = aMessage.UpdateChecksum(aChecksum, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset());
|
||||
|
||||
if (aChecksum != 0xffff)
|
||||
{
|
||||
aChecksum = ~aChecksum;
|
||||
}
|
||||
|
||||
aChecksum = HostSwap16(aChecksum);
|
||||
aMessage.Write(aMessage.GetOffset() + UdpHeader::GetChecksumOffset(), sizeof(aChecksum), &aChecksum);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for UDP/IPv6 sockets.
|
||||
*/
|
||||
|
||||
#ifndef UDP6_HPP_
|
||||
#define UDP6_HPP_
|
||||
|
||||
#include <openthread.h>
|
||||
#include <net/ip6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Ip6 {
|
||||
|
||||
/**
|
||||
* @addtogroup core-udp
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for UDP/IPv6 sockets.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements a UDP/IPv6 socket.
|
||||
*
|
||||
*/
|
||||
class UdpSocket: public otUdpSocket
|
||||
{
|
||||
friend class Udp;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This method opens the UDP socket.
|
||||
*
|
||||
* @param[in] aHandler A pointer to a function that is called when receiving UDP messages.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
* @retval kThreadError_None Successfully opened the socket.
|
||||
* @retval kThreadError_Busy The socket is already open.
|
||||
*
|
||||
*/
|
||||
ThreadError Open(otUdpReceive aHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* This method binds the UDP socket.
|
||||
*
|
||||
* @param[in] aSockAddr A reference to the socket address.
|
||||
*
|
||||
* @retval kThreadError_None Successfully bound the socket.
|
||||
*
|
||||
*/
|
||||
ThreadError Bind(const SockAddr &aSockAddr);
|
||||
|
||||
/**
|
||||
* This method closes the UDP socket.
|
||||
*
|
||||
* @retval kThreadError_None Successfully closed the UDP socket.
|
||||
* @retval kThreadErrorBusy The socket is already closed.
|
||||
*
|
||||
*/
|
||||
ThreadError Close(void);
|
||||
|
||||
/**
|
||||
* This method sends a UDP message.
|
||||
*
|
||||
* @param[in] aMessage The message to send.
|
||||
* @param[in] aMessageInfo The message info associated with @p aMessage.
|
||||
*
|
||||
* @retval kThreadError_None Successfully sent the UDP messag.
|
||||
* @retval kThreadError_NoBufs Insufficient available buffer to add the UDP and IPv6 headers.
|
||||
*
|
||||
*/
|
||||
ThreadError SendTo(Message &aMessage, const MessageInfo &aMessageInfo);
|
||||
|
||||
private:
|
||||
UdpSocket *GetNext(void) { return static_cast<UdpSocket *>(mNext); }
|
||||
void SetNext(UdpSocket *socket) { mNext = static_cast<otUdpSocket *>(socket); }
|
||||
|
||||
SockAddr &GetSockName(void) { return *static_cast<SockAddr *>(&mSockName); }
|
||||
SockAddr &GetPeerName(void) { return *static_cast<SockAddr *>(&mPeerName); }
|
||||
|
||||
void HandleUdpReceive(Message &aMessage, const MessageInfo &aMessageInfo) {
|
||||
mHandler(mContext, &aMessage, &aMessageInfo);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements core UDP message handling.
|
||||
*
|
||||
*/
|
||||
class Udp
|
||||
{
|
||||
friend class UdpSocket;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This static method returns a new UDP message with sufficient header space reserved.
|
||||
*
|
||||
* @param[in] aReserved The number of header bytes to reserve after the UDP header.
|
||||
*
|
||||
* @returns A pointer to the message or NULL if no buffers are available.
|
||||
*
|
||||
*/
|
||||
static Message *NewMessage(uint16_t aReserved);
|
||||
|
||||
/**
|
||||
* This static method handles a received UDP message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the UDP message to process.
|
||||
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
|
||||
*
|
||||
* @retval kThreadError_None Successfully processed the UDP message.
|
||||
* @retval kThreadError_Drop Could not fully process the UDP message.
|
||||
*
|
||||
*/
|
||||
static ThreadError HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This static method updates the UDP checksum.
|
||||
*
|
||||
* @param[in] aMessage A reference to the UDP message.
|
||||
* @param[in] aPseudoHeaderChecksum The pseudo-header checksum value.
|
||||
*
|
||||
* @retval kThreadError_None Successfully updated the UDP checksum.
|
||||
* @retval kThreadError_InvalidArgs The message was invalid.
|
||||
*
|
||||
*/
|
||||
static ThreadError UpdateChecksum(Message &aMessage, uint16_t aPseudoHeaderChecksum);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kDynamicPortMin = 49152, ///< Service Name and Transport Protocol Port Number Registry
|
||||
kDynamicPortMax = 65535, ///< Service Name and Transport Protocol Port Number Registry
|
||||
};
|
||||
static uint16_t sEphemeralPort;
|
||||
static UdpSocket *sSockets;
|
||||
};
|
||||
|
||||
struct UdpHeaderPoD
|
||||
{
|
||||
uint16_t mSource;
|
||||
uint16_t mDestination;
|
||||
uint16_t mLength;
|
||||
uint16_t mChecksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* This class implements UDP header generation and parsing.
|
||||
*
|
||||
*/
|
||||
class UdpHeader: private UdpHeaderPoD
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method returns the UDP Source Port.
|
||||
*
|
||||
* @returns The UDP Source Port.
|
||||
*
|
||||
*/
|
||||
uint16_t GetSourcePort(void) const { return HostSwap16(mSource); }
|
||||
|
||||
/**
|
||||
* This method sets the UDP Source Port.
|
||||
*
|
||||
* @param[in] aPort The UDP Source Port.
|
||||
*
|
||||
*/
|
||||
void SetSourcePort(uint16_t aPort) { mSource = HostSwap16(aPort); }
|
||||
|
||||
/**
|
||||
* This method returns the UDP Destination Port.
|
||||
*
|
||||
* @returns The UDP Destination Port.
|
||||
*
|
||||
*/
|
||||
uint16_t GetDestinationPort(void) const { return HostSwap16(mDestination); }
|
||||
|
||||
/**
|
||||
* This method sets the UDP Destination Port.
|
||||
*
|
||||
* @param[in] aPort The UDP Destination Port.
|
||||
*
|
||||
*/
|
||||
void SetDestinationPort(uint16_t aPort) { mDestination = HostSwap16(aPort); }
|
||||
|
||||
/**
|
||||
* This method returns the UDP Length.
|
||||
*
|
||||
* @returns The UDP Length.
|
||||
*
|
||||
*/
|
||||
uint16_t GetLength(void) const { return HostSwap16(mLength); }
|
||||
|
||||
/**
|
||||
* This method sets the UDP Length.
|
||||
*
|
||||
* @param[in] aLength The UDP Length.
|
||||
*
|
||||
*/
|
||||
void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
|
||||
|
||||
/**
|
||||
* This method returns the UDP Checksum.
|
||||
*
|
||||
* @returns The UDP Checksum.
|
||||
*
|
||||
*/
|
||||
uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
|
||||
|
||||
/**
|
||||
* This method sets the UDP Checksum.
|
||||
*
|
||||
* @param[in] aChecksum The UDP Checksum.
|
||||
*
|
||||
*/
|
||||
void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset for the UDP Length.
|
||||
*
|
||||
* @returns The byte offset for the UDP Length.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetLengthOffset(void) { return offsetof(UdpHeaderPoD, mLength); }
|
||||
|
||||
/**
|
||||
* This static method returns the byte offset for the UDP Checksum.
|
||||
*
|
||||
* @returns The byte offset for the UDP Checksum.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetChecksumOffset(void) { return offsetof(UdpHeaderPoD, mChecksum); }
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
} // namespace Ip6
|
||||
} // namespace Thread
|
||||
|
||||
#endif // NET_UDP6_HPP_
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes compile-time configuration constants for OpenThread.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_CORE_CONFIG_H_
|
||||
#define OPENTHREAD_CORE_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS
|
||||
*
|
||||
* The number of message buffers in the buffer pool.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS
|
||||
#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 64
|
||||
#endif // OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE
|
||||
*
|
||||
* The size of a message buffer in bytes.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE
|
||||
#define OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE 128
|
||||
#endif // OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_DEFAULT_CHANNEL
|
||||
*
|
||||
* The default IEEE 802.15.4 channel.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_DEFAULT_CHANNEL
|
||||
#define OPENTHREAD_CONFIG_DEFAULT_CHANNEL 11
|
||||
#endif // OPENTHREAD_CONFIG_DEFAULT_CHANNEL
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ATTACH_DATA_POLL_PERIOD
|
||||
*
|
||||
* The Data Poll period during attach in milliseconds.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ATTACH_DATA_POLL_PERIOD
|
||||
#define OPENTHREAD_CONFIG_ATTACH_DATA_POLL_PERIOD 100
|
||||
#endif // OPENTHREAD_CONFIG_ATTACH_DATA_POLL_PERIOD
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ADDRESS_CACHE_ENTRIES
|
||||
*
|
||||
* The number of EID-to-RLOC cache entries.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ADDRESS_CACHE_ENTRIES
|
||||
#define OPENTHREAD_CONFIG_ADDRESS_CACHE_ENTRIES 8
|
||||
#endif // OPENTHREAD_CONFIG_ADDRESS_CACHE_ENTRIES
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MAX_CHILDREN
|
||||
*
|
||||
* The maximum number of children.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MAX_CHILDREN
|
||||
#define OPENTHREAD_CONFIG_MAX_CHILDREN 5
|
||||
#endif // OPENTHREAD_CONFIG_MAX_CHILDREN
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_IP_ADDRS_PER_CHILD
|
||||
*
|
||||
* The minimum number of supported IPv6 address registrations per child.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_IP_ADDRS_PER_CHILD
|
||||
#define OPENTHREAD_CONFIG_IP_ADDRS_PER_CHILD 4
|
||||
#endif // OPENTHREAD_CONFIG_IP_ADDRS_PER_CHILD
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT
|
||||
*
|
||||
* The 6LoWPAN fragment reassembly timeout in seconds.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT
|
||||
#define OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT 5
|
||||
#endif // OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES
|
||||
*
|
||||
* The number of MPL cache entries for duplicate detection.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES
|
||||
#define OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES 32
|
||||
#endif // OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME
|
||||
*
|
||||
* The MPL cache entry lifetime in seconds.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME
|
||||
#define OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME 5
|
||||
#endif // OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_LEVEL
|
||||
*
|
||||
* The log level.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_LOG_LEVEL
|
||||
#define OPENTHREAD_CONFIG_LOG_LEVEL OPENTHREAD_LOG_LEVEL_CRIT
|
||||
#endif // OPENTHREAD_CONFIG_LOG_LEVEL
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_API
|
||||
*
|
||||
* Define to enable OpenThread API logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_API
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_MLE
|
||||
*
|
||||
* Define to enable MLE logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_MLE
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_ARP
|
||||
*
|
||||
* Define to enable EID-to-RLOC map logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_ARP
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_NETDATA
|
||||
*
|
||||
* Define to enable Network Data logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_NETDATA
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_ICMP
|
||||
*
|
||||
* Define to enable ICMPv6 logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_ICMP
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_IP6
|
||||
*
|
||||
* Define to enable IPv6 logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_IP6
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_MAC
|
||||
*
|
||||
* Define to enable IEEE 802.15.4 MAC logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_MAC
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_MEM
|
||||
*
|
||||
* Define to enable memory logging.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_LOG_MEM
|
||||
|
||||
#endif // OPENTHREAD_CORE_CONFIG_H_
|
||||
|
||||
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the top-level interface to the OpenThread stack.
|
||||
*/
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <openthread.h>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <common/message.hpp>
|
||||
#include <common/tasklet.hpp>
|
||||
#include <common/timer.hpp>
|
||||
#include <platform/random.h>
|
||||
#include <thread/thread_netif.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
// Allocate the structure using "raw" storage.
|
||||
#define otDEFINE_ALIGNED_VAR(name, size, align_type) \
|
||||
align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))]
|
||||
|
||||
static otDEFINE_ALIGNED_VAR(sThreadNetifRaw, sizeof(ThreadNetif), uint64_t);
|
||||
|
||||
static ThreadNetif *sThreadNetif;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void otInit()
|
||||
{
|
||||
otLogInfoApi("Init\n");
|
||||
Message::Init();
|
||||
sThreadNetif = new(&sThreadNetifRaw) ThreadNetif;
|
||||
}
|
||||
|
||||
void otProcessNextTasklet(void)
|
||||
{
|
||||
TaskletScheduler::RunNextTasklet();
|
||||
}
|
||||
|
||||
bool otAreTaskletsPending(void)
|
||||
{
|
||||
return TaskletScheduler::AreTaskletsPending();
|
||||
}
|
||||
|
||||
uint8_t otGetChannel(void)
|
||||
{
|
||||
return sThreadNetif->GetMac().GetChannel();
|
||||
}
|
||||
|
||||
ThreadError otSetChannel(uint8_t aChannel)
|
||||
{
|
||||
return sThreadNetif->GetMac().SetChannel(aChannel);
|
||||
}
|
||||
|
||||
uint32_t otGetChildTimeout(void)
|
||||
{
|
||||
return sThreadNetif->GetMle().GetTimeout();
|
||||
}
|
||||
|
||||
void otSetChildTimeout(uint32_t aTimeout)
|
||||
{
|
||||
sThreadNetif->GetMle().SetTimeout(aTimeout);
|
||||
}
|
||||
|
||||
const uint8_t *otGetExtendedAddress(void)
|
||||
{
|
||||
return reinterpret_cast<const uint8_t *>(sThreadNetif->GetMac().GetExtAddress());
|
||||
}
|
||||
|
||||
const uint8_t *otGetExtendedPanId(void)
|
||||
{
|
||||
return sThreadNetif->GetMac().GetExtendedPanId();
|
||||
}
|
||||
|
||||
void otSetExtendedPanId(const uint8_t *aExtendedPanId)
|
||||
{
|
||||
sThreadNetif->GetMac().SetExtendedPanId(aExtendedPanId);
|
||||
}
|
||||
|
||||
otLinkModeConfig otGetLinkMode(void)
|
||||
{
|
||||
otLinkModeConfig config = {};
|
||||
uint8_t mode = sThreadNetif->GetMle().GetDeviceMode();
|
||||
|
||||
if (mode & Mle::ModeTlv::kModeRxOnWhenIdle)
|
||||
{
|
||||
config.mRxOnWhenIdle = 1;
|
||||
}
|
||||
|
||||
if (mode & Mle::ModeTlv::kModeSecureDataRequest)
|
||||
{
|
||||
config.mSecureDataRequests = 1;
|
||||
}
|
||||
|
||||
if (mode & Mle::ModeTlv::kModeFFD)
|
||||
{
|
||||
config.mDeviceType = 1;
|
||||
}
|
||||
|
||||
if (mode & Mle::ModeTlv::kModeFullNetworkData)
|
||||
{
|
||||
config.mNetworkData = 1;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
ThreadError otSetLinkMode(otLinkModeConfig aConfig)
|
||||
{
|
||||
uint8_t mode = 0;
|
||||
|
||||
if (aConfig.mRxOnWhenIdle)
|
||||
{
|
||||
mode |= Mle::ModeTlv::kModeRxOnWhenIdle;
|
||||
}
|
||||
|
||||
if (aConfig.mSecureDataRequests)
|
||||
{
|
||||
mode |= Mle::ModeTlv::kModeSecureDataRequest;
|
||||
}
|
||||
|
||||
if (aConfig.mDeviceType)
|
||||
{
|
||||
mode |= Mle::ModeTlv::kModeFFD;
|
||||
}
|
||||
|
||||
if (aConfig.mNetworkData)
|
||||
{
|
||||
mode |= Mle::ModeTlv::kModeFullNetworkData;
|
||||
}
|
||||
|
||||
return sThreadNetif->GetMle().SetDeviceMode(mode);
|
||||
}
|
||||
|
||||
const uint8_t *otGetMasterKey(uint8_t *aKeyLength)
|
||||
{
|
||||
return sThreadNetif->GetKeyManager().GetMasterKey(aKeyLength);
|
||||
}
|
||||
|
||||
ThreadError otSetMasterKey(const uint8_t *aKey, uint8_t aKeyLength)
|
||||
{
|
||||
return sThreadNetif->GetKeyManager().SetMasterKey(aKey, aKeyLength);
|
||||
}
|
||||
|
||||
const char *otGetNetworkName(void)
|
||||
{
|
||||
return sThreadNetif->GetMac().GetNetworkName();
|
||||
}
|
||||
|
||||
ThreadError otSetNetworkName(const char *aNetworkName)
|
||||
{
|
||||
return sThreadNetif->GetMac().SetNetworkName(aNetworkName);
|
||||
}
|
||||
|
||||
uint16_t otGetPanId(void)
|
||||
{
|
||||
return sThreadNetif->GetMac().GetPanId();
|
||||
}
|
||||
|
||||
ThreadError otSetPanId(uint16_t aPanId)
|
||||
{
|
||||
return sThreadNetif->GetMac().SetPanId(aPanId);
|
||||
}
|
||||
|
||||
uint8_t otGetLocalLeaderWeight(void)
|
||||
{
|
||||
return sThreadNetif->GetMle().GetLeaderWeight();
|
||||
}
|
||||
|
||||
void otSetLocalLeaderWeight(uint8_t aWeight)
|
||||
{
|
||||
sThreadNetif->GetMle().SetLeaderWeight(aWeight);
|
||||
}
|
||||
|
||||
ThreadError otAddBorderRouter(const otBorderRouterConfig *aConfig)
|
||||
{
|
||||
uint8_t flags = 0;
|
||||
|
||||
if (aConfig->mSlaacPreferred)
|
||||
{
|
||||
flags |= NetworkData::BorderRouterEntry::kPreferredFlag;
|
||||
}
|
||||
|
||||
if (aConfig->mSlaacValid)
|
||||
{
|
||||
flags |= NetworkData::BorderRouterEntry::kValidFlag;
|
||||
}
|
||||
|
||||
if (aConfig->mDhcp)
|
||||
{
|
||||
flags |= NetworkData::BorderRouterEntry::kDhcpFlag;
|
||||
}
|
||||
|
||||
if (aConfig->mConfigure)
|
||||
{
|
||||
flags |= NetworkData::BorderRouterEntry::kConfigureFlag;
|
||||
}
|
||||
|
||||
if (aConfig->mDefaultRoute)
|
||||
{
|
||||
flags |= NetworkData::BorderRouterEntry::kDefaultRouteFlag;
|
||||
}
|
||||
|
||||
return sThreadNetif->GetNetworkDataLocal().AddOnMeshPrefix(aConfig->mPrefix.mPrefix.m8, aConfig->mPrefix.mLength,
|
||||
aConfig->mPreference, flags, aConfig->mStable);
|
||||
}
|
||||
|
||||
ThreadError otRemoveBorderRouter(const otIp6Prefix *aPrefix)
|
||||
{
|
||||
return sThreadNetif->GetNetworkDataLocal().RemoveOnMeshPrefix(aPrefix->mPrefix.m8, aPrefix->mLength);
|
||||
}
|
||||
|
||||
ThreadError otAddExternalRoute(const otExternalRouteConfig *aConfig)
|
||||
{
|
||||
return sThreadNetif->GetNetworkDataLocal().AddHasRoutePrefix(aConfig->mPrefix.mPrefix.m8, aConfig->mPrefix.mLength,
|
||||
aConfig->mPreference, aConfig->mStable);
|
||||
}
|
||||
|
||||
ThreadError otRemoveExternalRoute(const otIp6Prefix *aPrefix)
|
||||
{
|
||||
return sThreadNetif->GetNetworkDataLocal().RemoveHasRoutePrefix(aPrefix->mPrefix.m8, aPrefix->mLength);
|
||||
}
|
||||
|
||||
ThreadError otSendServerData(void)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
sThreadNetif->GetMle().GetLeaderAddress(destination);
|
||||
return sThreadNetif->GetNetworkDataLocal().Register(destination);
|
||||
}
|
||||
|
||||
uint32_t otGetContextIdReuseDelay(void)
|
||||
{
|
||||
return sThreadNetif->GetNetworkDataLeader().GetContextIdReuseDelay();
|
||||
}
|
||||
|
||||
void otSetContextIdReuseDelay(uint32_t aDelay)
|
||||
{
|
||||
sThreadNetif->GetNetworkDataLeader().SetContextIdReuseDelay(aDelay);
|
||||
}
|
||||
|
||||
uint32_t otGetKeySequenceCounter(void)
|
||||
{
|
||||
return sThreadNetif->GetKeyManager().GetCurrentKeySequence();
|
||||
}
|
||||
|
||||
void otSetKeySequenceCounter(uint32_t aKeySequenceCounter)
|
||||
{
|
||||
sThreadNetif->GetKeyManager().SetCurrentKeySequence(aKeySequenceCounter);
|
||||
}
|
||||
|
||||
uint32_t otGetNetworkIdTimeout(void)
|
||||
{
|
||||
return sThreadNetif->GetMle().GetNetworkIdTimeout();
|
||||
}
|
||||
|
||||
void otSetNetworkIdTimeout(uint32_t aTimeout)
|
||||
{
|
||||
sThreadNetif->GetMle().SetNetworkIdTimeout(aTimeout);
|
||||
}
|
||||
|
||||
uint8_t otGetRouterUpgradeThreshold(void)
|
||||
{
|
||||
return sThreadNetif->GetMle().GetRouterUpgradeThreshold();
|
||||
}
|
||||
|
||||
void otSetRouterUpgradeThreshold(uint8_t aThreshold)
|
||||
{
|
||||
sThreadNetif->GetMle().SetRouterUpgradeThreshold(aThreshold);
|
||||
}
|
||||
|
||||
ThreadError otReleaseRouterId(uint8_t aRouterId)
|
||||
{
|
||||
return sThreadNetif->GetMle().ReleaseRouterId(aRouterId);
|
||||
}
|
||||
|
||||
ThreadError otAddMacWhitelist(const uint8_t *aExtAddr)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
if (sThreadNetif->GetMac().GetWhitelist().Add(*reinterpret_cast<const Mac::ExtAddress *>(aExtAddr)) == NULL)
|
||||
{
|
||||
error = kThreadError_NoBufs;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otAddMacWhitelistRssi(const uint8_t *aExtAddr, int8_t aRssi)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Thread::Mac::Whitelist::Entry *entry;
|
||||
|
||||
entry = sThreadNetif->GetMac().GetWhitelist().Add(*reinterpret_cast<const Mac::ExtAddress *>(aExtAddr));
|
||||
VerifyOrExit(entry != NULL, error = kThreadError_NoBufs);
|
||||
sThreadNetif->GetMac().GetWhitelist().SetConstantRssi(*entry, aRssi);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void otRemoveMacWhitelist(const uint8_t *aExtAddr)
|
||||
{
|
||||
sThreadNetif->GetMac().GetWhitelist().Remove(*reinterpret_cast<const Mac::ExtAddress *>(aExtAddr));
|
||||
}
|
||||
|
||||
void otClearMacWhitelist()
|
||||
{
|
||||
sThreadNetif->GetMac().GetWhitelist().Clear();
|
||||
}
|
||||
|
||||
void otDisableMacWhitelist()
|
||||
{
|
||||
sThreadNetif->GetMac().GetWhitelist().Disable();
|
||||
}
|
||||
|
||||
void otEnableMacWhitelist()
|
||||
{
|
||||
sThreadNetif->GetMac().GetWhitelist().Enable();
|
||||
}
|
||||
|
||||
ThreadError otBecomeDetached()
|
||||
{
|
||||
return sThreadNetif->GetMle().BecomeDetached();
|
||||
}
|
||||
|
||||
ThreadError otBecomeChild(otMleAttachFilter aFilter)
|
||||
{
|
||||
return sThreadNetif->GetMle().BecomeChild(aFilter);
|
||||
}
|
||||
|
||||
ThreadError otBecomeRouter()
|
||||
{
|
||||
return sThreadNetif->GetMle().BecomeRouter();
|
||||
}
|
||||
|
||||
ThreadError otBecomeLeader()
|
||||
{
|
||||
return sThreadNetif->GetMle().BecomeLeader();
|
||||
}
|
||||
|
||||
otDeviceRole otGetDeviceRole()
|
||||
{
|
||||
otDeviceRole rval = kDeviceRoleDisabled;
|
||||
|
||||
switch (sThreadNetif->GetMle().GetDeviceState())
|
||||
{
|
||||
case Mle::kDeviceStateDisabled:
|
||||
rval = kDeviceRoleDisabled;
|
||||
break;
|
||||
|
||||
case Mle::kDeviceStateDetached:
|
||||
rval = kDeviceRoleDetached;
|
||||
break;
|
||||
|
||||
case Mle::kDeviceStateChild:
|
||||
rval = kDeviceRoleChild;
|
||||
break;
|
||||
|
||||
case Mle::kDeviceStateRouter:
|
||||
rval = kDeviceRoleRouter;
|
||||
break;
|
||||
|
||||
case Mle::kDeviceStateLeader:
|
||||
rval = kDeviceRoleLeader;
|
||||
break;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint8_t otGetLeaderRouterId()
|
||||
{
|
||||
return sThreadNetif->GetMle().GetLeaderDataTlv().GetLeaderRouterId();
|
||||
}
|
||||
|
||||
uint8_t otGetLeaderWeight()
|
||||
{
|
||||
return sThreadNetif->GetMle().GetLeaderDataTlv().GetWeighting();
|
||||
}
|
||||
|
||||
uint8_t otGetNetworkDataVersion()
|
||||
{
|
||||
return sThreadNetif->GetMle().GetLeaderDataTlv().GetDataVersion();
|
||||
}
|
||||
|
||||
uint32_t otGetPartitionId()
|
||||
{
|
||||
return sThreadNetif->GetMle().GetLeaderDataTlv().GetPartitionId();
|
||||
}
|
||||
|
||||
uint16_t otGetRloc16(void)
|
||||
{
|
||||
return sThreadNetif->GetMle().GetRloc16();
|
||||
}
|
||||
|
||||
uint8_t otGetRouterIdSequence()
|
||||
{
|
||||
return sThreadNetif->GetMle().GetRouterIdSequence();
|
||||
}
|
||||
|
||||
uint8_t otGetStableNetworkDataVersion()
|
||||
{
|
||||
return sThreadNetif->GetMle().GetLeaderDataTlv().GetStableDataVersion();
|
||||
}
|
||||
|
||||
bool otIsIp6AddressEqual(const otIp6Address *a, const otIp6Address *b)
|
||||
{
|
||||
return *static_cast<const Ip6::Address *>(a) == *static_cast<const Ip6::Address *>(b);
|
||||
}
|
||||
|
||||
ThreadError otIp6AddressFromString(const char *str, otIp6Address *address)
|
||||
{
|
||||
return static_cast<Ip6::Address *>(address)->FromString(str);
|
||||
}
|
||||
|
||||
const otNetifAddress *otGetUnicastAddresses()
|
||||
{
|
||||
return sThreadNetif->GetUnicastAddresses();
|
||||
}
|
||||
|
||||
ThreadError otAddUnicastAddress(otNetifAddress *address)
|
||||
{
|
||||
return sThreadNetif->AddUnicastAddress(*static_cast<Ip6::NetifUnicastAddress *>(address));
|
||||
}
|
||||
|
||||
ThreadError otRemoveUnicastAddress(otNetifAddress *address)
|
||||
{
|
||||
return sThreadNetif->RemoveUnicastAddress(*static_cast<Ip6::NetifUnicastAddress *>(address));
|
||||
}
|
||||
|
||||
ThreadError otEnable(void)
|
||||
{
|
||||
return sThreadNetif->Up();
|
||||
}
|
||||
|
||||
ThreadError otDisable(void)
|
||||
{
|
||||
return sThreadNetif->Down();
|
||||
}
|
||||
|
||||
otMessage otNewUdpMessage()
|
||||
{
|
||||
return Ip6::Udp::NewMessage(0);
|
||||
}
|
||||
|
||||
ThreadError otFreeMessage(otMessage aMessage)
|
||||
{
|
||||
return Message::Free(*static_cast<Message *>(aMessage));
|
||||
}
|
||||
|
||||
uint16_t otGetMessageLength(otMessage aMessage)
|
||||
{
|
||||
Message *message = static_cast<Message *>(aMessage);
|
||||
return message->GetLength();
|
||||
}
|
||||
|
||||
ThreadError otSetMessageLength(otMessage aMessage, uint16_t aLength)
|
||||
{
|
||||
Message *message = static_cast<Message *>(aMessage);
|
||||
return message->SetLength(aLength);
|
||||
}
|
||||
|
||||
uint16_t otGetMessageOffset(otMessage aMessage)
|
||||
{
|
||||
Message *message = static_cast<Message *>(aMessage);
|
||||
return message->GetOffset();
|
||||
}
|
||||
|
||||
ThreadError otSetMessageOffset(otMessage aMessage, uint16_t aOffset)
|
||||
{
|
||||
Message *message = static_cast<Message *>(aMessage);
|
||||
return message->SetOffset(aOffset);
|
||||
}
|
||||
|
||||
int otAppendMessage(otMessage aMessage, const void *aBuf, uint16_t aLength)
|
||||
{
|
||||
Message *message = static_cast<Message *>(aMessage);
|
||||
return message->Append(aBuf, aLength);
|
||||
}
|
||||
|
||||
int otReadMessage(otMessage aMessage, uint16_t aOffset, void *aBuf, uint16_t aLength)
|
||||
{
|
||||
Message *message = static_cast<Message *>(aMessage);
|
||||
return message->Read(aOffset, aLength, aBuf);
|
||||
}
|
||||
|
||||
int otWriteMessage(otMessage aMessage, uint16_t aOffset, const void *aBuf, uint16_t aLength)
|
||||
{
|
||||
Message *message = static_cast<Message *>(aMessage);
|
||||
return message->Write(aOffset, aLength, aBuf);
|
||||
}
|
||||
|
||||
ThreadError otOpenUdpSocket(otUdpSocket *aSocket, otUdpReceive aCallback, void *aContext)
|
||||
{
|
||||
Ip6::UdpSocket *socket = reinterpret_cast<Ip6::UdpSocket *>(aSocket);
|
||||
return socket->Open(aCallback, aContext);
|
||||
}
|
||||
|
||||
ThreadError otCloseUdpSocket(otUdpSocket *aSocket)
|
||||
{
|
||||
Ip6::UdpSocket *socket = reinterpret_cast<Ip6::UdpSocket *>(aSocket);
|
||||
return socket->Close();
|
||||
}
|
||||
|
||||
ThreadError otBindUdpSocket(otUdpSocket *aSocket, otSockAddr *aSockName)
|
||||
{
|
||||
Ip6::UdpSocket *socket = reinterpret_cast<Ip6::UdpSocket *>(aSocket);
|
||||
return socket->Bind(*reinterpret_cast<const Ip6::SockAddr *>(aSockName));
|
||||
}
|
||||
|
||||
ThreadError otSendUdpMessage(otUdpSocket *aSocket, otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
Ip6::UdpSocket *socket = reinterpret_cast<Ip6::UdpSocket *>(aSocket);
|
||||
return socket->SendTo(*reinterpret_cast<Message *>(aMessage),
|
||||
*reinterpret_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,638 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements Thread's EID-to-RLOC mapping and caching.
|
||||
*/
|
||||
|
||||
#include <coap/coap_header.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <common/encoding.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <platform/random.h>
|
||||
#include <thread/address_resolver.hpp>
|
||||
#include <thread/mesh_forwarder.hpp>
|
||||
#include <thread/mle_router.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
#include <thread/thread_tlvs.hpp>
|
||||
#include <thread/thread_uris.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
|
||||
namespace Thread {
|
||||
|
||||
AddressResolver::AddressResolver(ThreadNetif &aThreadNetif) :
|
||||
mAddressError(OPENTHREAD_URI_ADDRESS_ERROR, &HandleAddressError, this),
|
||||
mAddressQuery(OPENTHREAD_URI_ADDRESS_QUERY, &HandleAddressQuery, this),
|
||||
mAddressNotification(OPENTHREAD_URI_ADDRESS_NOTIFY, &HandleAddressNotification, this),
|
||||
mIcmpHandler(&HandleDstUnreach, this),
|
||||
mTimer(&HandleTimer, this),
|
||||
mMeshForwarder(aThreadNetif.GetMeshForwarder()),
|
||||
mCoapServer(aThreadNetif.GetCoapServer()),
|
||||
mMle(aThreadNetif.GetMle()),
|
||||
mNetif(aThreadNetif)
|
||||
{
|
||||
memset(&mCache, 0, sizeof(mCache));
|
||||
|
||||
mCoapServer.AddResource(mAddressError);
|
||||
mCoapServer.AddResource(mAddressQuery);
|
||||
mCoapServer.AddResource(mAddressNotification);
|
||||
mCoapMessageId = otPlatRandomGet();
|
||||
|
||||
Ip6::Icmp::RegisterCallbacks(mIcmpHandler);
|
||||
}
|
||||
|
||||
void AddressResolver::Clear()
|
||||
{
|
||||
memset(&mCache, 0, sizeof(mCache));
|
||||
}
|
||||
|
||||
void AddressResolver::Remove(uint8_t routerId)
|
||||
{
|
||||
for (int i = 0; i < kCacheEntries; i++)
|
||||
{
|
||||
if ((mCache[i].mRloc16 >> 10) == routerId)
|
||||
{
|
||||
mCache[i].mState = Cache::kStateInvalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError AddressResolver::Resolve(const Ip6::Address &aEid, uint16_t &aRloc16)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Cache *entry = NULL;
|
||||
|
||||
for (int i = 0; i < kCacheEntries; i++)
|
||||
{
|
||||
if (mCache[i].mState != Cache::kStateInvalid)
|
||||
{
|
||||
if (memcmp(&mCache[i].mTarget, &aEid, sizeof(mCache[i].mTarget)) == 0)
|
||||
{
|
||||
entry = &mCache[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (entry == NULL)
|
||||
{
|
||||
entry = &mCache[i];
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrExit(entry != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
switch (entry->mState)
|
||||
{
|
||||
case Cache::kStateInvalid:
|
||||
entry->mTarget = aEid;
|
||||
entry->mRloc16 = Mac::kShortAddrInvalid;
|
||||
entry->mTimeout = kAddressQueryTimeout;
|
||||
entry->mFailures = 0;
|
||||
entry->mRetryTimeout = kAddressQueryInitialRetryDelay;
|
||||
entry->mState = Cache::kStateQuery;
|
||||
SendAddressQuery(aEid);
|
||||
error = kThreadError_AddressQuery;
|
||||
break;
|
||||
|
||||
case Cache::kStateQuery:
|
||||
if (entry->mTimeout > 0)
|
||||
{
|
||||
error = kThreadError_AddressQuery;
|
||||
}
|
||||
else if (entry->mTimeout == 0 && entry->mRetryTimeout == 0)
|
||||
{
|
||||
entry->mTimeout = kAddressQueryTimeout;
|
||||
SendAddressQuery(aEid);
|
||||
error = kThreadError_AddressQuery;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = kThreadError_Drop;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Cache::kStateCached:
|
||||
aRloc16 = entry->mRloc16;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError AddressResolver::SendAddressQuery(const Ip6::Address &aEid)
|
||||
{
|
||||
ThreadError error;
|
||||
Ip6::SockAddr sockaddr;
|
||||
Message *message;
|
||||
Coap::Header header;
|
||||
ThreadTargetTlv targetTlv;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
sockaddr.mPort = kCoapUdpPort;
|
||||
mSocket.Open(&HandleUdpReceive, this);
|
||||
mSocket.Bind(sockaddr);
|
||||
|
||||
for (size_t i = 0; i < sizeof(mCoapToken); i++)
|
||||
{
|
||||
mCoapToken[i] = otPlatRandomGet();
|
||||
}
|
||||
|
||||
VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
header.Init();
|
||||
header.SetVersion(1);
|
||||
header.SetType(Coap::Header::kTypeNonConfirmable);
|
||||
header.SetCode(Coap::Header::kCodePost);
|
||||
header.SetMessageId(++mCoapMessageId);
|
||||
header.SetToken(NULL, 0);
|
||||
header.AppendUriPathOptions(OPENTHREAD_URI_ADDRESS_QUERY);
|
||||
header.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
|
||||
header.Finalize();
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
|
||||
targetTlv.Init();
|
||||
targetTlv.SetTarget(aEid);
|
||||
SuccessOrExit(error = message->Append(&targetTlv, sizeof(targetTlv)));
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.GetPeerAddr().m16[0] = HostSwap16(0xff03);
|
||||
messageInfo.GetPeerAddr().m16[7] = HostSwap16(0x0002);
|
||||
messageInfo.mPeerPort = kCoapUdpPort;
|
||||
messageInfo.mInterfaceId = mNetif.GetInterfaceId();
|
||||
|
||||
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
|
||||
|
||||
otLogInfoArp("Sent address query\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (mTimer.IsRunning() == false)
|
||||
{
|
||||
mTimer.Start(kStateUpdatePeriod);
|
||||
}
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
Message::Free(*message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void AddressResolver::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
}
|
||||
|
||||
void AddressResolver::HandleAddressNotification(void *aContext, Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
AddressResolver *obj = reinterpret_cast<AddressResolver *>(aContext);
|
||||
obj->HandleAddressNotification(aHeader, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void AddressResolver::HandleAddressNotification(Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadTargetTlv targetTlv;
|
||||
ThreadMeshLocalEidTlv mlIidTlv;
|
||||
ThreadRloc16Tlv rloc16Tlv;
|
||||
|
||||
VerifyOrExit(aHeader.GetType() == Coap::Header::kTypeConfirmable &&
|
||||
aHeader.GetCode() == Coap::Header::kCodePost, ;);
|
||||
|
||||
otLogInfoArp("Received address notification from %04x\n", HostSwap16(aMessageInfo.GetPeerAddr().m16[7]));
|
||||
|
||||
SuccessOrExit(ThreadTlv::GetTlv(aMessage, ThreadTlv::kTarget, sizeof(targetTlv), targetTlv));
|
||||
VerifyOrExit(targetTlv.IsValid(), ;);
|
||||
|
||||
SuccessOrExit(ThreadTlv::GetTlv(aMessage, ThreadTlv::kMeshLocalEid, sizeof(mlIidTlv), mlIidTlv));
|
||||
VerifyOrExit(mlIidTlv.IsValid(), ;);
|
||||
|
||||
SuccessOrExit(ThreadTlv::GetTlv(aMessage, ThreadTlv::kRloc16, sizeof(rloc16Tlv), rloc16Tlv));
|
||||
VerifyOrExit(rloc16Tlv.IsValid(), ;);
|
||||
|
||||
for (int i = 0; i < kCacheEntries; i++)
|
||||
{
|
||||
if (mCache[i].mTarget == *targetTlv.GetTarget())
|
||||
{
|
||||
if (mCache[i].mState != Cache::kStateCached ||
|
||||
memcmp(mCache[i].mMeshLocalIid, mlIidTlv.GetIid(), sizeof(mCache[i].mMeshLocalIid)) == 0)
|
||||
{
|
||||
memcpy(mCache[i].mMeshLocalIid, mlIidTlv.GetIid(), sizeof(mCache[i].mMeshLocalIid));
|
||||
mCache[i].mRloc16 = rloc16Tlv.GetRloc16();
|
||||
mCache[i].mRetryTimeout = 0;
|
||||
mCache[i].mTimeout = 0;
|
||||
mCache[i].mFailures = 0;
|
||||
mCache[i].mState = Cache::kStateCached;
|
||||
SendAddressNotificationResponse(aHeader, aMessageInfo);
|
||||
mMeshForwarder.HandleResolved(*targetTlv.GetTarget(), kThreadError_None);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendAddressError(targetTlv, mlIidTlv, NULL);
|
||||
}
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
ExitNow();
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
void AddressResolver::SendAddressNotificationResponse(const Coap::Header &aRequestHeader,
|
||||
const Ip6::MessageInfo &aRequestInfo)
|
||||
{
|
||||
ThreadError error;
|
||||
Message *message;
|
||||
Coap::Header responseHeader;
|
||||
Ip6::MessageInfo responseInfo;
|
||||
|
||||
VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
responseHeader.Init();
|
||||
responseHeader.SetVersion(1);
|
||||
responseHeader.SetType(Coap::Header::kTypeAcknowledgment);
|
||||
responseHeader.SetCode(Coap::Header::kCodeChanged);
|
||||
responseHeader.SetMessageId(aRequestHeader.GetMessageId());
|
||||
responseHeader.SetToken(aRequestHeader.GetToken(), aRequestHeader.GetTokenLength());
|
||||
responseHeader.Finalize();
|
||||
SuccessOrExit(error = message->Append(responseHeader.GetBytes(), responseHeader.GetLength()));
|
||||
|
||||
memcpy(&responseInfo, &aRequestInfo, sizeof(responseInfo));
|
||||
memset(&responseInfo.mSockAddr, 0, sizeof(responseInfo.mSockAddr));
|
||||
SuccessOrExit(error = mCoapServer.SendMessage(*message, responseInfo));
|
||||
|
||||
otLogInfoArp("Sent address notification acknowledgment\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
Message::Free(*message);
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError AddressResolver::SendAddressError(const ThreadTargetTlv &aTarget, const ThreadMeshLocalEidTlv &aEid,
|
||||
const Ip6::Address *aDestination)
|
||||
{
|
||||
ThreadError error;
|
||||
Message *message;
|
||||
Coap::Header header;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
Ip6::SockAddr sockaddr;
|
||||
|
||||
sockaddr.mPort = kCoapUdpPort;
|
||||
mSocket.Open(&HandleUdpReceive, this);
|
||||
mSocket.Bind(sockaddr);
|
||||
|
||||
for (size_t i = 0; i < sizeof(mCoapToken); i++)
|
||||
{
|
||||
mCoapToken[i] = otPlatRandomGet();
|
||||
}
|
||||
|
||||
VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
header.Init();
|
||||
header.SetVersion(1);
|
||||
header.SetType(Coap::Header::kTypeNonConfirmable);
|
||||
header.SetCode(Coap::Header::kCodePost);
|
||||
header.SetMessageId(++mCoapMessageId);
|
||||
header.SetToken(NULL, 0);
|
||||
header.AppendUriPathOptions(OPENTHREAD_URI_ADDRESS_ERROR);
|
||||
header.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
|
||||
header.Finalize();
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
SuccessOrExit(error = message->Append(&aTarget, sizeof(aTarget)));
|
||||
SuccessOrExit(error = message->Append(&aEid, sizeof(aEid)));
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
|
||||
if (aDestination == NULL)
|
||||
{
|
||||
messageInfo.GetPeerAddr().m16[0] = HostSwap16(0xff03);
|
||||
messageInfo.GetPeerAddr().m16[7] = HostSwap16(0x0002);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&messageInfo.GetPeerAddr(), aDestination, sizeof(messageInfo.GetPeerAddr()));
|
||||
}
|
||||
|
||||
messageInfo.mPeerPort = kCoapUdpPort;
|
||||
messageInfo.mInterfaceId = mNetif.GetInterfaceId();
|
||||
|
||||
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
|
||||
|
||||
otLogInfoArp("Sent address error\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
Message::Free(*message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void AddressResolver::HandleAddressError(void *aContext, Coap::Header &aHeader,
|
||||
Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
AddressResolver *obj = reinterpret_cast<AddressResolver *>(aContext);
|
||||
obj->HandleAddressError(aHeader, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void AddressResolver::HandleAddressError(Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ThreadTargetTlv targetTlv;
|
||||
ThreadMeshLocalEidTlv mlIidTlv;
|
||||
Child *children;
|
||||
uint8_t numChildren;
|
||||
Mac::ExtAddress macAddr;
|
||||
Ip6::Address destination;
|
||||
|
||||
VerifyOrExit(aHeader.GetCode() == Coap::Header::kCodePost, error = kThreadError_Drop);
|
||||
|
||||
otLogInfoArp("Received address error notification\n");
|
||||
|
||||
SuccessOrExit(error = ThreadTlv::GetTlv(aMessage, ThreadTlv::kTarget, sizeof(targetTlv), targetTlv));
|
||||
VerifyOrExit(targetTlv.IsValid(), error = kThreadError_Parse);
|
||||
|
||||
SuccessOrExit(error = ThreadTlv::GetTlv(aMessage, ThreadTlv::kMeshLocalEid, sizeof(mlIidTlv), mlIidTlv));
|
||||
VerifyOrExit(mlIidTlv.IsValid(), error = kThreadError_Parse);
|
||||
|
||||
for (const Ip6::NetifUnicastAddress *address = mNetif.GetUnicastAddresses(); address; address = address->GetNext())
|
||||
{
|
||||
if (memcmp(&address->mAddress, targetTlv.GetTarget(), sizeof(address->mAddress)) == 0 &&
|
||||
memcmp(mMle.GetMeshLocal64()->GetIid(), mlIidTlv.GetIid(), 8))
|
||||
{
|
||||
// Target EID matches address and Mesh Local EID differs
|
||||
mNetif.RemoveUnicastAddress(*address);
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
children = mMle.GetChildren(&numChildren);
|
||||
|
||||
memcpy(&macAddr, mlIidTlv.GetIid(), sizeof(macAddr));
|
||||
macAddr.mBytes[0] ^= 0x2;
|
||||
|
||||
for (int i = 0; i < Mle::kMaxChildren; i++)
|
||||
{
|
||||
if (children[i].mState != Neighbor::kStateValid || (children[i].mMode & Mle::ModeTlv::kModeFFD) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < Child::kMaxIp6AddressPerChild; j++)
|
||||
{
|
||||
if (memcmp(&children[i].mIp6Address[j], targetTlv.GetTarget(), sizeof(children[i].mIp6Address[j])) == 0 &&
|
||||
memcmp(&children[i].mMacAddr, &macAddr, sizeof(children[i].mMacAddr)))
|
||||
{
|
||||
// Target EID matches child address and Mesh Local EID differs on child
|
||||
memset(&children[i].mIp6Address[j], 0, sizeof(children[i].mIp6Address[j]));
|
||||
|
||||
memset(&destination, 0, sizeof(destination));
|
||||
destination.m16[0] = HostSwap16(0xfe80);
|
||||
destination.SetIid(children[i].mMacAddr);
|
||||
|
||||
SendAddressError(targetTlv, mlIidTlv, &destination);
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
void AddressResolver::HandleAddressQuery(void *aContext, Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
AddressResolver *obj = reinterpret_cast<AddressResolver *>(aContext);
|
||||
obj->HandleAddressQuery(aHeader, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void AddressResolver::HandleAddressQuery(Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadTargetTlv targetTlv;
|
||||
ThreadMeshLocalEidTlv mlIidTlv;
|
||||
ThreadLastTransactionTimeTlv lastTransactionTimeTlv;
|
||||
Child *children;
|
||||
uint8_t numChildren;
|
||||
|
||||
VerifyOrExit(aHeader.GetType() == Coap::Header::kTypeNonConfirmable &&
|
||||
aHeader.GetCode() == Coap::Header::kCodePost, ;);
|
||||
|
||||
otLogInfoArp("Received address query from %04x\n", HostSwap16(aMessageInfo.GetPeerAddr().m16[7]));
|
||||
|
||||
SuccessOrExit(ThreadTlv::GetTlv(aMessage, ThreadTlv::kTarget, sizeof(targetTlv), targetTlv));
|
||||
VerifyOrExit(targetTlv.IsValid(), ;);
|
||||
|
||||
mlIidTlv.Init();
|
||||
|
||||
lastTransactionTimeTlv.Init();
|
||||
|
||||
if (mNetif.IsUnicastAddress(*targetTlv.GetTarget()))
|
||||
{
|
||||
mlIidTlv.SetIid(mMle.GetMeshLocal64()->GetIid());
|
||||
SendAddressQueryResponse(targetTlv, mlIidTlv, NULL, aMessageInfo.GetPeerAddr());
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
children = mMle.GetChildren(&numChildren);
|
||||
|
||||
for (int i = 0; i < Mle::kMaxChildren; i++)
|
||||
{
|
||||
if (children[i].mState != Neighbor::kStateValid || (children[i].mMode & Mle::ModeTlv::kModeFFD) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < Child::kMaxIp6AddressPerChild; j++)
|
||||
{
|
||||
if (memcmp(&children[i].mIp6Address[j], targetTlv.GetTarget(), sizeof(children[i].mIp6Address[j])))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
children[i].mMacAddr.mBytes[0] ^= 0x2;
|
||||
mlIidTlv.SetIid(children[i].mMacAddr.mBytes);
|
||||
children[i].mMacAddr.mBytes[0] ^= 0x2;
|
||||
lastTransactionTimeTlv.SetTime(Timer::GetNow() - children[i].mLastHeard);
|
||||
SendAddressQueryResponse(targetTlv, mlIidTlv, &lastTransactionTimeTlv, aMessageInfo.GetPeerAddr());
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
void AddressResolver::SendAddressQueryResponse(const ThreadTargetTlv &aTargetTlv,
|
||||
const ThreadMeshLocalEidTlv &aMlIidTlv,
|
||||
const ThreadLastTransactionTimeTlv *aLastTransactionTimeTlv,
|
||||
const Ip6::Address &aDestination)
|
||||
{
|
||||
ThreadError error;
|
||||
Message *message;
|
||||
Coap::Header header;
|
||||
ThreadRloc16Tlv rloc16Tlv;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
header.Init();
|
||||
header.SetVersion(1);
|
||||
header.SetType(Coap::Header::kTypeConfirmable);
|
||||
header.SetCode(Coap::Header::kCodePost);
|
||||
header.SetMessageId(++mCoapMessageId);
|
||||
header.SetToken(NULL, 0);
|
||||
header.AppendUriPathOptions(OPENTHREAD_URI_ADDRESS_NOTIFY);
|
||||
header.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
|
||||
header.Finalize();
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
|
||||
SuccessOrExit(error = message->Append(&aTargetTlv, sizeof(aTargetTlv)));
|
||||
SuccessOrExit(error = message->Append(&aMlIidTlv, sizeof(aMlIidTlv)));
|
||||
|
||||
rloc16Tlv.Init();
|
||||
rloc16Tlv.SetRloc16(mMle.GetRloc16());
|
||||
SuccessOrExit(error = message->Append(&rloc16Tlv, sizeof(rloc16Tlv)));
|
||||
|
||||
if (aLastTransactionTimeTlv != NULL)
|
||||
{
|
||||
SuccessOrExit(error = message->Append(aLastTransactionTimeTlv, sizeof(*aLastTransactionTimeTlv)));
|
||||
}
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
memcpy(&messageInfo.GetPeerAddr(), &aDestination, sizeof(messageInfo.GetPeerAddr()));
|
||||
messageInfo.mInterfaceId = messageInfo.mInterfaceId;
|
||||
messageInfo.mPeerPort = kCoapUdpPort;
|
||||
|
||||
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
|
||||
|
||||
otLogInfoArp("Sent address notification\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
Message::Free(*message);
|
||||
}
|
||||
}
|
||||
|
||||
void AddressResolver::HandleTimer(void *aContext)
|
||||
{
|
||||
AddressResolver *obj = reinterpret_cast<AddressResolver *>(aContext);
|
||||
obj->HandleTimer();
|
||||
}
|
||||
|
||||
void AddressResolver::HandleTimer()
|
||||
{
|
||||
bool continueTimer = false;
|
||||
|
||||
for (int i = 0; i < kCacheEntries; i++)
|
||||
{
|
||||
if (mCache[i].mState != Cache::kStateQuery)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
continueTimer = true;
|
||||
|
||||
if (mCache[i].mTimeout > 0)
|
||||
{
|
||||
mCache[i].mTimeout--;
|
||||
|
||||
if (mCache[i].mTimeout == 0)
|
||||
{
|
||||
mCache[i].mFailures++;
|
||||
mCache[i].mRetryTimeout = kAddressQueryInitialRetryDelay * (1 << mCache[i].mFailures);
|
||||
|
||||
if (mCache[i].mRetryTimeout > kAddressQueryMaxRetryDelay)
|
||||
{
|
||||
mCache[i].mRetryTimeout = kAddressQueryMaxRetryDelay;
|
||||
mCache[i].mFailures--;
|
||||
}
|
||||
|
||||
mMeshForwarder.HandleResolved(mCache[i].mTarget, kThreadError_Drop);
|
||||
}
|
||||
}
|
||||
else if (mCache[i].mRetryTimeout > 0)
|
||||
{
|
||||
mCache[i].mRetryTimeout--;
|
||||
}
|
||||
}
|
||||
|
||||
if (continueTimer)
|
||||
{
|
||||
mTimer.Start(kStateUpdatePeriod);
|
||||
}
|
||||
}
|
||||
|
||||
void AddressResolver::HandleDstUnreach(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
const Ip6::IcmpHeader &aIcmpHeader)
|
||||
{
|
||||
AddressResolver *obj = reinterpret_cast<AddressResolver *>(aContext);
|
||||
obj->HandleDstUnreach(aMessage, aMessageInfo, aIcmpHeader);
|
||||
}
|
||||
|
||||
void AddressResolver::HandleDstUnreach(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
const Ip6::IcmpHeader &aIcmpHeader)
|
||||
{
|
||||
Ip6::Header ip6Header;
|
||||
|
||||
VerifyOrExit(aIcmpHeader.GetCode() == Ip6::IcmpHeader::kCodeDstUnreachNoRoute, ;);
|
||||
VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(ip6Header), &ip6Header) == sizeof(ip6Header), ;);
|
||||
|
||||
for (int i = 0; i < kCacheEntries; i++)
|
||||
{
|
||||
if (mCache[i].mState != Cache::kStateInvalid &&
|
||||
memcmp(&mCache[i].mTarget, &ip6Header.GetDestination(), sizeof(mCache[i].mTarget)) == 0)
|
||||
{
|
||||
mCache[i].mState = Cache::kStateInvalid;
|
||||
otLogInfoArp("cache entry removed!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for Thread EID-to-RLOC mapping and caching.
|
||||
*/
|
||||
|
||||
#ifndef ADDRESS_RESOLVER_HPP_
|
||||
#define ADDRESS_RESOLVER_HPP_
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread-types.h>
|
||||
#include <coap/coap_server.hpp>
|
||||
#include <common/timer.hpp>
|
||||
#include <mac/mac.hpp>
|
||||
#include <net/icmp6.hpp>
|
||||
#include <net/udp6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
class MeshForwarder;
|
||||
class ThreadLastTransactionTimeTlv;
|
||||
class ThreadMeshLocalEidTlv;
|
||||
class ThreadNetif;
|
||||
class ThreadTargetTlv;
|
||||
|
||||
/**
|
||||
* @addtogroup core-arp
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for Thread EID-to-RLOC mapping and caching.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements the EID-to-RLOC mapping and caching.
|
||||
*
|
||||
*/
|
||||
class AddressResolver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
*/
|
||||
explicit AddressResolver(ThreadNetif &aThreadNetif);
|
||||
|
||||
/**
|
||||
* This method clears the EID-to-RLOC cache.
|
||||
*
|
||||
*/
|
||||
void Clear(void);
|
||||
|
||||
/**
|
||||
* This method removes a Router ID from the EID-to-RLOC cache.
|
||||
*
|
||||
* @param[in] aRouterId The Router ID.
|
||||
*
|
||||
*/
|
||||
void Remove(uint8_t aRouterId);
|
||||
|
||||
/**
|
||||
* This method returns the RLOC16 for a given EID, or initiates an Address Query if the mapping is not known.
|
||||
*
|
||||
* @param[in] aEid A reference to the EID.
|
||||
* @param[out] aRloc16 The RLOC16 corresponding to @p aEid.
|
||||
*
|
||||
* @retval kTheradError_None Successfully provided the RLOC16.
|
||||
* @retval kThreadError_AddressQuery Initiated an Address Query.
|
||||
*
|
||||
*/
|
||||
ThreadError Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kCacheEntries = OPENTHREAD_CONFIG_ADDRESS_CACHE_ENTRIES,
|
||||
kStateUpdatePeriod = 1000u, ///< State update period in milliseconds.
|
||||
};
|
||||
|
||||
/**
|
||||
* Thread Protocol Parameters and Constants
|
||||
*
|
||||
*/
|
||||
enum
|
||||
{
|
||||
kAddressQueryTimeout = 3, ///< ADDRESS_QUERY_TIMEOUT (seconds)
|
||||
kAddressQueryInitialRetryDelay = 15, ///< ADDRESS_QUERY_INITIAL_RETRY_DELAY (seconds)
|
||||
kAddressQueryMaxRetryDelay = 480, ///< ADDRESS_QUERY_MAX_RETRY_DELAY (seconds)
|
||||
};
|
||||
|
||||
struct Cache
|
||||
{
|
||||
Ip6::Address mTarget;
|
||||
uint8_t mMeshLocalIid[Ip6::Address::kInterfaceIdentifierSize];
|
||||
Mac::ShortAddress mRloc16;
|
||||
uint16_t mRetryTimeout;
|
||||
uint8_t mTimeout;
|
||||
uint8_t mFailures;
|
||||
|
||||
enum State
|
||||
{
|
||||
kStateInvalid,
|
||||
kStateQuery,
|
||||
kStateCached,
|
||||
};
|
||||
State mState;
|
||||
};
|
||||
|
||||
ThreadError SendAddressQuery(const Ip6::Address &aEid);
|
||||
ThreadError SendAddressError(const ThreadTargetTlv &aTarget, const ThreadMeshLocalEidTlv &aEid,
|
||||
const Ip6::Address *aDestination);
|
||||
void SendAddressQueryResponse(const ThreadTargetTlv &aTargetTlv, const ThreadMeshLocalEidTlv &aMlEidTlv,
|
||||
const ThreadLastTransactionTimeTlv *aLastTransactionTimeTlv,
|
||||
const Ip6::Address &aDestination);
|
||||
void SendAddressNotificationResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
static void HandleAddressError(void *aContext, Coap::Header &aHeader,
|
||||
Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleAddressError(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
static void HandleAddressQuery(void *aContext, Coap::Header &aHeader,
|
||||
Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleAddressQuery(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
static void HandleAddressNotification(void *aContext, Coap::Header &aHeader,
|
||||
Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleAddressNotification(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
static void HandleDstUnreach(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
const Ip6::IcmpHeader &aIcmpHeader);
|
||||
void HandleDstUnreach(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Ip6::IcmpHeader &aIcmpHeader);
|
||||
|
||||
static void HandleTimer(void *aContext);
|
||||
void HandleTimer(void);
|
||||
|
||||
Coap::Resource mAddressError;
|
||||
Coap::Resource mAddressQuery;
|
||||
Coap::Resource mAddressNotification;
|
||||
Cache mCache[kCacheEntries];
|
||||
uint16_t mCoapMessageId;
|
||||
uint8_t mCoapToken[2];
|
||||
Ip6::IcmpHandler mIcmpHandler;
|
||||
Ip6::UdpSocket mSocket;
|
||||
Timer mTimer;
|
||||
|
||||
MeshForwarder &mMeshForwarder;
|
||||
Coap::Server &mCoapServer;
|
||||
Mle::MleRouter &mMle;
|
||||
Ip6::Netif &mNetif;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // ADDRESS_RESOLVER_HPP_
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements Thread security material generation.
|
||||
*/
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <crypto/hmac_sha256.h>
|
||||
#include <thread/key_manager.hpp>
|
||||
#include <thread/mle_router.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
static const uint8_t kThreadString[] =
|
||||
{
|
||||
'T', 'h', 'r', 'e', 'a', 'd',
|
||||
};
|
||||
|
||||
KeyManager::KeyManager(ThreadNetif &aThreadNetif):
|
||||
mNetif(aThreadNetif)
|
||||
{
|
||||
mPreviousKeyValid = false;
|
||||
mMacFrameCounter = 0;
|
||||
mMleFrameCounter = 0;
|
||||
}
|
||||
|
||||
const uint8_t *KeyManager::GetMasterKey(uint8_t *aKeyLength) const
|
||||
{
|
||||
if (aKeyLength)
|
||||
{
|
||||
*aKeyLength = mMasterKeyLength;
|
||||
}
|
||||
|
||||
return mMasterKey;
|
||||
}
|
||||
|
||||
ThreadError KeyManager::SetMasterKey(const void *aKey, uint8_t aKeyLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(aKeyLength <= sizeof(mMasterKey), error = kThreadError_InvalidArgs);
|
||||
memcpy(mMasterKey, aKey, aKeyLength);
|
||||
mMasterKeyLength = aKeyLength;
|
||||
mCurrentKeySequence = 0;
|
||||
ComputeKey(mCurrentKeySequence, mCurrentKey);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError KeyManager::ComputeKey(uint32_t aKeySequence, uint8_t *aKey)
|
||||
{
|
||||
uint8_t keySequenceBytes[4];
|
||||
|
||||
otCryptoHmacSha256Start(mMasterKey, mMasterKeyLength);
|
||||
|
||||
keySequenceBytes[0] = aKeySequence >> 24;
|
||||
keySequenceBytes[1] = aKeySequence >> 16;
|
||||
keySequenceBytes[2] = aKeySequence >> 8;
|
||||
keySequenceBytes[3] = aKeySequence >> 0;
|
||||
otCryptoHmacSha256Update(keySequenceBytes, sizeof(keySequenceBytes));
|
||||
otCryptoHmacSha256Update(kThreadString, sizeof(kThreadString));
|
||||
|
||||
otCryptoHmacSha256Finish(aKey);
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
uint32_t KeyManager::GetCurrentKeySequence() const
|
||||
{
|
||||
return mCurrentKeySequence;
|
||||
}
|
||||
|
||||
void KeyManager::UpdateNeighbors()
|
||||
{
|
||||
uint8_t numNeighbors;
|
||||
Router *routers;
|
||||
Child *children;
|
||||
|
||||
routers = mNetif.GetMle().GetParent();
|
||||
routers->mPreviousKey = true;
|
||||
|
||||
routers = mNetif.GetMle().GetRouters(&numNeighbors);
|
||||
|
||||
for (int i = 0; i < numNeighbors; i++)
|
||||
{
|
||||
routers[i].mPreviousKey = true;
|
||||
}
|
||||
|
||||
children = mNetif.GetMle().GetChildren(&numNeighbors);
|
||||
|
||||
for (int i = 0; i < numNeighbors; i++)
|
||||
{
|
||||
children[i].mPreviousKey = true;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence)
|
||||
{
|
||||
mPreviousKeyValid = true;
|
||||
mPreviousKeySequence = mCurrentKeySequence;
|
||||
memcpy(mPreviousKey, mCurrentKey, sizeof(mPreviousKey));
|
||||
|
||||
mCurrentKeySequence = aKeySequence;
|
||||
ComputeKey(mCurrentKeySequence, mCurrentKey);
|
||||
|
||||
mMacFrameCounter = 0;
|
||||
mMleFrameCounter = 0;
|
||||
|
||||
UpdateNeighbors();
|
||||
}
|
||||
|
||||
const uint8_t *KeyManager::GetCurrentMacKey() const
|
||||
{
|
||||
return mCurrentKey + 16;
|
||||
}
|
||||
|
||||
const uint8_t *KeyManager::GetCurrentMleKey() const
|
||||
{
|
||||
return mCurrentKey;
|
||||
}
|
||||
|
||||
bool KeyManager::IsPreviousKeyValid() const
|
||||
{
|
||||
return mPreviousKeyValid;
|
||||
}
|
||||
|
||||
uint32_t KeyManager::GetPreviousKeySequence() const
|
||||
{
|
||||
return mPreviousKeySequence;
|
||||
}
|
||||
|
||||
const uint8_t *KeyManager::GetPreviousMacKey() const
|
||||
{
|
||||
return mPreviousKey + 16;
|
||||
}
|
||||
|
||||
const uint8_t *KeyManager::GetPreviousMleKey() const
|
||||
{
|
||||
return mPreviousKey;
|
||||
}
|
||||
|
||||
const uint8_t *KeyManager::GetTemporaryMacKey(uint32_t aKeySequence)
|
||||
{
|
||||
ComputeKey(aKeySequence, mTemporaryKey);
|
||||
return mTemporaryKey + 16;
|
||||
}
|
||||
|
||||
const uint8_t *KeyManager::GetTemporaryMleKey(uint32_t aKeySequence)
|
||||
{
|
||||
ComputeKey(aKeySequence, mTemporaryKey);
|
||||
return mTemporaryKey;
|
||||
}
|
||||
|
||||
uint32_t KeyManager::GetMacFrameCounter() const
|
||||
{
|
||||
return mMacFrameCounter;
|
||||
}
|
||||
|
||||
void KeyManager::IncrementMacFrameCounter()
|
||||
{
|
||||
mMacFrameCounter++;
|
||||
}
|
||||
|
||||
uint32_t KeyManager::GetMleFrameCounter() const
|
||||
{
|
||||
return mMleFrameCounter;
|
||||
}
|
||||
|
||||
void KeyManager::IncrementMleFrameCounter()
|
||||
{
|
||||
mMleFrameCounter++;
|
||||
}
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for Thread security material generation.
|
||||
*/
|
||||
|
||||
#ifndef KEY_MANAGER_HPP_
|
||||
#define KEY_MANAGER_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <crypto/hmac_sha256.h>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
class ThreadNetif;
|
||||
|
||||
/**
|
||||
* @addtogroup core-security
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for Thread security material generation.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
class KeyManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
* @param[in] aThreadNetif A reference to the Thread network interface.
|
||||
*
|
||||
*/
|
||||
explicit KeyManager(ThreadNetif &aThreadNetif);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Thread Master Key
|
||||
*
|
||||
* @param[out] aKeyLength A pointer where the key length value will be placed.
|
||||
*
|
||||
* @returns A pointer to the Thread Master Key.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetMasterKey(uint8_t *aKeyLength) const;
|
||||
|
||||
/**
|
||||
* This method sets the Thread Master Key.
|
||||
*
|
||||
* @param[in] aKey A pointer to the Thread Master Key.
|
||||
* @param[in] aKeyLength The length of @p aKey.
|
||||
*
|
||||
* @retval kThreadError_None Successfully set the Thread Master Key.
|
||||
* @retval kThreadError_InvalidArgs The @p aKeyLength value was invalid.
|
||||
*
|
||||
*/
|
||||
ThreadError SetMasterKey(const void *aKey, uint8_t aKeyLength);
|
||||
|
||||
/**
|
||||
* This method returns the current key sequence value.
|
||||
*
|
||||
* @returns The current key sequence value.
|
||||
*
|
||||
*/
|
||||
uint32_t GetCurrentKeySequence() const;
|
||||
|
||||
/**
|
||||
* This method sets the current key sequence value.
|
||||
*
|
||||
* @param[in] aKeySequence The key sequence value.
|
||||
*
|
||||
*/
|
||||
void SetCurrentKeySequence(uint32_t aKeySequence);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the current MAC key.
|
||||
*
|
||||
* @returns A pointer to the current MAC key.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetCurrentMacKey() const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the current MLE key.
|
||||
*
|
||||
* @returns A pointer to the current MLE key.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetCurrentMleKey() const;
|
||||
|
||||
/**
|
||||
* This method indicates whether the previous key is valid.
|
||||
*
|
||||
* @retval TRUE If the previous key is vaild.
|
||||
* @retval FALSE If the previous key is not valid.
|
||||
*
|
||||
*/
|
||||
bool IsPreviousKeyValid() const;
|
||||
|
||||
/**
|
||||
* This method returns the previous key sequence value.
|
||||
*
|
||||
* @returns The previous key sequence value.
|
||||
*
|
||||
*/
|
||||
uint32_t GetPreviousKeySequence() const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the previous MAC key.
|
||||
*
|
||||
* @returns A pointer to the previous MAC key.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetPreviousMacKey() const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the previous MLE key.
|
||||
*
|
||||
* @returns A pointer to the previous MLE key.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetPreviousMleKey() const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to a temporary MAC key computed from the given key sequence.
|
||||
*
|
||||
* @param[in] aKeySequence The key sequence value.
|
||||
*
|
||||
* @returns A pointer to the temporary MAC key.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetTemporaryMacKey(uint32_t aKeySequence);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to a temporary MLE key computed from the given key sequence.
|
||||
*
|
||||
* @param[in] aKeySequence The key sequence value.
|
||||
*
|
||||
* @returns A pointer to the temporary MLE key.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetTemporaryMleKey(uint32_t aKeySequence);
|
||||
|
||||
/**
|
||||
* This method returns the current MAC Frame Counter value.
|
||||
*
|
||||
* @returns The current MAC Frame Counter value.
|
||||
*
|
||||
*/
|
||||
uint32_t GetMacFrameCounter() const;
|
||||
|
||||
/**
|
||||
* This method increments the current MAC Frame Counter value.
|
||||
*
|
||||
* @returns The current MAC Frame Counter value.
|
||||
*
|
||||
*/
|
||||
void IncrementMacFrameCounter();
|
||||
|
||||
/**
|
||||
* This method returns the current MLE Frame Counter value.
|
||||
*
|
||||
* @returns The current MLE Frame Counter value.
|
||||
*
|
||||
*/
|
||||
uint32_t GetMleFrameCounter() const;
|
||||
|
||||
/**
|
||||
* This method increments the current MLE Frame Counter value.
|
||||
*
|
||||
* @returns The current MLE Frame Counter value.
|
||||
*
|
||||
*/
|
||||
void IncrementMleFrameCounter();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxKeyLength = 16,
|
||||
};
|
||||
|
||||
ThreadError ComputeKey(uint32_t aKeySequence, uint8_t *aKey);
|
||||
void UpdateNeighbors();
|
||||
|
||||
uint8_t mMasterKey[kMaxKeyLength];
|
||||
uint8_t mMasterKeyLength;
|
||||
|
||||
uint32_t mPreviousKeySequence;
|
||||
uint8_t mPreviousKey[otCryptoSha256Size];
|
||||
bool mPreviousKeyValid;
|
||||
|
||||
uint32_t mCurrentKeySequence;
|
||||
uint8_t mCurrentKey[otCryptoSha256Size];
|
||||
|
||||
uint8_t mTemporaryKey[otCryptoSha256Size];
|
||||
|
||||
uint32_t mMacFrameCounter;
|
||||
uint32_t mMleFrameCounter;
|
||||
|
||||
ThreadNetif &mNetif;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // KEY_MANAGER_HPP_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user