Refactor external transports (#179)

* Refactor stream framing code

* Added custom transports API

* Renaming serial_io to framing_io

* Refactor

* Move framing to runtime


Update custom callbacks API


Fix


Minor fixes

* Updates

* Add test

* Update test

* Fix Ralph issue

* Remove old external transport approach

* Revert "Remove old external transport approach"

This reverts commit dbd94b632b2fcd4325868d980339b0940b75f33e.

* Add deprecation message

* Fix leak in test

Fix leak in test


Fix


Fix test

* Fix windows test

* Minor fix

* Update

* Remove dead code

* Remove old transports approach

* Address comments

* Update test/transport/custom_comm/CustomComm.cpp

Co-authored-by: Jose Antonio Moral <joseantoniomoralparras@gmail.com>

* Update test/transport/custom_comm/CustomComm.hpp

Co-authored-by: Jose Antonio Moral <joseantoniomoralparras@gmail.com>

* Update test/transport/custom_comm/CustomComm.hpp

Co-authored-by: Jose Antonio Moral <joseantoniomoralparras@gmail.com>

* Update test/transport/custom_comm/CustomComm.hpp

Co-authored-by: Jose Antonio Moral <joseantoniomoralparras@gmail.com>

* Address comments

* Address comments

* Address comments

Co-authored-by: Jose Antonio Moral <joseantoniomoralparras@gmail.com>
This commit is contained in:
Pablo Garrido 2021-02-09 11:28:04 +01:00 committed by GitHub
parent 84bad2defe
commit 22bff80e0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 841 additions and 406 deletions

View File

@ -46,6 +46,7 @@ option(UCLIENT_PROFILE_DISCOVERY "Enable discovery profile." ON)
option(UCLIENT_PROFILE_UDP "Enable UDP transport." ON)
option(UCLIENT_PROFILE_TCP "Enable TCP transport." ON)
option(UCLIENT_PROFILE_SERIAL "Enable Serial transport." ON)
option(UCLIENT_PROFILE_STREAM_FRAMING "Enable stream framing protocol." ON)
set(UCLIENT_MAX_OUTPUT_BEST_EFFORT_STREAMS 1 CACHE STRING "Set the maximum number of output best-effort streams for session.")
set(UCLIENT_MAX_OUTPUT_RELIABLE_STREAMS 1 CACHE STRING "Set the maximum number of output reliable streams for session.")
set(UCLIENT_MAX_INPUT_BEST_EFFORT_STREAMS 1 CACHE STRING "Set the maximum number of input best-effort streams for session.")
@ -57,6 +58,9 @@ set(UCLIENT_UDP_TRANSPORT_MTU 512 CACHE STRING "Set the UDP transport MTU.")
set(UCLIENT_TCP_TRANSPORT_MTU 512 CACHE STRING "Set the TCP transport MTU.")
set(UCLIENT_SERIAL_TRANSPORT_MTU 512 CACHE STRING "Set the Serial transport MTU.")
option(UCLIENT_PROFILE_CUSTOM_TRANSPORT "Enable Custom transport." ON)
set(UCLIENT_CUSTOM_TRANSPORT_MTU 512 CACHE STRING "Set the Custom transport MTU.")
###############################################################################
# Dependencies
###############################################################################
@ -130,43 +134,30 @@ if(UCLIENT_PLATFORM_LINUX OR UCLIENT_PLATFORM_NUTTX OR UCLIENT_PLATFORM_ZEPHYR)
set(UCLIENT_PLATFORM_POSIX ON)
endif()
# Check external transport.
option(UCLIENT_EXTERNAL_TCP "Enable external serial transport." OFF)
option(UCLIENT_EXTERNAL_UDP "Enable external serial transport." OFF)
option(UCLIENT_EXTERNAL_SERIAL "Enable external serial transport." OFF)
# Transport sources.
set(_transport_src)
if(UCLIENT_PROFILE_UDP)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport.c)
if(UCLIENT_EXTERNAL_UDP)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_external.c)
else()
if(UCLIENT_PLATFORM_POSIX)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_posix.c)
elseif(UCLIENT_PLATFORM_POSIX_NOPOLL)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_posix_nopoll.c)
elseif(UCLIENT_PLATFORM_WINDOWS)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_windows.c)
elseif(UCLIENT_PLATFORM_FREERTOS_PLUS_TCP)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_freertos_plus_tcp.c)
endif()
if(UCLIENT_PLATFORM_POSIX)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_posix.c)
elseif(UCLIENT_PLATFORM_POSIX_NOPOLL)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_posix_nopoll.c)
elseif(UCLIENT_PLATFORM_WINDOWS)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_windows.c)
elseif(UCLIENT_PLATFORM_FREERTOS_PLUS_TCP)
list(APPEND _transport_src src/c/profile/transport/ip/udp/udp_transport_freertos_plus_tcp.c)
endif()
endif()
if(UCLIENT_PROFILE_TCP)
list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport.c)
if(UCLIENT_EXTERNAL_TCP)
list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_external.c)
else()
if(UCLIENT_PLATFORM_POSIX)
list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_posix.c)
elseif(UCLIENT_PLATFORM_WINDOWS)
list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_windows.c)
elseif(UCLIENT_PLATFORM_FREERTOS_PLUS_TCP)
list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_freertos_plus_tcp.c)
endif()
if(UCLIENT_PLATFORM_POSIX)
list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_posix.c)
elseif(UCLIENT_PLATFORM_WINDOWS)
list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_windows.c)
elseif(UCLIENT_PLATFORM_FREERTOS_PLUS_TCP)
list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_freertos_plus_tcp.c)
endif()
endif()
@ -175,14 +166,10 @@ set(UCLIENT_PROFILE_SERIAL OFF)
endif()
if(UCLIENT_PROFILE_SERIAL)
set(UCLIENT_PROFILE_STREAM_FRAMING ON)
list(APPEND _transport_src src/c/profile/transport/serial/serial_transport.c)
list(APPEND _transport_src src/c/profile/transport/serial/serial_protocol.c)
if(UCLIENT_EXTERNAL_SERIAL)
list(APPEND _transport_src src/c/profile/transport/serial/serial_transport_external.c)
else()
if(UCLIENT_PLATFORM_POSIX)
list(APPEND _transport_src src/c/profile/transport/serial/serial_transport_posix.c)
endif()
if(UCLIENT_PLATFORM_POSIX)
list(APPEND _transport_src src/c/profile/transport/serial/serial_transport_posix.c)
endif()
endif()
@ -212,6 +199,10 @@ if(UCLIENT_PROFILE_DISCOVERY)
endif()
endif()
if(UCLIENT_PROFILE_CUSTOM_TRANSPORT)
list(APPEND _transport_src src/c/profile/transport/custom/custom_transport.c)
endif()
# Other sources
set(SRCS
src/c/core/session/stream/input_best_effort_stream.c
@ -235,6 +226,7 @@ set(SRCS
src/c/core/session/create_entities_xml.c
src/c/core/session/read_access.c
src/c/core/session/write_access.c
$<$<BOOL:${UCLIENT_PROFILE_STREAM_FRAMING}>:src/c/profile/transport/stream_framing/stream_framing_protocol.c>
$<$<OR:$<BOOL:${UCLIENT_VERBOSE_MESSAGE}>,$<BOOL:${UCLIENT_VERBOSE_SERIALIZATION}>>:src/c/core/log/log.c>
${_transport_src}
)
@ -376,6 +368,7 @@ if(UCLIENT_BUILD_TESTS)
add_subdirectory(test/unitary)
if(UCLIENT_PLATFORM_LINUX)
add_subdirectory(test/transport/custom_comm)
add_subdirectory(test/transport/serial_comm)
endif()
endif()

View File

@ -25,6 +25,7 @@
#cmakedefine UCLIENT_PROFILE_UDP
#cmakedefine UCLIENT_PROFILE_TCP
#cmakedefine UCLIENT_PROFILE_SERIAL
#cmakedefine UCLIENT_PROFILE_CUSTOM_TRANSPORT
#cmakedefine UCLIENT_PLATFORM_POSIX
#cmakedefine UCLIENT_PLATFORM_POSIX_NOPOLL
@ -54,5 +55,8 @@
#ifdef UCLIENT_PROFILE_SERIAL
#define UXR_CONFIG_SERIAL_TRANSPORT_MTU @UCLIENT_SERIAL_TRANSPORT_MTU@
#endif
#ifdef UCLIENT_PROFILE_CUSTOM_TRANSPORT
#define UCLIENT_CUSTOM_TRANSPORT_MTU @UCLIENT_CUSTOM_TRANSPORT_MTU@
#endif
#endif // _UXR_CLIENT_CONFIG_H_

View File

@ -0,0 +1,85 @@
// Copyright 2020 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// 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.
#ifndef UXR_CLIENT_CUSTOM_TRANSPORT_H_
#define UXR_CLIENT_CUSTOM_TRANSPORT_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <uxr/client/core/communication/communication.h>
#include <uxr/client/config.h>
#include <uxr/client/profile/transport/stream_framing/stream_framing_protocol.h>
#include <uxr/client/visibility.h>
struct uxrCustomTransport;
typedef bool (*open_custom_func)(struct uxrCustomTransport*);
typedef bool (*close_custom_func)(struct uxrCustomTransport*);
typedef size_t (*write_custom_func)(struct uxrCustomTransport*, const uint8_t*, size_t, uint8_t*);
typedef size_t (*read_custom_func)(struct uxrCustomTransport*, uint8_t*, size_t, int, uint8_t*);
typedef struct uxrCustomTransport
{
uint8_t buffer[UCLIENT_CUSTOM_TRANSPORT_MTU];
bool framing;
uxrFramingIO framing_io;
open_custom_func open;
close_custom_func close;
write_custom_func write;
read_custom_func read;
uxrCommunication comm;
void * args;
} uxrCustomTransport;
/**
* @brief Set a Custom transport callbacks.
* @param transport The uninitialized transport structure used for managing the transport.
* @param open Open callback.
* @param close Close callback.
* @param write Write callback.
* @param read Read callback.
*/
UXRDLLAPI void uxr_set_custom_transport_callbacks(uxrCustomTransport* transport,
bool framing,
open_custom_func open,
close_custom_func close,
write_custom_func write,
read_custom_func read);
/**
* @brief Initializes a Custom transport.
* @param transport The transport structure used for managing the transport.
* Callbacks must be set.
* @param open_args Arguments for the open function.
* @return `true` in case of successful initialization. `false` in other case.
*/
UXRDLLAPI bool uxr_init_custom_transport(uxrCustomTransport* transport,
void * args);
/**
* @brief Closes a Custom transport.
* @param transport The transport structure.
* @return `true` in case of successful closing. `false` in other case.
*/
UXRDLLAPI bool uxr_close_custom_transport(uxrCustomTransport* transport);
#ifdef __cplusplus
}
#endif
#endif // UXR_CLIENT_CUSTOM_TRANSPORT_H_

