[url] move url to library (#5233)

This commit moves the URL parser to src/lib.

Also includes the following changes:
- Split URL on initialization.
- Make a GetValue() const method.
- Check aLastValue.
- Add some negative tests.
This commit is contained in:
Yakun Xu
2020-07-16 14:39:02 +08:00
committed by GitHub
parent 4e8836cbec
commit 89cd4b59f8
23 changed files with 477 additions and 227 deletions
+1
View File
@@ -277,6 +277,7 @@ LOCAL_SRC_FILES := \
src/lib/spinel/spinel.c \
src/lib/spinel/spinel_decoder.cpp \
src/lib/spinel/spinel_encoder.cpp \
src/lib/url/url.cpp \
src/posix/platform/alarm.cpp \
src/posix/platform/entropy.cpp \
src/posix/platform/hdlc_interface.cpp \
+5 -1
View File
@@ -40,7 +40,11 @@ set(OT_EXTERNAL_MBEDTLS "" CACHE STRING "Specify external mbedtls library")
add_library(ot-config INTERFACE)
target_include_directories(ot-config INTERFACE ${PROJECT_SOURCE_DIR}/src/core)
target_include_directories(ot-config INTERFACE
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/core
)
include(TestBigEndian)
TEST_BIG_ENDIAN(OT_BIG_ENDIAN)
+1
View File
@@ -1026,6 +1026,7 @@ src/lib/Makefile
src/lib/hdlc/Makefile
src/lib/platform/Makefile
src/lib/spinel/Makefile
src/lib/url/Makefile
third_party/Makefile
third_party/jlink/Makefile
third_party/mbedtls/Makefile
-2
View File
@@ -34,8 +34,6 @@
#ifndef CODE_UTILS_HPP_
#define CODE_UTILS_HPP_
#include "openthread-core-config.h"
#include <stdbool.h>
#include <openthread/error.h>
+1
View File
@@ -29,3 +29,4 @@
add_subdirectory(hdlc)
add_subdirectory(platform)
add_subdirectory(spinel)
add_subdirectory(url)
+1
View File
@@ -32,6 +32,7 @@ SUBDIRS = \
hdlc \
platform \
spinel \
url \
$(NULL)
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
+40
View File
@@ -0,0 +1,40 @@
#
# Copyright (c) 2020, The OpenThread Authors.
# 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.
#
add_library(openthread-url
url.cpp
)
set_target_properties(
openthread-url
PROPERTIES
C_STANDARD 99
CXX_STANDARD 11
)
target_link_libraries(openthread-url PRIVATE ot-config)
+59
View File
@@ -0,0 +1,59 @@
#
# Copyright (c) 2020, The OpenThread Authors.
# 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
noinst_LIBRARIES = libopenthread-url.a
libopenthread_url_a_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src \
$(NULL)
libopenthread_url_a_SOURCES = \
url.cpp \
url.hpp \
$(NULL)
check_PROGRAMS = test-url
test_url_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src \
-DSELF_TEST \
$(NULL)
test_url_SOURCES = \
url.cpp \
$(NULL)
TESTS = \
test-url \
$(NULL)
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
+205
View File
@@ -0,0 +1,205 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* 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 "lib/url/url.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "core/common/code_utils.hpp"
namespace ot {
namespace Url {
otError Url::Init(char *aUrl)
{
otError error = OT_ERROR_NONE;
char * url = aUrl;
mEnd = aUrl + strlen(aUrl);
mProtocol = aUrl;
url = strstr(aUrl, "://");
VerifyOrExit(url != nullptr, error = OT_ERROR_PARSE);
url += sizeof("://") - 1;
mPath = url;
url = strstr(url, "?");
if (url != nullptr)
{
mQuery = ++url;
for (char *cur = strtok(url, "&"); cur != nullptr; cur = strtok(nullptr, "&"))
{
cur[-1] = '\0';
}
}
else
{
mQuery = mEnd;
}
exit:
return error;
}
const char *Url::GetValue(const char *aName, const char *aLastValue) const
{
const char * rval = nullptr;
const size_t len = strlen(aName);
const char * start;
if (aLastValue == nullptr)
{
start = mQuery;
}
else
{
VerifyOrExit(aLastValue > mQuery && aLastValue < mEnd, OT_NOOP);
start = aLastValue + strlen(aLastValue) + 1;
}
while (start < mEnd)
{
const char *last = nullptr;
if (!strncmp(aName, start, len))
{
if (start[len] == '=')
{
ExitNow(rval = &start[len + 1]);
}
else if (start[len] == '\0')
{
ExitNow(rval = "");
}
}
last = start;
start = last + strlen(last) + 1;
}
exit:
return rval;
}
} // namespace Url
} // namespace ot
#ifndef SELF_TEST
#define SELF_TEST 0
#endif
#if SELF_TEST
#include <assert.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
void TestSimple(void)
{
char url[] = "spinel:///dev/ttyUSB0?baudrate=115200";
ot::Url::Url args;
assert(!args.Init(url));
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
assert(!strcmp(args.GetValue("baudrate"), "115200"));
assert(args.GetValue("not-exists") == nullptr);
assert(args.GetValue("last-value-wrong-position", url) == nullptr);
assert(args.GetValue("last-value-before-url", url - 1) == nullptr);
assert(args.GetValue("last-value-after-url", url + sizeof(url)) == nullptr);
printf("PASS %s\r\n", __func__);
}
void TestSimpleNoQueryString(void)
{
char url[] = "spinel:///dev/ttyUSB0";
ot::Url::Url args;
assert(!args.Init(url));
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
assert(args.GetValue("last-value-wrong-position", url) == nullptr);
assert(args.GetValue("last-value-before-url", url - 1) == nullptr);
assert(args.GetValue("last-value-after-url", url + sizeof(url)) == nullptr);
printf("PASS %s\r\n", __func__);
}
void TestMultipleProtocols(void)
{
char url[] = "spinel+spi:///dev/ttyUSB0?baudrate=115200";
ot::Url::Url args;
assert(!args.Init(url));
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
assert(!strcmp(args.GetValue("baudrate"), "115200"));
printf("PASS %s\r\n", __func__);
}
void TestMultipleProtocolsAndDuplicateParameters(void)
{
char url[] = "spinel+exec:///path/to/ot-rcp?arg=1&arg=arg2&arg=3";
ot::Url::Url args;
const char * arg = nullptr;
assert(!args.Init(url));
assert(!strcmp(args.GetPath(), "/path/to/ot-rcp"));
arg = args.GetValue("arg");
assert(!strcmp(arg, "1"));
arg = args.GetValue("arg", arg);
assert(!strcmp(arg, "arg2"));
arg = args.GetValue("arg", arg);
assert(!strcmp(arg, "3"));
assert(args.GetValue("arg", url) == nullptr);
assert(args.GetValue("arg", url - 1) == nullptr);
assert(args.GetValue("arg", url + sizeof(url)) == nullptr);
printf("PASS %s\r\n", __func__);
}
#pragma GCC diagnostic pop
int main(void)
{
TestSimple();
TestSimpleNoQueryString();
TestMultipleProtocols();
TestMultipleProtocolsAndDuplicateParameters();
return 0;
}
#endif // SELF_TEST
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* 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 OT_LIB_URL_URL_HPP_
#define OT_LIB_URL_URL_HPP_
#include <openthread/error.h>
/**
* @struct otUrl
*
* This structure represents a URL.
*
*/
struct otUrl
{
const char *mProtocol; ///< The URL protocol.
const char *mPath; ///< The path.
const char *mQuery; ///< The start of the URL query string.
const char *mEnd; ///< The end of the URL buffer.
};
namespace ot {
namespace Url {
/**
* This class implements the URL processing.
*
*/
class Url : public otUrl
{
public:
/**
* This method initializes the URL.
*
* @param[in] aUrl A buffer stores the null-terminated URL string.
*
* @retval OT_ERROR_NONE Successfully parsed the URL.
* @retval OT_ERROR_PARSE Failed to parse the string as a URL.
*
*/
otError Init(char *aUrl);
/**
* This method gets the path in URL.
*
* @returns The path in url.
*
*/
const char *GetPath(void) const { return mPath; }
/**
* This method gets the value of parameter @p aName.
*
* @param[in] aName The parameter name.
* @param[in] aLastValue The last iterated parameter value, nullptr for the first value.
*
* @returns The parameter value.
*
*/
const char *GetValue(const char *aName, const char *aLastValue = nullptr) const;
/**
* This method returns the URL protocol.
*
* @returns The URL protocol.
*
*/
const char *GetProtocol(void) const { return mProtocol; }
};
} // namespace Url
} // namespace ot
#endif // OT_LIB_URL_URL_HPP_
-1
View File
@@ -55,7 +55,6 @@ CPPFLAGS_COMMON = \
LIBTOOLFLAGS_COMMON = --preserve-dup-deps
LDADD_COMMON = \
$(top_builddir)/src/lib/platform/libopenthread-platform.a \
$(top_builddir)/src/posix/platform/libopenthread-posix.a \
-lutil \
$(NULL)
+1
View File
@@ -87,6 +87,7 @@ target_link_libraries(openthread-posix
PUBLIC
openthread-platform
PRIVATE
openthread-url
ot-config
util
$<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:rt>
+7 -15
View File
@@ -27,6 +27,7 @@
#
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
include $(top_srcdir)/src/lib/common.am
lib_LIBRARIES = libopenthread-posix.a
@@ -59,6 +60,11 @@ libopenthread_posix_a_SOURCES = \
virtual_time.cpp \
$(NULL)
libopenthread_posix_a_LIBADD = \
$(call ot_list_objects,$(top_builddir)/src/lib/url/libopenthread-url.a) \
$(call ot_list_objects,$(top_builddir)/src/lib/platform/libopenthread-platform.a) \
$(NULL)
noinst_HEADERS = \
hdlc_interface.hpp \
openthread-posix-config.h \
@@ -77,7 +83,7 @@ if OPENTHREAD_BUILD_COVERAGE
CLEANFILES = $(wildcard *.gcda *.gcno)
endif # OPENTHREAD_BUILD_COVERAGE
check_PROGRAMS = test-settings test-radio-url
check_PROGRAMS = test-settings
test_settings_CPPFLAGS = \
-I$(top_srcdir)/include \
@@ -92,22 +98,8 @@ test_settings_SOURCES = \
settings.cpp \
$(NULL)
test_radio_url_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/src/posix/platform/include \
-DOPENTHREAD_CONFIG_LOG_PLATFORM=0 \
-DSELF_TEST \
$(NULL)
test_radio_url_SOURCES = \
radio_url.cpp \
$(NULL)
TESTS = \
test-settings \
test-radio-url \
$(NULL)
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
+14 -14
View File
@@ -138,30 +138,30 @@ HdlcInterface::HdlcInterface(SpinelInterface::ReceiveFrameCallback aCallback,
{
}
otError HdlcInterface::Init(Arguments &aArguments)
otError HdlcInterface::Init(const RadioUrl &aRadioUrl)
{
otError error = OT_ERROR_NONE;
struct stat st;
VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY);
VerifyOrDie(stat(aArguments.GetPath(), &st) == 0, OT_EXIT_INVALID_ARGUMENTS);
VerifyOrDie(stat(aRadioUrl.GetPath(), &st) == 0, OT_EXIT_INVALID_ARGUMENTS);
if (S_ISCHR(st.st_mode))
{
mSockFd = OpenFile(aArguments.GetPath(), aArguments);
mSockFd = OpenFile(aRadioUrl);
VerifyOrExit(mSockFd != -1, error = OT_ERROR_INVALID_ARGS);
}
#if OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
else if (S_ISREG(st.st_mode))
{
mSockFd = ForkPty(aArguments.GetPath(), aArguments.GetValue("forkpty-arg"));
mSockFd = ForkPty(aRadioUrl.GetPath(), aRadioUrl.GetValue("forkpty-arg"));
VerifyOrExit(mSockFd != -1, error = OT_ERROR_INVALID_ARGS);
}
#endif // OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
else
{
otLogCritPlat("Radio file '%s' not supported", aArguments.GetPath());
otLogCritPlat("Radio file '%s' not supported", aRadioUrl.GetPath());
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
@@ -409,12 +409,12 @@ exit:
return error;
}
int HdlcInterface::OpenFile(const char *aFile, Arguments &aArguments)
int HdlcInterface::OpenFile(const RadioUrl &aRadioUrl)
{
int fd = -1;
int rval = 0;
fd = open(aFile, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
fd = open(aRadioUrl.GetPath(), O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
if (fd == -1)
{
perror("open uart failed");
@@ -436,7 +436,7 @@ int HdlcInterface::OpenFile(const char *aFile, Arguments &aArguments)
tios.c_cflag = CS8 | HUPCL | CREAD | CLOCAL;
if ((value = aArguments.GetValue("uart-parity")) != nullptr)
if ((value = aRadioUrl.GetValue("uart-parity")) != nullptr)
{
if (strncmp(value, "odd", 3) == 0)
{
@@ -453,7 +453,7 @@ int HdlcInterface::OpenFile(const char *aFile, Arguments &aArguments)
}
}
if ((value = aArguments.GetValue("uart-stop")) != nullptr)
if ((value = aRadioUrl.GetValue("uart-stop")) != nullptr)
{
stopBit = atoi(value);
}
@@ -471,7 +471,7 @@ int HdlcInterface::OpenFile(const char *aFile, Arguments &aArguments)
break;
}
if ((value = aArguments.GetValue("uart-baudrate")))
if ((value = aRadioUrl.GetValue("uart-baudrate")))
{
baudrate = static_cast<uint32_t>(atoi(value));
}
@@ -563,7 +563,7 @@ int HdlcInterface::OpenFile(const char *aFile, Arguments &aArguments)
break;
}
if (aArguments.GetValue("uart-flow-control") != nullptr)
if (aRadioUrl.GetValue("uart-flow-control") != nullptr)
{
tios.c_cflag |= CRTSCTS;
}
@@ -583,7 +583,7 @@ exit:
}
#if OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
int HdlcInterface::ForkPty(const char *aCommand, const char *aArguments)
int HdlcInterface::ForkPty(const char *aCommand, const char *aRadioUrl)
{
int fd = -1;
int pid = -1;
@@ -604,13 +604,13 @@ int HdlcInterface::ForkPty(const char *aCommand, const char *aArguments)
const int kMaxCommand = 255;
char cmd[kMaxCommand];
if (aArguments == nullptr)
if (aRadioUrl == nullptr)
{
rval = snprintf(cmd, sizeof(cmd), "exec %s", aCommand);
}
else
{
rval = snprintf(cmd, sizeof(cmd), "exec %s %s", aCommand, aArguments);
rval = snprintf(cmd, sizeof(cmd), "exec %s %s", aCommand, aRadioUrl);
}
VerifyOrExit(rval > 0 && static_cast<size_t>(rval) < sizeof(cmd),
fprintf(stderr, "NCP file and configuration is too long!");
+4 -4
View File
@@ -74,14 +74,14 @@ public:
*
* @note This method should be called before reading and sending spinel frames to the interface.
*
* @param[in] aArguments Arguments parsed from radio url.
* @param[in] aRadioUrl RadioUrl parsed from radio url.
*
* @retval OT_ERROR_NONE The interface is initialized successfully
* @retval OT_ERROR_ALREADY The interface is already initialized.
* @retval OT_ERROR_INVALID_ARGS The UART device or executable cannot be found or failed to open/run.
*
*/
otError Init(Arguments &aArguments);
otError Init(const RadioUrl &aRadioUrl);
/**
* This method deinitializes the interface to the RCP.
@@ -198,9 +198,9 @@ private:
static void HandleHdlcFrame(void *aContext, otError aError);
void HandleHdlcFrame(otError aError);
static int OpenFile(const char *aFile, Arguments &aArguments);
static int OpenFile(const RadioUrl &aRadioUrl);
#if OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
static int ForkPty(const char *aCommand, const char *aArguments);
static int ForkPty(const char *aCommand, const char *aRadioUrl);
#endif
enum
@@ -64,12 +64,6 @@ enum
32, ///< Default smallest SPI packet size we can receive in a single transaction.
};
/**
* This structure represents the radio URL.
*
*/
typedef struct otPosixRadioArguments otPosixRadioArguments;
/**
* This structure represents platform specific configurations.
*
+1 -1
View File
@@ -166,7 +166,7 @@ void platformAlarmAdvanceNow(uint64_t aDelta);
* @param[in] aPlatformConfig Platform configuration structure.
*
*/
void platformRadioInit(otPosixRadioArguments *aArguments);
void platformRadioInit(otUrl *aRadioUrl);
/**
* This function shuts down the radio service used by OpenThread.
+6 -6
View File
@@ -94,15 +94,15 @@ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
SuccessOrDie(sRadioSpinel.SetPromiscuous(aEnable));
}
void platformRadioInit(otPosixRadioArguments *aArguments)
void platformRadioInit(otUrl *aRadioUrl)
{
ot::Posix::Arguments *args = reinterpret_cast<ot::Posix::Arguments *>(aArguments);
bool resetRadio = (args->GetValue("no-reset") == nullptr);
bool restoreDataset = (args->GetValue("ncp-dataset") != nullptr);
ot::Posix::RadioUrl &radioUrl = *static_cast<ot::Posix::RadioUrl *>(aRadioUrl);
bool resetRadio = (radioUrl.GetValue("no-reset") == nullptr);
bool restoreDataset = (radioUrl.GetValue("ncp-dataset") != nullptr);
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
uint8_t channel = ot::Radio::kChannelMin;
int8_t power = ot::Posix::MaxPowerTable::kPowerDefault;
const char *maxPowerTable = args->GetValue("max-power-table");
const char *maxPowerTable = radioUrl.GetValue("max-power-table");
if (maxPowerTable != nullptr)
{
@@ -126,7 +126,7 @@ void platformRadioInit(otPosixRadioArguments *aArguments)
}
#endif
SuccessOrDie(sRadioSpinel.GetSpinelInterface().Init(*args));
SuccessOrDie(sRadioSpinel.GetSpinelInterface().Init(radioUrl));
sRadioSpinel.Init(resetRadio, restoreDataset);
}
+3 -134
View File
@@ -29,7 +29,6 @@
#include "posix/platform/radio_url.hpp"
#include <stdio.h>
#include <string.h>
#include <openthread/openthread-system.h>
@@ -96,142 +95,12 @@ const char *otSysGetRadioUrlHelpString(void)
namespace ot {
namespace Posix {
Arguments::Arguments(const char *aUrl)
RadioUrl::RadioUrl(const char *aUrl)
{
char *url = &mUrl[0];
mPath = nullptr;
mStart = nullptr;
mEnd = nullptr;
VerifyOrExit(aUrl != nullptr, OT_NOOP);
VerifyOrExit(strnlen(aUrl, sizeof(mUrl)) < sizeof(mUrl), OT_NOOP);
VerifyOrDie(strnlen(aUrl, sizeof(mUrl)) < sizeof(mUrl), OT_EXIT_INVALID_ARGUMENTS);
strncpy(mUrl, aUrl, sizeof(mUrl) - 1);
url = strstr(url, "://");
VerifyOrExit(url != nullptr, OT_NOOP);
url += sizeof("://") - 1;
mPath = url;
mStart = strstr(url, "?");
if (mStart != nullptr)
{
mStart[0] = '\0';
mStart++;
mEnd = mStart + strlen(mStart);
for (char *cur = strtok(mStart, "&"); cur != nullptr; cur = strtok(nullptr, "&"))
;
}
else
{
mEnd = url + strlen(url);
mStart = mEnd;
}
exit:
return;
}
const char *Arguments::GetValue(const char *aName, const char *aLastValue)
{
const char * rval = nullptr;
const size_t len = strlen(aName);
char * start = (aLastValue == nullptr ? mStart : (const_cast<char *>(aLastValue) + strlen(aLastValue) + 1));
while (start < mEnd)
{
char *last = nullptr;
if (!strncmp(aName, start, len))
{
if (start[len] == '=')
{
ExitNow(rval = &start[len + 1]);
}
else if (start[len] == '&' || start[len] == '\0')
{
ExitNow(rval = "");
}
}
last = start;
start = last + strlen(last) + 1;
}
exit:
return rval;
SuccessOrDie(Url::Url::Init(mUrl));
}
} // namespace Posix
} // namespace ot
#ifndef SELF_TEST
#define SELF_TEST 0
#endif
#if SELF_TEST
#include <assert.h>
void TestSimple()
{
char url[] = "spinel:///dev/ttyUSB0?baudrate=115200";
ot::Posix::Arguments args(url);
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
assert(!strcmp(args.GetValue("baudrate"), "115200"));
printf("PASS %s\r\n", __func__);
}
void TestSimpleNoArguments()
{
char url[] = "spinel:///dev/ttyUSB0";
ot::Posix::Arguments args(url);
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
printf("PASS %s\r\n", __func__);
}
void TestMultipleProtocols()
{
char url[] = "spinel+spi:///dev/ttyUSB0?baudrate=115200";
ot::Posix::Arguments args(url);
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
assert(!strcmp(args.GetValue("baudrate"), "115200"));
printf("PASS %s\r\n", __func__);
}
void TestMultipleProtocolsAndDuplicateParameters()
{
char url[] = "spinel+exec:///path/to/ot-rcp?arg=1&arg=arg2&arg=3";
ot::Posix::Arguments args(url);
const char * arg = nullptr;
assert(!strcmp(args.GetPath(), "/path/to/ot-rcp"));
arg = args.GetValue("arg");
assert(!strcmp(arg, "1"));
arg = args.GetValue("arg", arg);
assert(!strcmp(arg, "arg2"));
arg = args.GetValue("arg", arg);
assert(!strcmp(arg, "3"));
printf("PASS %s\r\n", __func__);
}
int main()
{
TestSimple();
TestSimpleNoArguments();
TestMultipleProtocols();
TestMultipleProtocolsAndDuplicateParameters();
return 0;
}
#endif // SELF_TEST
+9 -24
View File
@@ -34,37 +34,25 @@
#include <openthread/openthread-system.h>
struct otPosixRadioArguments
{
const char *mPath; ///< The path to the executable or device
};
#include "lib/url/url.hpp"
namespace ot {
namespace Posix {
class Arguments : public otPosixRadioArguments
/**
* This class implements the radio URL processing.
*
*/
class RadioUrl : public ot::Url::Url
{
public:
Arguments(const char *aUrl);
/**
* This method gets the path in url
* This constructor initializes the object.
*
* @returns The path in url.
* @param[in] aUrl The null-terminated URL string.
*
*/
const char *GetPath(void) const { return mPath; }
/**
* This method returns the url agument value.
*
* @param[in] aName Argument name.
* @param[in] aLastValue The last iterated argument value, nullptr for first value.
*
* @returns The argument value.
*
*/
const char *GetValue(const char *aName, const char *aLastValue = nullptr);
RadioUrl(const char *aUrl);
private:
enum
@@ -72,9 +60,6 @@ private:
kRadioUrlMaxSize = 512,
};
char mUrl[kRadioUrlMaxSize];
char *mStart;
char *mEnd;
};
} // namespace Posix
+12 -12
View File
@@ -91,7 +91,7 @@ SpiInterface::SpiInterface(SpinelInterface::ReceiveFrameCallback aCallback,
{
}
otError SpiInterface::Init(Arguments &aArguments)
otError SpiInterface::Init(const RadioUrl &aRadioUrl)
{
const char *spiGpioIntDevice;
const char *spiGpioResetDevice;
@@ -105,14 +105,14 @@ otError SpiInterface::Init(Arguments &aArguments)
uint8_t spiSmallPacketSize = OT_PLATFORM_CONFIG_SPI_DEFAULT_SMALL_PACKET_SIZE;
const char *value;
spiGpioIntDevice = aArguments.GetValue("gpio-int-device");
spiGpioResetDevice = aArguments.GetValue("gpio-reset-device");
spiGpioIntDevice = aRadioUrl.GetValue("gpio-int-device");
spiGpioResetDevice = aRadioUrl.GetValue("gpio-reset-device");
if (!spiGpioIntDevice || !spiGpioResetDevice)
{
DieNow(OT_EXIT_INVALID_ARGUMENTS);
}
if ((value = aArguments.GetValue("gpio-int-line")))
if ((value = aRadioUrl.GetValue("gpio-int-line")))
{
spiGpioIntLine = static_cast<uint8_t>(atoi(value));
}
@@ -120,7 +120,7 @@ otError SpiInterface::Init(Arguments &aArguments)
{
DieNow(OT_EXIT_INVALID_ARGUMENTS);
}
if ((value = aArguments.GetValue("gpio-reset-line")))
if ((value = aRadioUrl.GetValue("gpio-reset-line")))
{
spiGpioResetLine = static_cast<uint8_t>(atoi(value));
}
@@ -128,27 +128,27 @@ otError SpiInterface::Init(Arguments &aArguments)
{
DieNow(OT_EXIT_INVALID_ARGUMENTS);
}
if ((value = aArguments.GetValue("spi-mode")))
if ((value = aRadioUrl.GetValue("spi-mode")))
{
spiMode = static_cast<uint8_t>(atoi(value));
}
if ((value = aArguments.GetValue("spi-speed")))
if ((value = aRadioUrl.GetValue("spi-speed")))
{
spiSpeed = static_cast<uint32_t>(atoi(value));
}
if ((value = aArguments.GetValue("spi-reset-delay")))
if ((value = aRadioUrl.GetValue("spi-reset-delay")))
{
spiResetDelay = static_cast<uint32_t>(atoi(value));
}
if ((value = aArguments.GetValue("spi-cs-delay")))
if ((value = aRadioUrl.GetValue("spi-cs-delay")))
{
spiCsDelay = static_cast<uint16_t>(atoi(value));
}
if ((value = aArguments.GetValue("spi-align-allowance")))
if ((value = aRadioUrl.GetValue("spi-align-allowance")))
{
spiAlignAllowance = static_cast<uint8_t>(atoi(value));
}
if ((value = aArguments.GetValue("spi-small-packet")))
if ((value = aRadioUrl.GetValue("spi-small-packet")))
{
spiSmallPacketSize = static_cast<uint8_t>(atoi(value));
}
@@ -170,7 +170,7 @@ otError SpiInterface::Init(Arguments &aArguments)
}
InitResetPin(spiGpioResetDevice, spiGpioResetLine);
InitSpiDev(aArguments.GetPath(), spiMode, spiSpeed);
InitSpiDev(aRadioUrl.GetPath(), spiMode, spiSpeed);
// Reset RCP chip.
TrigerReset();
+2 -2
View File
@@ -79,14 +79,14 @@ public:
*
* @note This method should be called before reading and sending spinel frames to the interface.
*
* @param[in] aArguments Arguments parsed from radio url.
* @param[in] aRadioUrl Arguments parsed from radio url.
*
* @retval OT_ERROR_NONE The interface is initialized successfully.
* @retval OT_ERROR_ALREADY The interface is already initialized.
* @retval OT_ERROR_INVALID_ARGS The UART device or executable cannot be found or failed to open/run.
*
*/
otError Init(Arguments &aArguments);
otError Init(const RadioUrl &aRadioUrl);
/**
* This method deinitializes the interface to the RCP.
+5 -5
View File
@@ -49,16 +49,16 @@ uint64_t gNodeId = 0;
otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
{
otInstance * instance = nullptr;
ot::Posix::Arguments args(aPlatformConfig->mRadioUrl);
otInstance * instance = nullptr;
ot::Posix::RadioUrl radioUrl(aPlatformConfig->mRadioUrl);
#if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeInit(static_cast<uint16_t>(atoi(args.GetValue("forkpty-arg"))));
virtualTimeInit(static_cast<uint16_t>(atoi(radioUrl.GetValue("forkpty-arg"))));
#endif
VerifyOrDie(args.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
VerifyOrDie(radioUrl.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
platformAlarmInit(aPlatformConfig->mSpeedUpFactor, aPlatformConfig->mRealTimeSignal);
platformRadioInit(&args);
platformRadioInit(&radioUrl);
platformRandomInit();
instance = otInstanceInitSingle();