View File

@ -1,20 +0,0 @@
#ifndef UXR_CLIENT_PROFILE_TRANSPORT_IP_TCP_EXTERNAL_H_
#define UXR_CLIENT_PROFILE_TRANSPORT_IP_TCP_EXTERNAL_H_
#ifdef __cplusplus
extern "C"
{
#endif
// Place here your includes
typedef struct uxrTCPPlatform
{
// Place here your platform data
} uxrTCPPlatform;
#ifdef __cplusplus
}
#endif
#endif // UXR_CLIENT_PROFILE_TRANSPORT_IP_TCP_EXTERNAL_H_

View File

@ -1,20 +0,0 @@
#ifndef UXR_CLIENT_PROFILE_TRANSPORT_IP_UDP_EXTERNAL_H_
#define UXR_CLIENT_PROFILE_TRANSPORT_IP_UDP_EXTERNAL_H_
#ifdef __cplusplus
extern "C"
{
#endif
// Place here your includes
typedef struct uxrUDPPlatform
{
// Place here your platform data
} uxrUDPPlatform;
#ifdef __cplusplus
}
#endif
#endif // UXR_CLIENT_PROFILE_TRANSPORT_IP_UDP_EXTERNAL_H_

View File

@ -21,7 +21,7 @@ extern "C"
#endif
#include <uxr/client/core/communication/communication.h>
#include <uxr/client/profile/transport/serial/serial_protocol.h>
#include <uxr/client/profile/transport/stream_framing/stream_framing_protocol.h>
#include <uxr/client/config.h>
#include <uxr/client/visibility.h>
#include <uxr/client/transport.h>
@ -29,7 +29,7 @@ extern "C"
typedef struct uxrSerialTransport
{
uint8_t buffer[UXR_CONFIG_SERIAL_TRANSPORT_MTU];
uxrSerialIO serial_io;
uxrFramingIO framing_io;
uint8_t remote_addr;
uxrCommunication comm;
struct uxrSerialPlatform platform;

View File

@ -1,20 +0,0 @@
#ifndef UXR_CLIENT_PROFILE_TRANSPORT_SERIAL_EXTERNAL_H_
#define UXR_CLIENT_PROFILE_TRANSPORT_SERIAL_EXTERNAL_H_
#ifdef __cplusplus
extern "C"
{
#endif
// Place here your includes
typedef struct uxrSerialPlatform
{
// Place here your platform data
} uxrSerialPlatform;
#ifdef __cplusplus
}
#endif
#endif // UXR_CLIENT_PROFILE_TRANSPORT_SERIAL_EXTERNAL_H_

View File

@ -22,15 +22,15 @@ extern "C"
#include <uxr/client/profile/transport/serial/serial_transport.h>
bool uxr_init_serial_platform(struct uxrSerialPlatform* platform, const int fd, uint8_t remote_addr, uint8_t local_addr);
bool uxr_close_serial_platform(struct uxrSerialPlatform* platform);
bool uxr_init_serial_platform(void* args, const int fd, uint8_t remote_addr, uint8_t local_addr);
bool uxr_close_serial_platform(void* args);
size_t uxr_write_serial_data_platform(struct uxrSerialPlatform* platform,
uint8_t* buf,
size_t uxr_write_serial_data_platform(void* args,
const uint8_t* buf,
size_t len,
uint8_t* errcode);
size_t uxr_read_serial_data_platform(struct uxrSerialPlatform* platform,
size_t uxr_read_serial_data_platform(void* args,
uint8_t* buf,
size_t len,
int timeout,

View File

@ -27,18 +27,18 @@ extern "C"
typedef enum uxrSerialInputState
{
UXR_SERIAL_UNINITIALIZED,
UXR_SERIAL_READING_SRC_ADDR,
UXR_SERIAL_READING_DST_ADDR,
UXR_SERIAL_READING_LEN_LSB,
UXR_SERIAL_READING_LEN_MSB,
UXR_SERIAL_READING_PAYLOAD,
UXR_SERIAL_READING_CRC_LSB,
UXR_SERIAL_READING_CRC_MSB,
UXR_FRAMING_UNINITIALIZED,
UXR_FRAMING_READING_SRC_ADDR,
UXR_FRAMING_READING_DST_ADDR,
UXR_FRAMING_READING_LEN_LSB,
UXR_FRAMING_READING_LEN_MSB,
UXR_FRAMING_READING_PAYLOAD,
UXR_FRAMING_READING_CRC_LSB,
UXR_FRAMING_READING_CRC_MSB,
} uxrSerialInputState;
typedef struct uxrSerialIO
typedef struct uxrFramingIO
{
uxrSerialInputState state;
uint8_t local_addr;
@ -53,7 +53,7 @@ typedef struct uxrSerialIO
uint8_t wb[42];
uint8_t wb_pos;
} uxrSerialIO;
} uxrFramingIO;
#ifdef __cplusplus
}

View File

@ -52,4 +52,8 @@
#include <uxr/client/profile/transport/serial/serial_transport.h>
#endif //UCLIENT_PROFILE_SERIAL
#ifdef UCLIENT_PROFILE_CUSTOM_TRANSPORT
#include <uxr/client/profile/transport/custom/custom_transport.h>
#endif //UCLIENT_PROFILE_CUSTOM_TRANSPORT
#endif // UXR_CLIENT_TRANSPORT_H_

View File

@ -0,0 +1,155 @@
#include <uxr/client/profile/transport/custom/custom_transport.h>
#include "../stream_framing/stream_framing_protocol.h"
#include <uxr/client/util/time.h>
/*******************************************************************************
* Static members.
*******************************************************************************/
static uint8_t error_code;
/*******************************************************************************
* Private function definitions.
*******************************************************************************/
static bool send_custom_msg(void* instance, const uint8_t* buf, size_t len)
{
bool rv = false;
uxrCustomTransport* transport = (uxrCustomTransport*)instance;
uint8_t errcode;
size_t bytes_written = 0;
if (transport->framing)
{
bytes_written = uxr_write_framed_msg(&transport->framing_io,
(uxr_write_cb) transport->write,
transport,
buf,
len,
0x00,
&errcode);
}
else
{
bytes_written = transport->write(transport, buf, len, &errcode);
}
if ((0 < bytes_written) && (bytes_written == len))
{
rv = true;
}
else
{
error_code = errcode;
}
return rv;
}
static bool recv_custom_msg(void* instance, uint8_t** buf, size_t* len, int timeout)
{
bool rv = false;
uxrCustomTransport* transport = (uxrCustomTransport*)instance;
size_t bytes_read = 0;
do
{
int64_t time_init = uxr_millis();
uint8_t remote_addr = 0x00;
uint8_t errcode;
if (transport->framing)
{
bytes_read = uxr_read_framed_msg(&transport->framing_io,
(uxr_read_cb) transport->read,
transport,
transport->buffer,
sizeof(transport->buffer),
&remote_addr,
timeout,
&errcode);
}
else
{
bytes_read = transport->read(transport,
transport->buffer,
sizeof(transport->buffer),
timeout,
&errcode);
}
if ((0 < bytes_read) && (remote_addr == 0x00))
{
*len = bytes_read;
*buf = transport->buffer;
rv = true;
}
else
{
error_code = errcode;
}
timeout -= (int)(uxr_millis() - time_init);
}
while ((0 == bytes_read) && (0 < timeout));
return rv;
}
static uint8_t get_custom_error(void)
{
return error_code;
}
/*******************************************************************************
* Public function definitions.
*******************************************************************************/
void uxr_set_custom_transport_callbacks(uxrCustomTransport* transport,
bool framing,
open_custom_func open,
close_custom_func close,
write_custom_func write,
read_custom_func read)
{
transport->framing = framing;
transport->open = open;
transport->close = close;
transport->write = write;
transport->read = read;
}
bool uxr_init_custom_transport(uxrCustomTransport* transport,
void * args)
{
bool rv = false;
if (transport->open == NULL ||
transport->close == NULL ||
transport->write == NULL ||
transport->read == NULL)
{
return rv;
}
transport->args = args;
if (transport->open(transport))
{
if (transport->framing)
{
/* Init FramingIO. */
uxr_init_framing_io(&transport->framing_io, 0x00);
}
/* Setup interface. */
transport->comm.instance = (void*)transport;
transport->comm.send_msg = send_custom_msg;
transport->comm.recv_msg = recv_custom_msg;
transport->comm.comm_error = get_custom_error;
transport->comm.mtu = UCLIENT_CUSTOM_TRANSPORT_MTU;
rv = true;
}
return rv;
}
bool uxr_close_custom_transport(uxrCustomTransport* transport)
{
return transport->close(transport);
}

View File

@ -1,48 +0,0 @@
#include <uxr/client/profile/transport/ip/tcp/tcp_transport_external.h>
#include "tcp_transport_internal.h"
// Place here your includes
bool uxr_init_tcp_platform(
struct uxrTCPPlatform* platform,
uxrIpProtocol ip_protocol,
const char* ip,
const char* port)
{
// Place here your initialization platform code
// Return true if success
}
bool uxr_close_tcp_platform(
struct uxrTCPPlatform* platform)
{
// Place here your closing platform code
// Return true if success
}
size_t uxr_write_tcp_data_platform(
struct uxrTCPPlatform* platform,
const uint8_t* buf,
size_t len,
uint8_t* errcode)
{
// Place here your writing bytes platform code
// Return number of bytes written
}
size_t uxr_read_tcp_data_platform(
struct uxrTCPPlatform* platform,
uint8_t* buf,
size_t len,
int timeout,
uint8_t* errcode)
{
// Place here your reading bytes platform code
// Return number of bytes read (max bytes: len)
}
void uxr_disconnect_tcp_platform(
struct uxrTCPPlatform* platform)
{
// Place here your disconnection platform code
}

View File

@ -1,42 +0,0 @@
#include <uxr/client/profile/transport/ip/udp/udp_transport_external.h>
#include "udp_transport_internal.h"
// Place here your includes
bool uxr_init_udp_platform(
uxrUDPPlatform* platform,
uxrIpProtocol ip_protocol,
const char* ip,
const char* port)
{
// Place here your initialization platform code
// Return true if success
}
bool uxr_close_udp_platform(
uxrUDPPlatform* platform)
{
// Place here your closing platform code
// Return true if success
}
size_t uxr_write_udp_data_platform(
uxrUDPPlatform* platform,
const uint8_t* buf,
size_t len,
uint8_t* errcode)
{
// Place here your writing bytes platform code
// Return number of bytes written
}
size_t uxr_read_udp_data_platform(
uxrUDPPlatform* platform,
uint8_t* buf,
size_t len,
int timeout,
uint8_t* errcode)
{
// Place here your reading bytes platform code
// Return number of bytes read (max bytes: len)
}

View File

@ -1,5 +1,5 @@
#include <uxr/client/profile/transport/serial/serial_transport_platform.h>
#include "serial_protocol_internal.h"
#include "../stream_framing/stream_framing_protocol.h"
#include <uxr/client/util/time.h>
/*******************************************************************************
@ -23,7 +23,7 @@ static bool send_serial_msg(void* instance, const uint8_t* buf, size_t len)
uxrSerialTransport* transport = (uxrSerialTransport*)instance;
uint8_t errcode;
size_t bytes_written = uxr_write_serial_msg(&transport->serial_io,
size_t bytes_written = uxr_write_framed_msg(&transport->framing_io,
uxr_write_serial_data_platform,
&transport->platform,
buf,
@ -53,7 +53,7 @@ static bool recv_serial_msg(void* instance, uint8_t** buf, size_t* len, int time
int64_t time_init = uxr_millis();
uint8_t remote_addr;
uint8_t errcode;
bytes_read = uxr_read_serial_msg(&transport->serial_io,
bytes_read = uxr_read_framed_msg(&transport->framing_io,
uxr_read_serial_data_platform,
&transport->platform,
transport->buffer,
@ -97,8 +97,8 @@ bool uxr_init_serial_transport(uxrSerialTransport* transport,
/* Setup address. */
transport->remote_addr = remote_addr;
/* Init SerialIO. */
uxr_init_serial_io(&transport->serial_io, local_addr);
/* Init FramingIO. */
uxr_init_framing_io(&transport->framing_io, local_addr);
/* Setup interface. */
transport->comm.instance = (void*)transport;

View File

@ -1,28 +0,0 @@
#include <uxr/client/profile/transport/serial/serial_transport_external.h>
#include <uxr/client/profile/transport/serial/serial_transport_platform.h>
// Place here your includes
bool uxr_init_serial_platform(struct uxrSerialPlatform* platform, int fd, uint8_t remote_addr, uint8_t local_addr)
{
// Place here your initialization platform code
// Return true if success
}
bool uxr_close_serial_platform(struct uxrSerialPlatform* platform)
{
// Place here your closing platform code
// Return true if success
}
size_t uxr_write_serial_data_platform(uxrSerialPlatform* platform, uint8_t* buf, size_t len, uint8_t* errcode)
{
// Place here your writing bytes platform code
// Return number of bytes written
}
size_t uxr_read_serial_data_platform(uxrSerialPlatform* platform, uint8_t* buf, size_t len, int timeout, uint8_t* errcode)
{
// Place here your reading bytes platform code
// Return number of bytes read (max bytes: len)
}

View File

@ -4,11 +4,13 @@
#include <unistd.h>
#include <errno.h>
bool uxr_init_serial_platform(struct uxrSerialPlatform* platform, int fd, uint8_t remote_addr, uint8_t local_addr)
bool uxr_init_serial_platform(void* args, int fd, uint8_t remote_addr, uint8_t local_addr)
{
(void) remote_addr;
(void) local_addr;
struct uxrSerialPlatform* platform = (struct uxrSerialPlatform*) args;
/* Poll setup. */
platform->poll_fd.fd = fd;
platform->poll_fd.events = POLLIN;
@ -16,14 +18,16 @@ bool uxr_init_serial_platform(struct uxrSerialPlatform* platform, int fd, uint8_
return true;
}
bool uxr_close_serial_platform(struct uxrSerialPlatform* platform)
bool uxr_close_serial_platform(void* args)
{
struct uxrSerialPlatform* platform = (struct uxrSerialPlatform*) args;
return (-1 == platform->poll_fd.fd) ? true : (0 == close(platform->poll_fd.fd));
}
size_t uxr_write_serial_data_platform(uxrSerialPlatform* platform, uint8_t* buf, size_t len, uint8_t* errcode)
size_t uxr_write_serial_data_platform(void* args, const uint8_t* buf, size_t len, uint8_t* errcode)
{
size_t rv = 0;
struct uxrSerialPlatform* platform = (struct uxrSerialPlatform*) args;
ssize_t bytes_written = write(platform->poll_fd.fd, (void*)buf, (size_t)len);
if (-1 != bytes_written)
@ -38,9 +42,10 @@ size_t uxr_write_serial_data_platform(uxrSerialPlatform* platform, uint8_t* buf,
return rv;
}
size_t uxr_read_serial_data_platform(uxrSerialPlatform* platform, uint8_t* buf, size_t len, int timeout, uint8_t* errcode)
size_t uxr_read_serial_data_platform(void* args, uint8_t* buf, size_t len, int timeout, uint8_t* errcode)
{
size_t rv = 0;
struct uxrSerialPlatform* platform = (struct uxrSerialPlatform*) args;
int poll_rv = poll(&platform->poll_fd, 1, timeout);
if (0 < poll_rv)

View File

@ -1,4 +1,5 @@
#include "serial_protocol_internal.h"
#include <uxr/client/util/time.h>
#include "stream_framing_protocol.h"
#include <string.h>
/*******************************************************************************
@ -48,25 +49,25 @@ void uxr_update_crc(uint16_t* crc, const uint8_t data)
*crc = (*crc >> 8) ^ crc16_table[(*crc ^ data) & 0xFF];
}
bool uxr_get_next_octet(uxrSerialIO* serial_io, uint8_t* octet)
bool uxr_get_next_octet(uxrFramingIO* framing_io, uint8_t* octet)
{
bool rv = false;
*octet = 0;
if (serial_io->rb_head != serial_io->rb_tail)
if (framing_io->rb_head != framing_io->rb_tail)
{
if (UXR_FRAMING_ESC_FLAG != serial_io->rb[serial_io->rb_tail])
if (UXR_FRAMING_ESC_FLAG != framing_io->rb[framing_io->rb_tail])
{
*octet = serial_io->rb[serial_io->rb_tail];
serial_io->rb_tail = (uint8_t)((size_t)(serial_io->rb_tail + 1) % sizeof(serial_io->rb));
*octet = framing_io->rb[framing_io->rb_tail];
framing_io->rb_tail = (uint8_t)((size_t)(framing_io->rb_tail + 1) % sizeof(framing_io->rb));
rv = (UXR_FRAMING_BEGIN_FLAG != *octet);
}
else
{
uint8_t temp_tail = (uint8_t)((size_t)(serial_io->rb_tail + 1) % sizeof(serial_io->rb));
if (temp_tail != serial_io->rb_head)
uint8_t temp_tail = (uint8_t)((size_t)(framing_io->rb_tail + 1) % sizeof(framing_io->rb));
if (temp_tail != framing_io->rb_head)
{
*octet = serial_io->rb[temp_tail];
serial_io->rb_tail = (uint8_t)((size_t)(serial_io->rb_tail + 2) % sizeof(serial_io->rb));
*octet = framing_io->rb[temp_tail];
framing_io->rb_tail = (uint8_t)((size_t)(framing_io->rb_tail + 2) % sizeof(framing_io->rb));
if (UXR_FRAMING_BEGIN_FLAG != *octet)
{
*octet ^= UXR_FRAMING_XOR_FLAG;
@ -78,26 +79,26 @@ bool uxr_get_next_octet(uxrSerialIO* serial_io, uint8_t* octet)
return rv;
}
bool uxr_add_next_octet(uxrSerialIO* serial_io, uint8_t octet)
bool uxr_add_next_octet(uxrFramingIO* framing_io, uint8_t octet)
{
bool rv = false;
if (UXR_FRAMING_BEGIN_FLAG == octet || UXR_FRAMING_ESC_FLAG == octet)
{
if ((uint8_t)(serial_io->wb_pos + 1) < sizeof(serial_io->wb))
if ((uint8_t)(framing_io->wb_pos + 1) < sizeof(framing_io->wb))
{
serial_io->wb[serial_io->wb_pos] = UXR_FRAMING_ESC_FLAG;
serial_io->wb[serial_io->wb_pos + 1] = octet ^ UXR_FRAMING_XOR_FLAG;
serial_io->wb_pos = (uint8_t)(serial_io->wb_pos + 2);
framing_io->wb[framing_io->wb_pos] = UXR_FRAMING_ESC_FLAG;
framing_io->wb[framing_io->wb_pos + 1] = octet ^ UXR_FRAMING_XOR_FLAG;
framing_io->wb_pos = (uint8_t)(framing_io->wb_pos + 2);
rv = true;
}
}
else
{
if (serial_io->wb_pos < sizeof(serial_io->wb))
if (framing_io->wb_pos < sizeof(framing_io->wb))
{
serial_io->wb[serial_io->wb_pos] = octet;
serial_io->wb_pos = (uint8_t)(serial_io->wb_pos + 1);
framing_io->wb[framing_io->wb_pos] = octet;
framing_io->wb_pos = (uint8_t)(framing_io->wb_pos + 1);
rv = true;
}
}
@ -105,15 +106,36 @@ bool uxr_add_next_octet(uxrSerialIO* serial_io, uint8_t octet)
return rv;
}
void uxr_init_serial_io(uxrSerialIO* serial_io, uint8_t local_addr)
void uxr_init_framing_io(uxrFramingIO* framing_io, uint8_t local_addr)
{
serial_io->local_addr = local_addr;
serial_io->state = UXR_SERIAL_UNINITIALIZED;
serial_io->rb_head = 0;
serial_io->rb_tail = 0;
framing_io->local_addr = local_addr;
framing_io->state = UXR_FRAMING_UNINITIALIZED;
framing_io->rb_head = 0;
framing_io->rb_tail = 0;
}
size_t uxr_write_serial_msg(uxrSerialIO* serial_io,
bool uxr_framing_write_transport(uxrFramingIO* framing_io,
uxr_write_cb write_cb,
void* cb_arg,
uint8_t* errcode)
{
size_t bytes_written = 0;
size_t last_written = 0;
do {
last_written = write_cb(cb_arg, &framing_io->wb[bytes_written], framing_io->wb_pos - bytes_written, errcode);
bytes_written += last_written;
} while (bytes_written < framing_io->wb_pos && 0 < last_written);
if (bytes_written == framing_io->wb_pos)
{
framing_io->wb_pos = 0;
return true;
}
return false;
}
size_t uxr_write_framed_msg(uxrFramingIO* framing_io,
uxr_write_cb write_cb,
void* cb_arg,
const uint8_t* buf,
@ -122,14 +144,14 @@ size_t uxr_write_serial_msg(uxrSerialIO* serial_io,
uint8_t* errcode)
{
/* Buffer being flag. */
serial_io->wb[0] = UXR_FRAMING_BEGIN_FLAG;
serial_io->wb_pos = 1;
framing_io->wb[0] = UXR_FRAMING_BEGIN_FLAG;
framing_io->wb_pos = 1;
/* Buffer header. */
uxr_add_next_octet(serial_io, serial_io->local_addr);
uxr_add_next_octet(serial_io, remote_addr);
uxr_add_next_octet(serial_io, (uint8_t)(len & 0xFF));
uxr_add_next_octet(serial_io, (uint8_t)(len >> 8));
uxr_add_next_octet(framing_io, framing_io->local_addr);
uxr_add_next_octet(framing_io, remote_addr);
uxr_add_next_octet(framing_io, (uint8_t)(len & 0xFF));
uxr_add_next_octet(framing_io, (uint8_t)(len >> 8));
/* Write payload. */
uint8_t octet = 0;
@ -139,23 +161,14 @@ size_t uxr_write_serial_msg(uxrSerialIO* serial_io,
while (written_len < len && cond)
{
octet = *(buf + written_len);
if (uxr_add_next_octet(serial_io, octet))
if (uxr_add_next_octet(framing_io, octet))
{
uxr_update_crc(&crc, octet);
++written_len;
}
else
{
size_t bytes_written = write_cb(cb_arg, serial_io->wb, serial_io->wb_pos, errcode);
if (0 < bytes_written)
{
cond = true;
serial_io->wb_pos = (uint8_t)(serial_io->wb_pos - bytes_written);
}
else
{
cond = false;
}
cond = uxr_framing_write_transport(framing_io, write_cb, cb_arg, errcode);
}
}
@ -167,45 +180,81 @@ size_t uxr_write_serial_msg(uxrSerialIO* serial_io,
while (written_len < sizeof(tmp_crc) && cond)
{
octet = *(tmp_crc + written_len);
if (uxr_add_next_octet(serial_io, octet))
if (uxr_add_next_octet(framing_io, octet))
{
uxr_update_crc(&crc, octet);
++written_len;
}
else
{
size_t bytes_written = write_cb(cb_arg, serial_io->wb, serial_io->wb_pos, errcode);
if (0 < bytes_written)
{
cond = true;
serial_io->wb_pos = (uint8_t)(serial_io->wb_pos - bytes_written);
}
else
{
cond = false;
}
cond = uxr_framing_write_transport(framing_io, write_cb, cb_arg, errcode);
}
}
/* Flus write buffer. */
if (cond && (0 < serial_io->wb_pos))
/* Flush write buffer. */
if (cond && (0 < framing_io->wb_pos))
{
size_t bytes_written = write_cb(cb_arg, serial_io->wb, serial_io->wb_pos, errcode);
if (0 < bytes_written)
{
cond = true;
serial_io->wb_pos = (uint8_t)(serial_io->wb_pos - bytes_written);
}
else
{
cond = false;
}
cond = uxr_framing_write_transport(framing_io, write_cb, cb_arg, errcode);
}
return cond ? (uint16_t)(len) : 0;
}
size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
size_t uxr_framing_read_transport(uxrFramingIO* framing_io,
uxr_read_cb read_cb,
void* cb_arg,
int * timeout,
uint8_t* errcode)
{
int64_t time_init = uxr_millis();
/* Compute read-buffer available size. */
uint8_t av_len[2] = {0, 0};
if (framing_io->rb_head == framing_io->rb_tail)
{
framing_io->rb_head = 0;
framing_io->rb_tail = 0;
av_len[0] = sizeof(framing_io->rb) - 1;
}
else if (framing_io->rb_head > framing_io->rb_tail)
{
if (0 < framing_io->rb_tail)
{
av_len[0] = (uint8_t)(sizeof(framing_io->rb) - framing_io->rb_head);
av_len[1] = (uint8_t)(framing_io->rb_tail - 1);
}
else
{
av_len[0] = (uint8_t)(sizeof(framing_io->rb) - framing_io->rb_head - 1);
}
}
else
{
av_len[0] = (uint8_t)(framing_io->rb_tail - framing_io->rb_head - 1);
}
/* Read */
size_t bytes_read[2] = {0};
if (0 < av_len[0])
{
bytes_read[0] = read_cb(cb_arg, &framing_io->rb[framing_io->rb_head], av_len[0], *timeout, errcode);
framing_io->rb_head = (uint8_t)((size_t)(framing_io->rb_head + bytes_read[0]) % sizeof(framing_io->rb));
if (0 < bytes_read[0])
{
if ((bytes_read[0] == av_len[0]) && (0 < av_len[1]))
{
bytes_read[1] = read_cb(cb_arg, &framing_io->rb[framing_io->rb_head], av_len[1], 0, errcode);
framing_io->rb_head = (uint8_t)((size_t)(framing_io->rb_head + bytes_read[1]) % sizeof(framing_io->rb));
}
}
}
*timeout -= (int)(uxr_millis() - time_init);
*timeout = (0 > *timeout) ? 0 : *timeout;
return bytes_read[0] + bytes_read[1];
}
size_t uxr_read_framed_msg(uxrFramingIO* framing_io,
uxr_read_cb read_cb,
void* cb_arg,
uint8_t* buf,
@ -216,68 +265,29 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
{
size_t rv = 0;
/* Compute read-buffer available size. */
uint8_t av_len[2] = {0, 0};
if (serial_io->rb_head == serial_io->rb_tail)
{
serial_io->rb_head = 0;
serial_io->rb_tail = 0;
av_len[0] = sizeof(serial_io->rb) - 1;
}
else if (serial_io->rb_head > serial_io->rb_tail)
{
if (0 < serial_io->rb_tail)
{
av_len[0] = (uint8_t)(sizeof(serial_io->rb) - serial_io->rb_head);
av_len[1] = (uint8_t)(serial_io->rb_tail - 1);
}
else
{
av_len[0] = (uint8_t)(sizeof(serial_io->rb) - serial_io->rb_head - 1);
}
}
else
{
av_len[0] = (uint8_t)(serial_io->rb_tail - serial_io->rb_head - 1);
}
size_t readed_bytes = uxr_framing_read_transport(framing_io, read_cb, cb_arg, &timeout, errcode);
/* Read from serial. */
size_t bytes_read[2] = {0};
if (0 < av_len[0])
{
bytes_read[0] = read_cb(cb_arg, &serial_io->rb[serial_io->rb_head], av_len[0], timeout, errcode);
serial_io->rb_head = (uint8_t)((size_t)(serial_io->rb_head + bytes_read[0]) % sizeof(serial_io->rb));
if (0 < bytes_read[0])
{
if ((bytes_read[0] == av_len[0]) && (0 < av_len[1]))
{
bytes_read[1] = read_cb(cb_arg, &serial_io->rb[serial_io->rb_head], av_len[1], 0, errcode);
serial_io->rb_head = (uint8_t)((size_t)(serial_io->rb_head + bytes_read[1]) % sizeof(serial_io->rb));
}
}
}
if (0 < (bytes_read[0] + bytes_read[1]) || (serial_io->rb_tail != serial_io->rb_head))
if (0 < readed_bytes || (framing_io->rb_tail != framing_io->rb_head))
{
/* State Machine. */
bool exit_cond = false;
while (!exit_cond)
{
uint8_t octet = 0;
switch (serial_io->state)
switch (framing_io->state)
{
case UXR_SERIAL_UNINITIALIZED:
case UXR_FRAMING_UNINITIALIZED:
{
octet = 0;
while ((UXR_FRAMING_BEGIN_FLAG != octet) && (serial_io->rb_head != serial_io->rb_tail))
while ((UXR_FRAMING_BEGIN_FLAG != octet) && (framing_io->rb_head != framing_io->rb_tail))
{
octet = serial_io->rb[serial_io->rb_tail];
serial_io->rb_tail = (uint8_t)((size_t)(serial_io->rb_tail + 1) % sizeof(serial_io->rb));
octet = framing_io->rb[framing_io->rb_tail];
framing_io->rb_tail = (uint8_t)((size_t)(framing_io->rb_tail + 1) % sizeof(framing_io->rb));
}
if (UXR_FRAMING_BEGIN_FLAG == octet)
{
serial_io->state = UXR_SERIAL_READING_SRC_ADDR;
framing_io->state = UXR_FRAMING_READING_SRC_ADDR;
}
else
{
@ -285,32 +295,32 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
}
break;
}
case UXR_SERIAL_READING_SRC_ADDR:
case UXR_FRAMING_READING_SRC_ADDR:
{
if (uxr_get_next_octet(serial_io, &serial_io->src_addr))
if (uxr_get_next_octet(framing_io, &framing_io->src_addr))
{
serial_io->state = UXR_SERIAL_READING_DST_ADDR;
framing_io->state = UXR_FRAMING_READING_DST_ADDR;
}
else
{
if (UXR_FRAMING_BEGIN_FLAG != serial_io->src_addr)
if (UXR_FRAMING_BEGIN_FLAG != framing_io->src_addr)
{
exit_cond = true;
}
}
break;
}
case UXR_SERIAL_READING_DST_ADDR:
if (uxr_get_next_octet(serial_io, &octet))
case UXR_FRAMING_READING_DST_ADDR:
if (uxr_get_next_octet(framing_io, &octet))
{
serial_io->state = (octet == serial_io->local_addr) ? UXR_SERIAL_READING_LEN_LSB :
UXR_SERIAL_UNINITIALIZED;
framing_io->state = (octet == framing_io->local_addr) ? UXR_FRAMING_READING_LEN_LSB :
UXR_FRAMING_UNINITIALIZED;
}
else
{
if (UXR_FRAMING_BEGIN_FLAG == octet)
{
serial_io->state = UXR_SERIAL_READING_SRC_ADDR;
framing_io->state = UXR_FRAMING_READING_SRC_ADDR;
}
else
{
@ -318,17 +328,17 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
}
}
break;
case UXR_SERIAL_READING_LEN_LSB:
if (uxr_get_next_octet(serial_io, &octet))
case UXR_FRAMING_READING_LEN_LSB:
if (uxr_get_next_octet(framing_io, &octet))
{
serial_io->msg_len = octet;
serial_io->state = UXR_SERIAL_READING_LEN_MSB;
framing_io->msg_len = octet;
framing_io->state = UXR_FRAMING_READING_LEN_MSB;
}
else
{
if (UXR_FRAMING_BEGIN_FLAG == octet)
{
serial_io->state = UXR_SERIAL_READING_SRC_ADDR;
framing_io->state = UXR_FRAMING_READING_SRC_ADDR;
}
else
{
@ -336,27 +346,27 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
}
}
break;
case UXR_SERIAL_READING_LEN_MSB:
if (uxr_get_next_octet(serial_io, &octet))
case UXR_FRAMING_READING_LEN_MSB:
if (uxr_get_next_octet(framing_io, &octet))
{
serial_io->msg_len = (uint16_t)(serial_io->msg_len + (octet << 8));
serial_io->msg_pos = 0;
serial_io->cmp_crc = 0;
if (len < serial_io->msg_len)
framing_io->msg_len = (uint16_t)(framing_io->msg_len + (octet << 8));
framing_io->msg_pos = 0;
framing_io->cmp_crc = 0;
if (len < framing_io->msg_len)
{
serial_io->state = UXR_SERIAL_UNINITIALIZED;
framing_io->state = UXR_FRAMING_UNINITIALIZED;
exit_cond = true;
}
else
{
serial_io->state = UXR_SERIAL_READING_PAYLOAD;
framing_io->state = UXR_FRAMING_READING_PAYLOAD;
}
}
else
{
if (UXR_FRAMING_BEGIN_FLAG == octet)
{
serial_io->state = UXR_SERIAL_READING_SRC_ADDR;
framing_io->state = UXR_FRAMING_READING_SRC_ADDR;
}
else
{
@ -364,24 +374,27 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
}
}
break;
case UXR_SERIAL_READING_PAYLOAD:
case UXR_FRAMING_READING_PAYLOAD:
{
while ((serial_io->msg_pos < serial_io->msg_len) && uxr_get_next_octet(serial_io, &octet))
while ((framing_io->msg_pos < framing_io->msg_len) && uxr_get_next_octet(framing_io, &octet))
{
buf[(size_t)serial_io->msg_pos] = octet;
serial_io->msg_pos = (uint16_t)(serial_io->msg_pos + 1);
uxr_update_crc(&serial_io->cmp_crc, octet);
buf[(size_t)framing_io->msg_pos] = octet;
framing_io->msg_pos = (uint16_t)(framing_io->msg_pos + 1);
uxr_update_crc(&framing_io->cmp_crc, octet);
}
if (serial_io->msg_pos == serial_io->msg_len)
if (framing_io->msg_pos == framing_io->msg_len)
{
serial_io->state = UXR_SERIAL_READING_CRC_LSB;
framing_io->state = UXR_FRAMING_READING_CRC_LSB;
}
else
{
if (UXR_FRAMING_BEGIN_FLAG == octet)
{
serial_io->state = UXR_SERIAL_READING_SRC_ADDR;
framing_io->state = UXR_FRAMING_READING_SRC_ADDR;
}
else if (0 < uxr_framing_read_transport(framing_io, read_cb, cb_arg, &timeout, errcode)){
}
else
{
@ -390,17 +403,17 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
}
break;
}
case UXR_SERIAL_READING_CRC_LSB:
if (uxr_get_next_octet(serial_io, &octet))
case UXR_FRAMING_READING_CRC_LSB:
if (uxr_get_next_octet(framing_io, &octet))
{
serial_io->msg_crc = octet;
serial_io->state = UXR_SERIAL_READING_CRC_MSB;
framing_io->msg_crc = octet;
framing_io->state = UXR_FRAMING_READING_CRC_MSB;
}
else
{
if (UXR_FRAMING_BEGIN_FLAG == octet)
{
serial_io->state = UXR_SERIAL_READING_SRC_ADDR;
framing_io->state = UXR_FRAMING_READING_SRC_ADDR;
}
else
{
@ -408,15 +421,15 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
}
}
break;
case UXR_SERIAL_READING_CRC_MSB:
if (uxr_get_next_octet(serial_io, &octet))
case UXR_FRAMING_READING_CRC_MSB:
if (uxr_get_next_octet(framing_io, &octet))
{
serial_io->msg_crc = (uint16_t)(serial_io->msg_crc + (octet << 8));
serial_io->state = UXR_SERIAL_UNINITIALIZED;
if (serial_io->cmp_crc == serial_io->msg_crc)
framing_io->msg_crc = (uint16_t)(framing_io->msg_crc + (octet << 8));
framing_io->state = UXR_FRAMING_UNINITIALIZED;
if (framing_io->cmp_crc == framing_io->msg_crc)
{
*remote_addr = serial_io->src_addr;
rv = serial_io->msg_len;
*remote_addr = framing_io->src_addr;
rv = framing_io->msg_len;
}
exit_cond = true;
}
@ -424,7 +437,7 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
{
if (UXR_FRAMING_BEGIN_FLAG == octet)
{
serial_io->state = UXR_SERIAL_READING_SRC_ADDR;
framing_io->state = UXR_FRAMING_READING_SRC_ADDR;
}
else
{

View File

@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _SRC_C_PROFILE_TRANSPORT_SERIAL_SERIAL_PROTOCOL_INTERNAL_H_
#define _SRC_C_PROFILE_TRANSPORT_SERIAL_SERIAL_PROTOCOL_INTERNAL_H_
#ifndef _SRC_C_PROFILE_TRANSPORT_FRAMING_PROTOCOL_INTERNAL_H_
#define _SRC_C_PROFILE_TRANSPORT_FRAMING_PROTOCOL_INTERNAL_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <uxr/client/profile/transport/serial/serial_protocol.h>
#include <uxr/client/profile/transport/stream_framing/stream_framing_protocol.h>
#include <stddef.h>
#include <stdbool.h>
@ -27,17 +27,16 @@ extern "C"
#define UXR_FRAMING_ESC_FLAG 0x7D
#define UXR_FRAMING_XOR_FLAG 0x20
void uxr_init_serial_io(uxrSerialIO* serial_io, uint8_t local_addr);
void uxr_init_framing_io(uxrFramingIO* framing_io, uint8_t local_addr);
void uxr_update_crc(uint16_t* crc, const uint8_t data);
bool uxr_get_next_octet(uxrSerialIO* serial_io, uint8_t* octet);
bool uxr_add_next_octet(uxrSerialIO* serial_io, uint8_t octet);
bool uxr_get_next_octet(uxrFramingIO* framing_io, uint8_t* octet);
bool uxr_add_next_octet(uxrFramingIO* framing_io, uint8_t octet);
struct uxrSerialPlatform;
typedef size_t (*uxr_write_cb)(struct uxrSerialPlatform*, uint8_t*, size_t, uint8_t*);
typedef size_t (*uxr_read_cb)(struct uxrSerialPlatform*, uint8_t*, size_t, int, uint8_t*);
typedef size_t (*uxr_write_cb)(void*, const uint8_t*, size_t, uint8_t*);
typedef size_t (*uxr_read_cb)(void*, uint8_t*, size_t, int, uint8_t*);
size_t uxr_write_serial_msg(uxrSerialIO* serial_io,
size_t uxr_write_framed_msg(uxrFramingIO* framing_io,
uxr_write_cb write_cb,
void* cb_arg,
const uint8_t* buf,
@ -45,7 +44,7 @@ size_t uxr_write_serial_msg(uxrSerialIO* serial_io,
uint8_t remote_addr,
uint8_t* errcode);
size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
size_t uxr_read_framed_msg(uxrFramingIO* framing_io,
uxr_read_cb read_cb,
void* cb_arg,
uint8_t* buf,
@ -58,4 +57,4 @@ size_t uxr_read_serial_msg(uxrSerialIO* serial_io,
}
#endif
#endif //_SRC_C_PROFILE_TRANSPORT_SERIAL_SERIAL_PROTOCOL_INTERNAL_H_
#endif //_SRC_C_PROFILE_TRANSPORT_FRAMING_PROTOCOL_INTERNAL_H_

View File

@ -0,0 +1,70 @@
###############################################################################
#
# Copyright 2020 Proyectos y Sistemas de Mantenimiento SL (eProsima).
#
# 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.
#
###############################################################################
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
# New project because of the CXX GTest dependency.
if(CMAKE_VERSION VERSION_LESS 3.0)
project(custom_transport_test C CXX)
else()
cmake_policy(SET CMP0048 NEW)
project(custom_transport_test LANGUAGES C CXX)
endif()
if(NOT UCLIENT_PROFILE_CUSTOM_TRANSPORT)
message(WARNING "Can not compile test: The UCLIENT_PROFILE_CUSTOM_TRANSPORT must be enabled.")
else()
set(SRCS CustomComm.cpp)
add_executable(${PROJECT_NAME} ${SRCS})
set_common_compile_options(${PROJECT_NAME})
if(MSVC OR MSVC_IDE)
target_compile_options(${PROJECT_NAME} PRIVATE /wd4996)
endif()
add_gtest(${PROJECT_NAME}
SOURCES
${SRCS}
DEPENDENCIES
microxrcedds_client
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
microxrcedds_client
${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
target_include_directories(${PROJECT_NAME}
PUBLIC
${PROJECT_SOURCE_DIR}
PRIVATE
${GTEST_INCLUDE_DIRS}
)
set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD
11
CXX_STANDARD_REQUIRED
YES
)
endif()

View File

@ -0,0 +1,182 @@
#include "CustomComm.hpp"
#include <stdint.h>
CustomComm::CustomComm() : buffer(2000)
{
max_payload = 20;
uxr_set_custom_transport_callbacks(&master_, true, open, close, write, read);
uxr_init_custom_transport(&master_, this);
uxr_set_custom_transport_callbacks(&slave_, true, open, close, write, read);
uxr_init_custom_transport(&slave_, this);
}
CustomComm::~CustomComm()
{
uxr_close_custom_transport(&master_);
uxr_close_custom_transport(&slave_);
}
bool CustomComm::open(uxrCustomTransport* /*transport*/)
{
return true;
}
bool CustomComm::close(uxrCustomTransport* /*transport*/)
{
return true;
}
size_t CustomComm::write(uxrCustomTransport* transport, const uint8_t* buf, size_t len, uint8_t* /*error*/)
{
CustomComm* custom_comm = static_cast<CustomComm*>(transport->args);
size_t written = 0;
while (written < len && written < custom_comm->max_payload)
{
if (0 == custom_comm->buffer.write(buf[written]))
{
written++;
}
else
{
break;
}
}
return written;
}
size_t CustomComm::read(uxrCustomTransport* transport, uint8_t* buf, size_t len, int /*timeout*/, uint8_t* /*error*/)
{
CustomComm* custom_comm = static_cast<CustomComm*>(transport->args);
size_t readed = 0;
while (readed < len && readed < custom_comm->max_payload)
{
if (0 == custom_comm->buffer.read(&buf[readed]))
{
readed++;
}
else
{
break;
}
}
return readed;
}
TEST_F(CustomComm, SingleWriteReadTest)
{
uint8_t output_msg[3] = {11, 11, 89};
uint8_t* input_msg;
size_t input_msg_len;
/* Send message. */
ASSERT_TRUE(master_.comm.send_msg(&master_, output_msg, sizeof(output_msg)));
/* Receive message. */
ASSERT_TRUE(slave_.comm.recv_msg(&slave_, &input_msg, &input_msg_len, 10));
ASSERT_EQ(memcmp(output_msg, input_msg, sizeof(output_msg)), 0);
ASSERT_FALSE(slave_.comm.recv_msg(&slave_, &input_msg, &input_msg_len, 10));
}
TEST_F(CustomComm, MultiWriteReadTest)
{
uint16_t msgs_size = 1;
uint8_t output_msg[3] = {11, 11, 89};
uint8_t* input_msg;
size_t input_msg_len;
/* Send messages. */
for (int i = 0; i < msgs_size; ++i)
{
ASSERT_TRUE(master_.comm.send_msg(&master_, output_msg, sizeof(output_msg)));
}
/* Receive messages. */
for (int i = 0; i < msgs_size; ++i)
{
ASSERT_TRUE(slave_.comm.recv_msg(&slave_, &input_msg, &input_msg_len, 10));
ASSERT_EQ(memcmp(output_msg, input_msg, sizeof(output_msg)), 0);
}
ASSERT_FALSE(slave_.comm.recv_msg(&slave_, &input_msg, &input_msg_len, 10));
}
TEST_F(CustomComm, SingleOctetTest)
{
uint8_t output_msg = 0;
uint8_t* input_msg;
size_t input_msg_len;
/* Send messages. */
ASSERT_TRUE(master_.comm.send_msg(&master_, &output_msg, 1));
/* Receive message. */
ASSERT_TRUE(slave_.comm.recv_msg(&slave_, &input_msg, &input_msg_len, 10));
ASSERT_EQ(input_msg_len, size_t(1));
ASSERT_EQ(*input_msg, 0);
}
TEST_F(CustomComm, NoPayloadTest)
{
uint8_t output_msg = 0;
/* Send messages. */
ASSERT_FALSE(master_.comm.send_msg(&master_, &output_msg, 0));
}
TEST_F(CustomComm, WorstStuffingTest)
{
uint8_t output_msg[UXR_CONFIG_SERIAL_TRANSPORT_MTU];
uint8_t* input_msg;
size_t input_msg_len;
memset(output_msg, UXR_FRAMING_BEGIN_FLAG, sizeof(output_msg));
ASSERT_TRUE(master_.comm.send_msg(&master_, output_msg, sizeof(output_msg)));
ASSERT_TRUE(slave_.comm.recv_msg(&slave_, &input_msg, &input_msg_len, 100));
ASSERT_EQ(memcmp(output_msg, input_msg, sizeof(output_msg)), 0);
}
TEST_F(CustomComm, FatigueTest)
{
uint16_t msgs_size = uint16_t(~0);
uint16_t sent_counter = 0;
uint16_t recv_counter = 0;
uint8_t receiver_ratio = 8;
uint8_t output_msg[UXR_CONFIG_SERIAL_TRANSPORT_MTU];
uint8_t* input_msg;
size_t input_msg_len;
for (size_t i = 0; i < sizeof(output_msg); ++i)
{
output_msg[i] = uint8_t(i % (std::numeric_limits<uint8_t>::max() + 1));
}
for (uint16_t i = 0; i < msgs_size; ++i)
{
size_t output_len = (i % sizeof(output_msg));
if (master_.comm.send_msg(&master_, output_msg, output_len))
{
++sent_counter;
}
if (i % receiver_ratio == 0)
{
if (slave_.comm.recv_msg(&slave_, &input_msg, &input_msg_len, 10))
{
++recv_counter;
}
}
}
while (slave_.comm.recv_msg(&slave_, &input_msg, &input_msg_len, 10))
{
++recv_counter;
}
ASSERT_EQ(recv_counter, sent_counter);
}

View File

@ -0,0 +1,103 @@
// Copyright 2018 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// 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.
#ifndef _TEST_TRANSPORT_SERIALCOMM_HPP_
#define _TEST_TRANSPORT_SERIALCOMM_HPP_
#include <gtest/gtest.h>
#include <uxr/client/client.h>
class CircularBuffer
{
public:
CircularBuffer(size_t len)
: maxlen(len)
, head(0)
, tail(0)
{
buffer = static_cast<uint8_t*>(malloc(maxlen));
}
~CircularBuffer()
{
free(buffer);
}
int write(uint8_t data)
{
size_t next;
next = head + 1;
if (next >= maxlen)
{
next = 0;
}
if (next == tail)
{
return -1;
}
buffer[head] = data;
head = next;
return 0;
}
int read(uint8_t *data)
{
size_t next;
if (head == tail)
{
return -1;
}
next = tail + 1;
if(next >= maxlen)
{
next = 0;
}
*data = buffer[tail];
tail = next;
return 0;
}
private:
uint8_t * buffer;
size_t maxlen;
size_t head;
size_t tail;
};
class CustomComm : public testing::Test
{
public:
CustomComm();
~CustomComm();
protected:
uxrCustomTransport master_;
uxrCustomTransport slave_;
static bool open(uxrCustomTransport * args);
static bool close(uxrCustomTransport* transport);
static size_t write(uxrCustomTransport* transport, const uint8_t* buf, size_t len, uint8_t* error);
static size_t read(uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* error);
CircularBuffer buffer;
size_t max_payload;
};
#endif //_TEST_TRANSPORT_SERIALCOMM_HPP_