From a6ca3fd5f50ddb7ea82d300a0a04f2a47bb19675 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Wed, 26 Aug 2020 07:39:22 +0200 Subject: [PATCH 01/25] First ideas --- src/c/core/session/create_entities_xml.c | 8 ++++++++ src/c/core/session/session.c | 16 ++++++++++++++++ src/c/core/session/write_access.c | 9 +++++++++ 3 files changed, 33 insertions(+) diff --git a/src/c/core/session/create_entities_xml.c b/src/c/core/session/create_entities_xml.c index 0d3256f61..b660069ed 100644 --- a/src/c/core/session/create_entities_xml.c +++ b/src/c/core/session/create_entities_xml.c @@ -69,6 +69,13 @@ uint16_t uxr_buffer_create_datawriter_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER; uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data); + // HERE WE CAN CATCH THE TYPE AND THE NAME OR REFERENCE AND ASSOCIATE IT WITH ITS NUMBER + + // typedef struct { + // char hash[XRCE_BL_HASH_SIZE]; + // uxrObjectId id; + // } blEntityHash; + return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } @@ -81,6 +88,7 @@ uint16_t uxr_buffer_create_datareader_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAREADER; uxr_object_id_to_raw(subscriber_id, payload.object_representation._.data_reader.subscriber_id.data); + // HERE WE CAN CATCH THE TYPE AND THE NAME OR REFERENCE AND ASSOCIATE IT WITH ITS NUMBER return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } diff --git a/src/c/core/session/session.c b/src/c/core/session/session.c index e394fad55..a02fa09e5 100644 --- a/src/c/core/session/session.c +++ b/src/c/core/session/session.c @@ -370,6 +370,21 @@ bool uxr_buffer_performance(uxrSession *session, void uxr_flash_output_streams(uxrSession* session) { + // HERE WE CAN HAVE: + // - THE POINTER TO THE SERIALIZED DATA + // - THE SERIALIZED DATA LEN (THIS CAN BE INFERED FROM THE UDP MESSAGE) + // - THE NAME AND TYPE (SHOULD WE HASH THEM?) + // SO WE CAN SERIALIZE A NEW BUFFER USING UCDR AND SEND IT USING UDP BROADCAST + + // typedef struct { + // uint8_t *data; + // uint32_t lenght; + // uxrObjectId id; + // } blMessage; + + // An static list of blMessage must be sent completely at this point + // HASH IS RETRIEVED FROM A POOL OF blEntityHash + for(uint8_t i = 0; i < session->streams.output_best_effort_size; ++i) { uxrOutputBestEffortStream* stream = &session->streams.output_best_effort[i]; @@ -480,6 +495,7 @@ inline bool send_message(const uxrSession* session, uint8_t* buffer, size_t leng inline bool recv_message(const uxrSession* session, uint8_t**buffer, size_t* length, int poll_ms) { bool received = session->comm->recv_msg(session->comm->instance, buffer, length, poll_ms); + //LISTEN P2P PROPOSAL if(received) { UXR_DEBUG_PRINT_MESSAGE(UXR_RECV, *buffer, *length, session->info.key); diff --git a/src/c/core/session/write_access.c b/src/c/core/session/write_access.c index 7a60d155d..0df2ab007 100644 --- a/src/c/core/session/write_access.c +++ b/src/c/core/session/write_access.c @@ -74,6 +74,15 @@ bool uxr_prepare_output_stream(uxrSession* session, uxrStreamId stream_id, uxrOb void* args = ub->args; ucdr_init_buffer(ub, ub->iterator, (size_t)(ub->final - ub->iterator)); ucdr_set_on_full_buffer_callback(ub, on_full_buffer, args); + + //HERE WE CAN CATCH THE POINTER TO THE BUFFER WHERE THE DATA IS GOING TO BE SERIALIZED AND WE ALSO HAVE THE TOPIC NAME/TYPE ALONG WITH THE NUMBER + + // FILL AND SAVE IN A STATIC ARRAY MESSAGE DATA: + // typedef struct { + // uint8_t *data; <- ub->iterator; + // uint32_t lenght; <- topic_size + // uxrObjectId id; <- datawriter_id + // } blMessage; } return !ub->error; From 88deb4836ef1e9fb1280b3ab6ad2f85b7c3bb327 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Wed, 26 Aug 2020 13:44:23 +0200 Subject: [PATCH 02/25] First iteration transport --- .../udp_transport_broadcast_posix.c | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/c/brokerless/udp_transport_broadcast_posix.c diff --git a/src/c/brokerless/udp_transport_broadcast_posix.c b/src/c/brokerless/udp_transport_broadcast_posix.c new file mode 100644 index 000000000..d9c3d705e --- /dev/null +++ b/src/c/brokerless/udp_transport_broadcast_posix.c @@ -0,0 +1,76 @@ + +#include + +#include +#include +#include +#include +#include + +#define MULTICAST_DEFAULT_IP "239.255.0.2" +#define MULTICAST_DEFAULT_PORT 7400 + +int fd; +const TransportLocator multicast; + +bool init_udp_broadcast_transport_datagram() +{ + fd = socket(AF_INET, SOCK_DGRAM, 0); + + int broadcastEnable=1; + setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)); + + uxr_ip_to_locator(MULTICAST_DEFAULT_IP, (uint16_t)MULTICAST_DEFAULT_PORT, UXR_IPv4, &multicast); + + return fd != -1; +} + +bool close_udp_broadcast_transport_datagram() +{ + return (0 == close(fd)); +} + +bool udp_broadcast_send_datagram( + const uint8_t* buf, + size_t len) +{ + bool rv = true; + + printf("Sending %d bytes brokerless\n",len); + struct sockaddr_in remote_addr; + memcpy(&remote_addr.sin_addr, multicast._.medium_locator.address, sizeof(remote_addr.sin_addr)); + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(multicast._.medium_locator.locator_port); + + ssize_t bytes_sent = sendto(fd, (const void*)buf, len, 0, (struct sockaddr*)&remote_addr, sizeof(remote_addr)); + if (0 > bytes_sent) + { + rv = false; + } + + return rv; +} + +bool udp_broadcast_recv_datagram( + uint8_t* buf, + size_t* len, + int timeout) +{ + + size_t rv = 0; + + timeout = (timeout <= 0) ? 1 : timeout; + + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + ssize_t bytes_received = recv(fd, (void*)buf, len, 0); + + printf("Received %d bytes brokerless. Timeout %d\n", bytes_received, timeout); + + return rv; +} + From 1940da1998e0a4b0cb610343fbe0956007516b33 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Thu, 27 Aug 2020 14:10:51 +0200 Subject: [PATCH 03/25] Semiworking --- CMakeLists.txt | 2 + examples/PublishHelloWorld/main.c | 13 +- examples/SubscribeHelloWorld/main.c | 22 ++- src/c/brokerless/brokerless.c | 182 ++++++++++++++++++ src/c/brokerless/brokerless_internal.h | 73 +++++++ .../udp_transport_broadcast_posix.c | 65 ++++--- src/c/core/session/create_entities_ref.c | 5 + src/c/core/session/create_entities_xml.c | 7 +- src/c/core/session/session.c | 32 +-- src/c/core/session/write_access.c | 10 +- 10 files changed, 344 insertions(+), 67 deletions(-) create mode 100644 src/c/brokerless/brokerless.c create mode 100644 src/c/brokerless/brokerless_internal.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a6dca3f69..54d3c5b82 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,6 +228,8 @@ set(SRCS src/c/core/session/create_entities_xml.c src/c/core/session/read_access.c src/c/core/session/write_access.c + src/c/brokerless/brokerless.c + src/c/brokerless/udp_transport_broadcast_posix.c $<$,$>:src/c/core/log/log.c> ${_transport_src} ) diff --git a/examples/PublishHelloWorld/main.c b/examples/PublishHelloWorld/main.c index aeed1679a..d8c5594b4 100644 --- a/examples/PublishHelloWorld/main.c +++ b/examples/PublishHelloWorld/main.c @@ -52,7 +52,7 @@ int main(int args, char** argv) if(!uxr_create_session(&session)) { printf("Error at create session.\n"); - return 1; + // return 1; } // Streams @@ -96,21 +96,22 @@ int main(int args, char** argv) "" "" ""; - uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); - + // uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); + uint16_t datawriter_req = uxr_buffer_create_datawriter_ref(&session, reliable_out, datawriter_id, publisher_id, "prueba1", UXR_REPLACE); + // Send create entities message and wait its status uint8_t status[4]; uint16_t requests[4] = {participant_req, topic_req, publisher_req, datawriter_req}; if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 4)) { printf("Error at create entities: participant: %i topic: %i publisher: %i darawriter: %i\n", status[0], status[1], status[2], status[3]); - return 1; + // return 1; } // Write topics bool connected = true; uint32_t count = 0; - while(connected && count < max_topics) + while(1) { HelloWorld topic = {++count, "Hello DDS world!"}; @@ -120,7 +121,7 @@ int main(int args, char** argv) HelloWorld_serialize_topic(&ub, &topic); printf("Send topic: %s, id: %i\n", topic.message, topic.index); - connected = uxr_run_session_time(&session, 1000); + connected = uxr_run_session_time(&session, 100); } // Delete resources diff --git a/examples/SubscribeHelloWorld/main.c b/examples/SubscribeHelloWorld/main.c index cae845274..13e7973e6 100644 --- a/examples/SubscribeHelloWorld/main.c +++ b/examples/SubscribeHelloWorld/main.c @@ -23,6 +23,7 @@ #define STREAM_HISTORY 8 #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY +uint32_t last_index = -1; void on_topic( uxrSession* session, uxrObjectId object_id, @@ -39,6 +40,13 @@ void on_topic( printf("Received topic: %s, id: %i\n", topic.message, topic.index); + if (last_index != topic.index-1) + { + printf("LOST PACKAGE!!"); + } + + last_index = topic.index; + uint32_t* count_ptr = (uint32_t*) args; (*count_ptr)++; } @@ -75,7 +83,7 @@ int main(int args, char** argv) if(!uxr_create_session(&session)) { printf("Error at create session.\n"); - return 1; + // return 1; } // Streams @@ -119,7 +127,8 @@ int main(int args, char** argv) "" "" ""; - uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); + // uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); + uint16_t datareader_req = uxr_buffer_create_datareader_ref(&session, reliable_out, datareader_id, subscriber_id, "prueba1", UXR_REPLACE); // Send create entities message and wait its status uint8_t status[4]; @@ -127,7 +136,7 @@ int main(int args, char** argv) if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 4)) { printf("Error at create entities: participant: %i topic: %i subscriber: %i datareader: %i\n", status[0], status[1], status[2], status[3]); - return 1; + // return 1; } // Request topics @@ -137,10 +146,11 @@ int main(int args, char** argv) // Read topics bool connected = true; - while(connected && count < max_topics) + while(true) { - uint8_t read_data_status; - connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); + // uint8_t read_data_status; + // connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); + connected = uxr_run_session_time(&session, 10); } // Delete resources diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c new file mode 100644 index 000000000..52bbb1b90 --- /dev/null +++ b/src/c/brokerless/brokerless.c @@ -0,0 +1,182 @@ +// Copyright 2017 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. + +// TODOs: +// - Manage brokerlessMessageQueue_t and brokerlessEntityMap_t as a container that allow push and pop +// - Implement removing entities from brokerless when they are removed from user API +// - Is the hast/objectid lookup optimal? Which container structure should we use? +// - Are the UDP broadcast sending a whole packet? Can it have fragmentation in UDP packet level? +// - What happen when uCDR buffer fragments? +// - Implement hash function for "topic recognition" +// - How can we match using XML instead of references? +// - Control flow of datareaders using the API of uxr_buffer_request_data + +#include "./brokerless_internal.h" + +#include + +brokerlessMessageQueue_t brokerlessMessageQueue; +brokerlessEntityMap_t brokerlessEntityMap; +uint8_t brokerlessBuffer[BROKERLESS_BUFFER_SIZE]; + +//================================================================== +// PRIVATE +//================================================================== + +// djb2 by Dan Bernstein: http://www.cse.yorku.ca/~oz/hash.html +void hash_brokerless(unsigned char *str, char* hash_out) +{ + unsigned long hash = 5381; + int c; + + while (c = *str++) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + for (size_t i = 0; i < sizeof(unsigned long); i++){ + hash_out = ((char*)&hash)[i]; + } + +} + +void init_brokerless() +{ + brokerlessMessageQueue.index = 0; + brokerlessEntityMap.index = 0; + brokerlessEntityMap.datareaders = 0; + brokerlessEntityMap.datawriters = 0; + + init_udp_broadcast_transport_datagram(); +} + +bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id) +{ + if (brokerlessMessageQueue.index < BROKERLESS_MESSAGE_QUEUE_LEN - 1) + { + brokerlessMessageQueue.queue[brokerlessMessageQueue.index].data = ub->iterator; + brokerlessMessageQueue.queue[brokerlessMessageQueue.index].lenght = lenght; + brokerlessMessageQueue.queue[brokerlessMessageQueue.index].id = id; + + brokerlessMessageQueue.index++; + + return true; + } + + return false; +} + +bool add_brokerless_entity_hash(char* ref, uxrObjectId id) +{ + if (brokerlessEntityMap.index < BROKERLESS_ENTITY_MAP_LEN - 1) + { + // memcpy(&brokerlessEntityMap.queue[brokerlessEntityMap.index].hash, ref, BROKERLESS_HASH_SIZE); + + hash_brokerless(ref, brokerlessEntityMap.queue[brokerlessEntityMap.index].hash); + + brokerlessEntityMap.queue[brokerlessMessageQueue.index].id = id; + + if (id.type == UXR_DATAREADER_ID){ + brokerlessEntityMap.datareaders++; + }else if (id.type == UXR_DATAWRITER_ID){ + brokerlessEntityMap.datawriters++; + } + + + brokerlessEntityMap.index++; + + return true; + } + + return false; +} + +int32_t find_brokerless_hash_from_id(uxrObjectId id) +{ + for (size_t i = 0; i < brokerlessEntityMap.index; i++) + { + if (brokerlessEntityMap.queue[i].id.id == id.id && + brokerlessEntityMap.queue[i].id.type == id.type) + { + return i; + } + } + return -1; +} + +int32_t find_brokerless_hash_from_hash(char* hash) +{ + for (size_t i = 0; i < brokerlessEntityMap.index; i++) + { + if (0 == memcmp((void*) hash, (void*) brokerlessEntityMap.queue[i].hash, BROKERLESS_HASH_SIZE)) + { + return i; + } + } + return -1; +} + +bool flush_brokerless_queues() +{ + for (size_t i = 0; i < brokerlessMessageQueue.index; i++) + { + int32_t hash_index = find_brokerless_hash_from_id(brokerlessMessageQueue.queue[i].id); + + if (-1 != hash_index) + { + ucdrBuffer writer; + ucdr_init_buffer(&writer, brokerlessBuffer, BROKERLESS_BUFFER_SIZE); + + ucdr_serialize_array_char(&writer, brokerlessEntityMap.queue[hash_index].hash, BROKERLESS_HASH_SIZE); + ucdr_serialize_sequence_char(&writer, brokerlessMessageQueue.queue[i].data, brokerlessMessageQueue.queue[i].lenght); + + udp_broadcast_send_datagram(writer.init, ucdr_buffer_length(&writer)); + } + } + + brokerlessMessageQueue.index = 0; + + return false; +} + +bool listen_brokerless(uint8_t** data, size_t* length, int timeout, uxrObjectId** id) +{ + size_t readed_bytes = 0; + if (0 != brokerlessEntityMap.datareaders){ + readed_bytes = udp_broadcast_recv_datagram(&brokerlessBuffer, BROKERLESS_BUFFER_SIZE, timeout); + } + + if(0 != readed_bytes){ + + ucdrBuffer reader; + ucdr_init_buffer(&reader, brokerlessBuffer, readed_bytes); + + char hash[BROKERLESS_HASH_SIZE]; + ucdr_deserialize_array_char(&reader, hash, BROKERLESS_HASH_SIZE); + + + int32_t hash_index = find_brokerless_hash_from_hash(hash); + + if (-1 != hash_index && brokerlessEntityMap.queue[hash_index].id.type == UXR_DATAREADER_ID) + { + *id = &brokerlessEntityMap.queue[hash_index]; + uint32_t aux; + ucdr_deserialize_uint32_t(&reader, &aux); + *length = aux; + *data = reader.iterator; + return true; + } + } + + return false; +} + diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h new file mode 100644 index 000000000..00d5f1205 --- /dev/null +++ b/src/c/brokerless/brokerless_internal.h @@ -0,0 +1,73 @@ +// Copyright 2017 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 _SRC_C_BROKERLESS_BROKERLESS_INTERNAL_H_ +#define _SRC_C_BROKERLESS_BROKERLESS_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#include +#include + +#define BROKERLESS_MESSAGE_QUEUE_LEN 100 +#define BROKERLESS_ENTITY_MAP_LEN 10 +#define BROKERLESS_HASH_SIZE sizeof(unsigned long) +#define BROKERLESS_BUFFER_SIZE 1000 + +// Outcomming message queue + +typedef struct { + uint8_t *data; + uint32_t lenght; + uxrObjectId id; +} brokerlessMessage_t; + +typedef struct { + brokerlessMessage_t queue[BROKERLESS_MESSAGE_QUEUE_LEN]; + uint8_t index; +} brokerlessMessageQueue_t; + +// Entities map + +typedef struct { + char hash[BROKERLESS_HASH_SIZE]; + uxrObjectId id; +} brokerlessEntityHash_t; + + +typedef struct { + brokerlessEntityHash_t queue[BROKERLESS_ENTITY_MAP_LEN]; + uint8_t index; + uint8_t datawriters; + uint8_t datareaders; +} brokerlessEntityMap_t; + +// Internal API + +void init_brokerless(); +bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id); +bool add_brokerless_entity_hash(char* hash, uxrObjectId id); +bool flush_brokerless_queues(); + +#ifdef __cplusplus +} +#endif + +#endif // _SRC_C_BROKERLESS_BROKERLESS_INTERNAL_H_ diff --git a/src/c/brokerless/udp_transport_broadcast_posix.c b/src/c/brokerless/udp_transport_broadcast_posix.c index d9c3d705e..00a5cab10 100644 --- a/src/c/brokerless/udp_transport_broadcast_posix.c +++ b/src/c/brokerless/udp_transport_broadcast_posix.c @@ -7,22 +7,38 @@ #include #include -#define MULTICAST_DEFAULT_IP "239.255.0.2" -#define MULTICAST_DEFAULT_PORT 7400 +#define MULTICAST_DEFAULT_IP "127.255.255.255" +#define MULTICAST_DEFAULT_PORT 9090 int fd; -const TransportLocator multicast; +struct sockaddr_in send_addr, recv_addr; bool init_udp_broadcast_transport_datagram() { - fd = socket(AF_INET, SOCK_DGRAM, 0); + int trueflag = 1, count = 0; + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + printf("socket"); - int broadcastEnable=1; - setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)); + if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &trueflag, sizeof trueflag) < 0) + printf("setsockopt"); - uxr_ip_to_locator(MULTICAST_DEFAULT_IP, (uint16_t)MULTICAST_DEFAULT_PORT, UXR_IPv4, &multicast); + memset(&send_addr, 0, sizeof send_addr); + send_addr.sin_family = AF_INET; + send_addr.sin_port = (in_port_t) htons(MULTICAST_DEFAULT_PORT); + inet_aton(MULTICAST_DEFAULT_IP, &send_addr.sin_addr); - return fd != -1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &trueflag, sizeof trueflag) < 0) + printf("setsockopt"); + + memset(&recv_addr, 0, sizeof recv_addr); + recv_addr.sin_family = AF_INET; + recv_addr.sin_port = (in_port_t) htons(MULTICAST_DEFAULT_PORT); + recv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(fd, (struct sockaddr*) &recv_addr, sizeof recv_addr) < 0) + printf("bind"); + + return true; } bool close_udp_broadcast_transport_datagram() @@ -30,35 +46,30 @@ bool close_udp_broadcast_transport_datagram() return (0 == close(fd)); } -bool udp_broadcast_send_datagram( +size_t udp_broadcast_send_datagram( const uint8_t* buf, size_t len) { - bool rv = true; + size_t rv = 0; - printf("Sending %d bytes brokerless\n",len); - struct sockaddr_in remote_addr; - memcpy(&remote_addr.sin_addr, multicast._.medium_locator.address, sizeof(remote_addr.sin_addr)); - remote_addr.sin_family = AF_INET; - remote_addr.sin_port = htons(multicast._.medium_locator.locator_port); - - ssize_t bytes_sent = sendto(fd, (const void*)buf, len, 0, (struct sockaddr*)&remote_addr, sizeof(remote_addr)); - if (0 > bytes_sent) - { - rv = false; + // printf("Sending %d bytes brokerless\n\t",len); + + ssize_t bytes_sent = sendto(fd, buf, len, 0, (struct sockaddr*) &send_addr, sizeof send_addr); + if (0 > bytes_sent) { + rv = 0; + } else { + rv = bytes_sent; } return rv; } -bool udp_broadcast_recv_datagram( +size_t udp_broadcast_recv_datagram( uint8_t* buf, - size_t* len, + size_t len, int timeout) { - size_t rv = 0; - timeout = (timeout <= 0) ? 1 : timeout; struct timeval tv; @@ -67,10 +78,10 @@ bool udp_broadcast_recv_datagram( setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); - ssize_t bytes_received = recv(fd, (void*)buf, len, 0); + ssize_t readed_bytes = recv(fd, (void*)buf, len, 0); - printf("Received %d bytes brokerless. Timeout %d\n", bytes_received, timeout); + // printf("Received %d/%d bytes brokerless. Timeout %d\n", readed_bytes, len, timeout); - return rv; + return (readed_bytes > 0) ? readed_bytes : 0; } diff --git a/src/c/core/session/create_entities_ref.c b/src/c/core/session/create_entities_ref.c index b4fd44e8b..e3369dbaf 100644 --- a/src/c/core/session/create_entities_ref.c +++ b/src/c/core/session/create_entities_ref.c @@ -2,6 +2,7 @@ #include #include "common_create_entities_internal.h" +#include "../../brokerless/brokerless_internal.h" #include @@ -43,6 +44,8 @@ uint16_t uxr_buffer_create_datawriter_ref(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER; uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data); + add_brokerless_entity_hash(ref, object_id); + return create_entity_ref(session, stream_id, object_id, ref, mode, &payload); } @@ -54,6 +57,8 @@ uint16_t uxr_buffer_create_datareader_ref(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAREADER; uxr_object_id_to_raw(subscriber_id, payload.object_representation._.data_reader.subscriber_id.data); + add_brokerless_entity_hash(ref, object_id); + return create_entity_ref(session, stream_id, object_id, ref, mode, &payload); } diff --git a/src/c/core/session/create_entities_xml.c b/src/c/core/session/create_entities_xml.c index b660069ed..7a266c4fc 100644 --- a/src/c/core/session/create_entities_xml.c +++ b/src/c/core/session/create_entities_xml.c @@ -69,12 +69,7 @@ uint16_t uxr_buffer_create_datawriter_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER; uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data); - // HERE WE CAN CATCH THE TYPE AND THE NAME OR REFERENCE AND ASSOCIATE IT WITH ITS NUMBER - - // typedef struct { - // char hash[XRCE_BL_HASH_SIZE]; - // uxrObjectId id; - // } blEntityHash; + // TODO (pablogs9): ALERT! Is not possible to parse the XML here for extracting the name/type; return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } diff --git a/src/c/core/session/session.c b/src/c/core/session/session.c index a02fa09e5..c55b7e903 100644 --- a/src/c/core/session/session.c +++ b/src/c/core/session/session.c @@ -16,6 +16,7 @@ #include "stream/seq_num_internal.h" #include "../log/log_internal.h" #include "../../util/time_internal.h" +#include "../../brokerless/brokerless_internal.h" #define CREATE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + CREATE_CLIENT_PAYLOAD_SIZE) #define DELETE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + DELETE_CLIENT_PAYLOAD_SIZE) @@ -81,6 +82,7 @@ void uxr_init_session(uxrSession* session, uxrCommunication* comm, uint32_t key) uxr_init_session_info(&session->info, 0x81, key); uxr_init_stream_storage(&session->streams); + init_brokerless(); } void uxr_set_status_callback(uxrSession* session, uxrOnStatusFunc on_status_func, void* args) @@ -370,20 +372,7 @@ bool uxr_buffer_performance(uxrSession *session, void uxr_flash_output_streams(uxrSession* session) { - // HERE WE CAN HAVE: - // - THE POINTER TO THE SERIALIZED DATA - // - THE SERIALIZED DATA LEN (THIS CAN BE INFERED FROM THE UDP MESSAGE) - // - THE NAME AND TYPE (SHOULD WE HASH THEM?) - // SO WE CAN SERIALIZE A NEW BUFFER USING UCDR AND SEND IT USING UDP BROADCAST - - // typedef struct { - // uint8_t *data; - // uint32_t lenght; - // uxrObjectId id; - // } blMessage; - - // An static list of blMessage must be sent completely at this point - // HASH IS RETRIEVED FROM A POOL OF blEntityHash + flush_brokerless_queues(); for(uint8_t i = 0; i < session->streams.output_best_effort_size; ++i) { @@ -426,6 +415,21 @@ bool listen_message(uxrSession* session, int poll_ms) read_message(session, &ub); } + uint8_t* data_brokerless; size_t length_brokerless; uxrObjectId* object_id; + bool must_be_read_brokerless = listen_brokerless(&data_brokerless, &length_brokerless, poll_ms, &object_id); + if(must_be_read_brokerless) + { + ucdrBuffer temp_buffer; + ucdr_init_buffer(&temp_buffer, data_brokerless, length_brokerless); + + //CALL CALLBACK + // object_id is the datareader (or service equivalent) that can be used to identify which topic should the callback must handle + // request_id is related to the uxr_buffer_request_data request, so it can determine some limitations imposed into the communication -> NOT IMPLEMENTED BY NOW + // stream_id should point to a new type of Brokerless stream -> NOT IMPLEMENTED BY NOW + uxrStreamId aux; + session->on_topic(session, *object_id, 0, aux, &temp_buffer, length_brokerless, session->on_topic_args); + } + return must_be_read; } diff --git a/src/c/core/session/write_access.c b/src/c/core/session/write_access.c index 0df2ab007..9b10d4496 100644 --- a/src/c/core/session/write_access.c +++ b/src/c/core/session/write_access.c @@ -4,6 +4,7 @@ #include "session_internal.h" #include "session_info_internal.h" #include "submessage_internal.h" +#include "../../brokerless/brokerless_internal.h" #define WRITE_DATA_PAYLOAD_SIZE 4 #define SAMPLE_IDENTITY_SIZE 24 @@ -75,14 +76,7 @@ bool uxr_prepare_output_stream(uxrSession* session, uxrStreamId stream_id, uxrOb ucdr_init_buffer(ub, ub->iterator, (size_t)(ub->final - ub->iterator)); ucdr_set_on_full_buffer_callback(ub, on_full_buffer, args); - //HERE WE CAN CATCH THE POINTER TO THE BUFFER WHERE THE DATA IS GOING TO BE SERIALIZED AND WE ALSO HAVE THE TOPIC NAME/TYPE ALONG WITH THE NUMBER - - // FILL AND SAVE IN A STATIC ARRAY MESSAGE DATA: - // typedef struct { - // uint8_t *data; <- ub->iterator; - // uint32_t lenght; <- topic_size - // uxrObjectId id; <- datawriter_id - // } blMessage; + add_brokerless_message(ub, topic_size, datawriter_id); } return !ub->error; From 8d3f0f17b6d31811b55c003955ea291db7bf0771 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Fri, 28 Aug 2020 11:13:34 +0200 Subject: [PATCH 04/25] Working state --- src/c/brokerless/brokerless.c | 17 +++---- src/c/brokerless/brokerless_internal.h | 4 +- .../udp_transport_broadcast_posix.c | 49 ++++++++++--------- 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 52bbb1b90..818edfed4 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -21,6 +21,8 @@ // - Implement hash function for "topic recognition" // - How can we match using XML instead of references? // - Control flow of datareaders using the API of uxr_buffer_request_data +// - If we implement binary XML entities it would be really nice to the Brokerless architecture +// Not all QoS can be sended in Binary Format p29 s7.7.3.2 https://www.omg.org/spec/DDS-XRCE/1.0/PDF #include "./brokerless_internal.h" @@ -35,18 +37,17 @@ uint8_t brokerlessBuffer[BROKERLESS_BUFFER_SIZE]; //================================================================== // djb2 by Dan Bernstein: http://www.cse.yorku.ca/~oz/hash.html -void hash_brokerless(unsigned char *str, char* hash_out) +void hash_brokerless(unsigned char *str, char* hash) { - unsigned long hash = 5381; + hash_int_t int_hash = 5381; int c; while (c = *str++) - hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + int_hash = ((int_hash << 5) + int_hash) + c; /* hash * 33 + c */ - for (size_t i = 0; i < sizeof(unsigned long); i++){ - hash_out = ((char*)&hash)[i]; - } - + for (size_t i = 0; i < BROKERLESS_HASH_SIZE; i++){ + hash[i] = ((char*)&int_hash)[i]; + } } void init_brokerless() @@ -79,8 +80,6 @@ bool add_brokerless_entity_hash(char* ref, uxrObjectId id) { if (brokerlessEntityMap.index < BROKERLESS_ENTITY_MAP_LEN - 1) { - // memcpy(&brokerlessEntityMap.queue[brokerlessEntityMap.index].hash, ref, BROKERLESS_HASH_SIZE); - hash_brokerless(ref, brokerlessEntityMap.queue[brokerlessEntityMap.index].hash); brokerlessEntityMap.queue[brokerlessMessageQueue.index].id = id; diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h index 00d5f1205..099a32c5c 100644 --- a/src/c/brokerless/brokerless_internal.h +++ b/src/c/brokerless/brokerless_internal.h @@ -26,9 +26,11 @@ extern "C" #include #include +typedef unsigned long hash_int_t; + #define BROKERLESS_MESSAGE_QUEUE_LEN 100 #define BROKERLESS_ENTITY_MAP_LEN 10 -#define BROKERLESS_HASH_SIZE sizeof(unsigned long) +#define BROKERLESS_HASH_SIZE sizeof(hash_int_t) #define BROKERLESS_BUFFER_SIZE 1000 // Outcomming message queue diff --git a/src/c/brokerless/udp_transport_broadcast_posix.c b/src/c/brokerless/udp_transport_broadcast_posix.c index 00a5cab10..551949fe4 100644 --- a/src/c/brokerless/udp_transport_broadcast_posix.c +++ b/src/c/brokerless/udp_transport_broadcast_posix.c @@ -7,43 +7,43 @@ #include #include -#define MULTICAST_DEFAULT_IP "127.255.255.255" -#define MULTICAST_DEFAULT_PORT 9090 +#define BROADCAST_DEFAULT_IP "255.255.255.255" +#define BROADCAST_DEFAULT_PORT 9000 -int fd; +int fd_recv; +int fd_send; struct sockaddr_in send_addr, recv_addr; bool init_udp_broadcast_transport_datagram() { - int trueflag = 1, count = 0; - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - printf("socket"); + int trueflag = 1; + fd_recv = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + fd_send = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &trueflag, sizeof trueflag) < 0) - printf("setsockopt"); + setsockopt(fd_recv, SOL_SOCKET, SO_BROADCAST, &trueflag, sizeof trueflag); + setsockopt(fd_send, SOL_SOCKET, SO_BROADCAST, &trueflag, sizeof trueflag); + + setsockopt(fd_recv, SOL_SOCKET, SO_REUSEADDR, &trueflag, sizeof trueflag); + setsockopt(fd_send, SOL_SOCKET, SO_REUSEADDR, &trueflag, sizeof trueflag); memset(&send_addr, 0, sizeof send_addr); send_addr.sin_family = AF_INET; - send_addr.sin_port = (in_port_t) htons(MULTICAST_DEFAULT_PORT); - inet_aton(MULTICAST_DEFAULT_IP, &send_addr.sin_addr); - - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &trueflag, sizeof trueflag) < 0) - printf("setsockopt"); + send_addr.sin_port = (in_port_t) htons(BROADCAST_DEFAULT_PORT); + inet_aton(BROADCAST_DEFAULT_IP, &send_addr.sin_addr); memset(&recv_addr, 0, sizeof recv_addr); recv_addr.sin_family = AF_INET; - recv_addr.sin_port = (in_port_t) htons(MULTICAST_DEFAULT_PORT); + recv_addr.sin_port = (in_port_t) htons(BROADCAST_DEFAULT_PORT); recv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - if (bind(fd, (struct sockaddr*) &recv_addr, sizeof recv_addr) < 0) - printf("bind"); + bind(fd_recv, (struct sockaddr*) &recv_addr, sizeof recv_addr); return true; } bool close_udp_broadcast_transport_datagram() { - return (0 == close(fd)); + return ((0 == close(fd_recv)) && 0 == close(fd_send)); } size_t udp_broadcast_send_datagram( @@ -52,9 +52,9 @@ size_t udp_broadcast_send_datagram( { size_t rv = 0; - // printf("Sending %d bytes brokerless\n\t",len); + // printf("Sending %d bytes brokerless\n",len); - ssize_t bytes_sent = sendto(fd, buf, len, 0, (struct sockaddr*) &send_addr, sizeof send_addr); + ssize_t bytes_sent = sendto(fd_send, buf, len, 0, (struct sockaddr*) &send_addr, sizeof(send_addr)); if (0 > bytes_sent) { rv = 0; } else { @@ -76,11 +76,16 @@ size_t udp_broadcast_recv_datagram( tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + setsockopt(fd_recv, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + struct sockaddr_in from; + int fromlen; + fromlen = sizeof(from); - ssize_t readed_bytes = recv(fd, (void*)buf, len, 0); + ssize_t readed_bytes = recvfrom(fd_recv, (void*)buf, len, 0, &from, &fromlen); - // printf("Received %d/%d bytes brokerless. Timeout %d\n", readed_bytes, len, timeout); + // if(readed_bytes != -1) + // printf("Received %d/%d bytes brokerless from %s:%d Timeout %d\n", readed_bytes, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port), timeout); return (readed_bytes > 0) ? readed_bytes : 0; } From 19eddc29a3d970639f2c9c1fb5c447bfdb9e3735 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Mon, 31 Aug 2020 09:06:23 +0200 Subject: [PATCH 05/25] Added brokerless request/reply --- .../client/core/session/stream/stream_id.h | 4 +- src/c/brokerless/brokerless.c | 96 ++++++++++++++----- src/c/brokerless/brokerless_internal.h | 7 ++ src/c/brokerless/brokerless_transport.h | 44 +++++++++ .../udp_transport_broadcast_posix.c | 8 +- src/c/core/session/create_entities_ref.c | 4 + src/c/core/session/session.c | 47 +++++++-- src/c/core/session/write_access.c | 8 ++ 8 files changed, 184 insertions(+), 34 deletions(-) create mode 100644 src/c/brokerless/brokerless_transport.h diff --git a/include/uxr/client/core/session/stream/stream_id.h b/include/uxr/client/core/session/stream/stream_id.h index bd8e41575..b7933a8dd 100644 --- a/include/uxr/client/core/session/stream/stream_id.h +++ b/include/uxr/client/core/session/stream/stream_id.h @@ -44,7 +44,9 @@ typedef enum uxrStreamType /** Identifies a best-effort stream. */ UXR_BEST_EFFORT_STREAM, /** Identifies a reliable stream. */ - UXR_RELIABLE_STREAM + UXR_RELIABLE_STREAM, + /** Identifies a brokerless stream. */ + UXR_BROKERLESS } uxrStreamType; diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 818edfed4..315627622 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -20,17 +20,27 @@ // - What happen when uCDR buffer fragments? // - Implement hash function for "topic recognition" // - How can we match using XML instead of references? -// - Control flow of datareaders using the API of uxr_buffer_request_data +// - Control flow of datareaders using the API of uxr_buffer_request_data and pass the request_id to the callbacks // - If we implement binary XML entities it would be really nice to the Brokerless architecture // Not all QoS can be sended in Binary Format p29 s7.7.3.2 https://www.omg.org/spec/DDS-XRCE/1.0/PDF +// - Should we simplify the approach of uxr_prepare_output_stream -> serialize to something similar to the request/reply where buffer is available in uxr_buffer_request? +// - Explore cases when multiple datawriters/datareaders/requesters/repliers coexists +// - sample identity inside brokerlessMessage_t can be optimized because it is a big member + +// IDEAS: +// - A P2P system that has a node with some services for create entities in the real agent. +// - A P2P system that has a node acting as a gateware to DDS. We need a P2P standart QoS which only fill type and topic to always match. + #include "./brokerless_internal.h" +#include "./brokerless_transport.h" #include -brokerlessMessageQueue_t brokerlessMessageQueue; -brokerlessEntityMap_t brokerlessEntityMap; -uint8_t brokerlessBuffer[BROKERLESS_BUFFER_SIZE]; +static uint32_t client_key; +static brokerlessMessageQueue_t brokerlessMessageQueue; +static brokerlessEntityMap_t brokerlessEntityMap; +static uint8_t brokerlessBuffer[BROKERLESS_BUFFER_SIZE]; //================================================================== // PRIVATE @@ -50,23 +60,34 @@ void hash_brokerless(unsigned char *str, char* hash) } } -void init_brokerless() +void init_brokerless(uint32_t key) { brokerlessMessageQueue.index = 0; brokerlessEntityMap.index = 0; brokerlessEntityMap.datareaders = 0; brokerlessEntityMap.datawriters = 0; + brokerlessEntityMap.requesters = 0; + brokerlessEntityMap.repliers = 0; + + client_key = key; - init_udp_broadcast_transport_datagram(); + brokerless_init_transport(); } bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id) +{ + SampleIdentity sample_id = {0}; + return add_brokerless_message_with_sample_id(ub, lenght, id, sample_id); +} + +bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id, SampleIdentity sample_id) { if (brokerlessMessageQueue.index < BROKERLESS_MESSAGE_QUEUE_LEN - 1) { brokerlessMessageQueue.queue[brokerlessMessageQueue.index].data = ub->iterator; brokerlessMessageQueue.queue[brokerlessMessageQueue.index].lenght = lenght; brokerlessMessageQueue.queue[brokerlessMessageQueue.index].id = id; + brokerlessMessageQueue.queue[brokerlessMessageQueue.index].sample_id = sample_id; brokerlessMessageQueue.index++; @@ -80,17 +101,20 @@ bool add_brokerless_entity_hash(char* ref, uxrObjectId id) { if (brokerlessEntityMap.index < BROKERLESS_ENTITY_MAP_LEN - 1) { - hash_brokerless(ref, brokerlessEntityMap.queue[brokerlessEntityMap.index].hash); + hash_brokerless((unsigned char*) ref, brokerlessEntityMap.queue[brokerlessEntityMap.index].hash); brokerlessEntityMap.queue[brokerlessMessageQueue.index].id = id; - + if (id.type == UXR_DATAREADER_ID){ brokerlessEntityMap.datareaders++; }else if (id.type == UXR_DATAWRITER_ID){ brokerlessEntityMap.datawriters++; + }else if (id.type == UXR_REQUESTER_ID){ + brokerlessEntityMap.requesters++; + }else if (id.type == UXR_REPLIER_ID){ + brokerlessEntityMap.repliers++; } - brokerlessEntityMap.index++; return true; @@ -106,7 +130,7 @@ int32_t find_brokerless_hash_from_id(uxrObjectId id) if (brokerlessEntityMap.queue[i].id.id == id.id && brokerlessEntityMap.queue[i].id.type == id.type) { - return i; + return (int32_t) i; } } return -1; @@ -118,12 +142,30 @@ int32_t find_brokerless_hash_from_hash(char* hash) { if (0 == memcmp((void*) hash, (void*) brokerlessEntityMap.queue[i].hash, BROKERLESS_HASH_SIZE)) { - return i; + return (int32_t) i; } } return -1; } +bool check_brokerless_sample_id(SampleIdentity sample_id) +{ + // TODO (pablogs9): Check if requester id stored in the sample_id still exists + + return !memcmp(&sample_id.writer_guid.entityId.entityKey, (uint8_t*)(&client_key), 3) && + !memcmp(&sample_id.writer_guid.entityId.entityKind, (uint8_t*)(&client_key) + 3, 1); +} + +void fill_brokerless_sample_id(SampleIdentity* sample_id, uxrObjectId id) +{ + // TODO (pablogs9): Improve this in order to take into account the endianness + + memcpy(&sample_id->writer_guid.entityId.entityKey, (uint8_t*)(&client_key), 3); + memcpy(&sample_id->writer_guid.entityId.entityKind, (uint8_t*)(&client_key) + 3, 1); + + memcpy(&sample_id->writer_guid.guidPrefix.data, (uint8_t*)(&id.id), 2); +} + bool flush_brokerless_queues() { for (size_t i = 0; i < brokerlessMessageQueue.index; i++) @@ -134,11 +176,23 @@ bool flush_brokerless_queues() { ucdrBuffer writer; ucdr_init_buffer(&writer, brokerlessBuffer, BROKERLESS_BUFFER_SIZE); - ucdr_serialize_array_char(&writer, brokerlessEntityMap.queue[hash_index].hash, BROKERLESS_HASH_SIZE); - ucdr_serialize_sequence_char(&writer, brokerlessMessageQueue.queue[i].data, brokerlessMessageQueue.queue[i].lenght); - udp_broadcast_send_datagram(writer.init, ucdr_buffer_length(&writer)); + if (brokerlessMessageQueue.queue[i].id.type == UXR_REQUESTER_ID || brokerlessMessageQueue.queue[i].id.type == UXR_REPLIER_ID){ + + ucdr_serialize_bool(&writer, brokerlessMessageQueue.queue[i].id.type == UXR_REQUESTER_ID); + + if (brokerlessMessageQueue.queue[i].id.type == UXR_REQUESTER_ID) + { + fill_brokerless_sample_id(&brokerlessMessageQueue.queue[i].sample_id, brokerlessMessageQueue.queue[i].id); + } + + uxr_serialize_SampleIdentity(&writer, &brokerlessMessageQueue.queue[i].sample_id); + } + + ucdr_serialize_sequence_char(&writer, (char*) brokerlessMessageQueue.queue[i].data, brokerlessMessageQueue.queue[i].lenght); + + brokerless_broadcast_send(writer.init, ucdr_buffer_length(&writer)); } } @@ -147,11 +201,11 @@ bool flush_brokerless_queues() return false; } -bool listen_brokerless(uint8_t** data, size_t* length, int timeout, uxrObjectId** id) +bool listen_brokerless(uint8_t** data, int timeout, uxrObjectId** id) { size_t readed_bytes = 0; - if (0 != brokerlessEntityMap.datareaders){ - readed_bytes = udp_broadcast_recv_datagram(&brokerlessBuffer, BROKERLESS_BUFFER_SIZE, timeout); + if (brokerlessEntityMap.datareaders || brokerlessEntityMap.requesters || brokerlessEntityMap.repliers){ + readed_bytes = brokerless_broadcast_recv(brokerlessBuffer, BROKERLESS_BUFFER_SIZE, timeout); } if(0 != readed_bytes){ @@ -162,15 +216,11 @@ bool listen_brokerless(uint8_t** data, size_t* length, int timeout, uxrObjectId* char hash[BROKERLESS_HASH_SIZE]; ucdr_deserialize_array_char(&reader, hash, BROKERLESS_HASH_SIZE); - int32_t hash_index = find_brokerless_hash_from_hash(hash); - if (-1 != hash_index && brokerlessEntityMap.queue[hash_index].id.type == UXR_DATAREADER_ID) + if (-1 != hash_index && brokerlessEntityMap.queue[hash_index].id.type != UXR_DATAWRITER_ID) { - *id = &brokerlessEntityMap.queue[hash_index]; - uint32_t aux; - ucdr_deserialize_uint32_t(&reader, &aux); - *length = aux; + *id = &brokerlessEntityMap.queue[hash_index].id; *data = reader.iterator; return true; } diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h index 099a32c5c..1a1335990 100644 --- a/src/c/brokerless/brokerless_internal.h +++ b/src/c/brokerless/brokerless_internal.h @@ -39,6 +39,7 @@ typedef struct { uint8_t *data; uint32_t lenght; uxrObjectId id; + SampleIdentity sample_id; } brokerlessMessage_t; typedef struct { @@ -59,15 +60,21 @@ typedef struct { uint8_t index; uint8_t datawriters; uint8_t datareaders; + uint8_t requesters; + uint8_t repliers; } brokerlessEntityMap_t; // Internal API +// TODO(Pablogs9): Complete this header list + void init_brokerless(); bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id); +bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id, SampleIdentity sample_id); bool add_brokerless_entity_hash(char* hash, uxrObjectId id); bool flush_brokerless_queues(); + #ifdef __cplusplus } #endif diff --git a/src/c/brokerless/brokerless_transport.h b/src/c/brokerless/brokerless_transport.h new file mode 100644 index 000000000..4ae5c5b1c --- /dev/null +++ b/src/c/brokerless/brokerless_transport.h @@ -0,0 +1,44 @@ +// Copyright 2017 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 _SRC_C_BROKERLESS_BROKERLESS_TRANSPORT_H_ +#define _SRC_C_BROKERLESS_BROKERLESS_TRANSPORT_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + +bool brokerless_init_transport(); + +bool brokerless_close_transport(); + +size_t brokerless_broadcast_send( + const uint8_t* buf, + size_t len); + +size_t brokerless_broadcast_recv( + uint8_t* buf, + size_t len, + int timeout); + +#ifdef __cplusplus +} +#endif + +#endif // _SRC_C_BROKERLESS_BROKERLESS_TRANSPORT_H_ diff --git a/src/c/brokerless/udp_transport_broadcast_posix.c b/src/c/brokerless/udp_transport_broadcast_posix.c index 551949fe4..23d35084c 100644 --- a/src/c/brokerless/udp_transport_broadcast_posix.c +++ b/src/c/brokerless/udp_transport_broadcast_posix.c @@ -14,7 +14,7 @@ int fd_recv; int fd_send; struct sockaddr_in send_addr, recv_addr; -bool init_udp_broadcast_transport_datagram() +bool brokerless_init_transport() { int trueflag = 1; fd_recv = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -41,12 +41,12 @@ bool init_udp_broadcast_transport_datagram() return true; } -bool close_udp_broadcast_transport_datagram() +bool brokerless_close_transport() { return ((0 == close(fd_recv)) && 0 == close(fd_send)); } -size_t udp_broadcast_send_datagram( +size_t brokerless_broadcast_send( const uint8_t* buf, size_t len) { @@ -64,7 +64,7 @@ size_t udp_broadcast_send_datagram( return rv; } -size_t udp_broadcast_recv_datagram( +size_t brokerless_broadcast_recv( uint8_t* buf, size_t len, int timeout) diff --git a/src/c/core/session/create_entities_ref.c b/src/c/core/session/create_entities_ref.c index e3369dbaf..9ad95aef4 100644 --- a/src/c/core/session/create_entities_ref.c +++ b/src/c/core/session/create_entities_ref.c @@ -74,6 +74,8 @@ uint16_t uxr_buffer_create_requester_ref( payload.object_representation.kind = DDS_XRCE_OBJK_REQUESTER; uxr_object_id_to_raw(participant_id, payload.object_representation._.requester.participant_id.data); + add_brokerless_entity_hash(ref, object_id); + return create_entity_ref(session, stream_id, object_id, ref, mode, &payload); } @@ -89,6 +91,8 @@ uint16_t uxr_buffer_create_replier_ref( payload.object_representation.kind = DDS_XRCE_OBJK_REPLIER; uxr_object_id_to_raw(participant_id, payload.object_representation._.replier.participant_id.data); + add_brokerless_entity_hash(ref, object_id); + return create_entity_ref(session, stream_id, object_id, ref, mode, &payload); } diff --git a/src/c/core/session/session.c b/src/c/core/session/session.c index c55b7e903..8ae39db8e 100644 --- a/src/c/core/session/session.c +++ b/src/c/core/session/session.c @@ -82,7 +82,7 @@ void uxr_init_session(uxrSession* session, uxrCommunication* comm, uint32_t key) uxr_init_session_info(&session->info, 0x81, key); uxr_init_stream_storage(&session->streams); - init_brokerless(); + init_brokerless(key); } void uxr_set_status_callback(uxrSession* session, uxrOnStatusFunc on_status_func, void* args) @@ -415,19 +415,54 @@ bool listen_message(uxrSession* session, int poll_ms) read_message(session, &ub); } - uint8_t* data_brokerless; size_t length_brokerless; uxrObjectId* object_id; - bool must_be_read_brokerless = listen_brokerless(&data_brokerless, &length_brokerless, poll_ms, &object_id); + uint8_t* data_brokerless; uxrObjectId* object_id; + bool must_be_read_brokerless = listen_brokerless(&data_brokerless, poll_ms, &object_id); if(must_be_read_brokerless) { ucdrBuffer temp_buffer; - ucdr_init_buffer(&temp_buffer, data_brokerless, length_brokerless); + // TODO (pablogs9): Here the available buffer size must be known, using BROKERLESS_BUFFER_SIZE can cause segfault. + ucdr_init_buffer(&temp_buffer, data_brokerless, BROKERLESS_BUFFER_SIZE); //CALL CALLBACK // object_id is the datareader (or service equivalent) that can be used to identify which topic should the callback must handle // request_id is related to the uxr_buffer_request_data request, so it can determine some limitations imposed into the communication -> NOT IMPLEMENTED BY NOW // stream_id should point to a new type of Brokerless stream -> NOT IMPLEMENTED BY NOW - uxrStreamId aux; - session->on_topic(session, *object_id, 0, aux, &temp_buffer, length_brokerless, session->on_topic_args); + if (object_id->type == UXR_DATAREADER_ID) + { + uxrStreamId stream = {0, 0, UXR_BROKERLESS, UXR_INPUT_STREAM}; + uint32_t length; + ucdr_deserialize_uint32_t(&temp_buffer, &length); + session->on_topic(session, *object_id, 0, stream, &temp_buffer, length, session->on_topic_args); + } + else + { + bool is_from_requester; + SampleIdentity sample_id; + uint32_t length; + + ucdr_deserialize_bool(&temp_buffer, &is_from_requester); + + // sample_id deserialization is done inside conditional in order to not deserialize when message should be dropped + + if (is_from_requester && object_id->type == UXR_REPLIER_ID) + { + uxr_deserialize_SampleIdentity(&temp_buffer, &sample_id); + ucdr_deserialize_uint32_t(&temp_buffer, &length); + session->on_request(session, *object_id, 0, &sample_id, &temp_buffer, length, session->on_request_args); + } + else if(!is_from_requester && object_id->type == UXR_REQUESTER_ID) + { + uxr_deserialize_SampleIdentity(&temp_buffer, &sample_id); + if (check_brokerless_sample_id(sample_id)) + { + ucdr_deserialize_uint32_t(&temp_buffer, &length); + session->on_reply(session, *object_id, 0, sample_id.sequence_number.low, &temp_buffer, length, session->on_reply_args); + } + } + + } + + } return must_be_read; diff --git a/src/c/core/session/write_access.c b/src/c/core/session/write_access.c index 9b10d4496..f810102a5 100644 --- a/src/c/core/session/write_access.c +++ b/src/c/core/session/write_access.c @@ -29,6 +29,11 @@ uint16_t uxr_buffer_request( WRITE_DATA_Payload_Data payload; rv = uxr_init_base_object_request(&session->info, requester_id, &payload.base); uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload); + + SampleIdentity sample_id; + sample_id.sequence_number.low = rv; + add_brokerless_message_with_sample_id(&ub, len, requester_id, sample_id); + ucdr_serialize_array_uint8_t(&ub, buffer, len); } @@ -54,6 +59,9 @@ uint16_t uxr_buffer_reply( rv = uxr_init_base_object_request(&session->info, replier_id, &payload.base); uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload); uxr_serialize_SampleIdentity(&ub, sample_id); + + add_brokerless_message_with_sample_id(&ub, len, replier_id, *sample_id); + ucdr_serialize_array_uint8_t(&ub, buffer, len); } From fa421a283e39c955b5d8c2aa38495aba6bcaa634 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Mon, 31 Aug 2020 09:41:09 +0200 Subject: [PATCH 06/25] TO REVERT: examples modification --- examples/PublishHelloWorld/main.c | 17 ++++++----- examples/ReplyAdder/main.c | 13 +++++---- examples/RequestAdder/main.c | 45 ++++++++++++++++++----------- examples/SubscribeHelloWorld/main.c | 2 +- 4 files changed, 45 insertions(+), 32 deletions(-) diff --git a/examples/PublishHelloWorld/main.c b/examples/PublishHelloWorld/main.c index d8c5594b4..e8cf12277 100644 --- a/examples/PublishHelloWorld/main.c +++ b/examples/PublishHelloWorld/main.c @@ -57,7 +57,7 @@ int main(int args, char** argv) // Streams uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; - uxrStreamId reliable_out = uxr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + uxrStreamId be_out = uxr_create_output_best_effort_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE); uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); @@ -71,7 +71,7 @@ int main(int args, char** argv) "" "" ""; - uint16_t participant_req = uxr_buffer_create_participant_xml(&session, reliable_out, participant_id, 0, participant_xml, UXR_REPLACE); + uint16_t participant_req = uxr_buffer_create_participant_xml(&session, be_out, participant_id, 0, participant_xml, UXR_REPLACE); uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "" @@ -80,11 +80,11 @@ int main(int args, char** argv) "HelloWorld" "" ""; - uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); + uint16_t topic_req = uxr_buffer_create_topic_xml(&session, be_out, topic_id, participant_id, topic_xml, UXR_REPLACE); uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); const char* publisher_xml = ""; - uint16_t publisher_req = uxr_buffer_create_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); + uint16_t publisher_req = uxr_buffer_create_publisher_xml(&session, be_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); const char* datawriter_xml = "" @@ -96,8 +96,8 @@ int main(int args, char** argv) "" "" ""; - // uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); - uint16_t datawriter_req = uxr_buffer_create_datawriter_ref(&session, reliable_out, datawriter_id, publisher_id, "prueba1", UXR_REPLACE); + // uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, be_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); + uint16_t datawriter_req = uxr_buffer_create_datawriter_ref(&session, be_out, datawriter_id, publisher_id, "prueba2", UXR_REPLACE); // Send create entities message and wait its status uint8_t status[4]; @@ -117,11 +117,12 @@ int main(int args, char** argv) ucdrBuffer ub; uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0); - uxr_prepare_output_stream(&session, reliable_out, datawriter_id, &ub, topic_size); + uxr_prepare_output_stream(&session, be_out, datawriter_id, &ub, topic_size); HelloWorld_serialize_topic(&ub, &topic); printf("Send topic: %s, id: %i\n", topic.message, topic.index); - connected = uxr_run_session_time(&session, 100); + connected = uxr_run_session_time(&session, 1000); + sleep(1); } // Delete resources diff --git a/examples/ReplyAdder/main.c b/examples/ReplyAdder/main.c index 3c5d3938f..67d251d6a 100644 --- a/examples/ReplyAdder/main.c +++ b/examples/ReplyAdder/main.c @@ -72,7 +72,7 @@ int main(int args, char** argv) char* ip = argv[1]; char* port = argv[2]; - uint32_t key = (args == 4) ? (uint32_t)atoi(argv[3]) : 0xCCCCDDDD; + uint32_t key = 0xCCCCDDDD; // Transport uxrUDPTransport transport; @@ -90,7 +90,7 @@ int main(int args, char** argv) if (!uxr_create_session(&session)) { printf("Error at init session.\n"); - return 1; + // return 1; } // Streams @@ -119,7 +119,7 @@ int main(int args, char** argv) "reply_type=\"reply_type\">" "" ""; - uint16_t replier_req = uxr_buffer_create_replier_xml(&session, reliable_out, replier_id, participant_id, replier_xml, UXR_REPLACE); + uint16_t replier_req = uxr_buffer_create_replier_ref(&session, reliable_out, replier_id, participant_id, "repli1", UXR_REPLACE); // Send create entities message and wait its status uint8_t status[2]; @@ -127,7 +127,7 @@ int main(int args, char** argv) if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 2)) { printf("Error at create entities: participant: %i requester: %i\n", status[0], status[1]); - return 1; + // return 1; } // Request requests @@ -137,10 +137,11 @@ int main(int args, char** argv) // Read request bool connected = true; - while (connected) + while (1) { uint8_t read_data_status; - connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); + // connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); + connected = uxr_run_session_time(&session, 100); } return 0; diff --git a/examples/RequestAdder/main.c b/examples/RequestAdder/main.c index 160f94ce8..1165c7f69 100644 --- a/examples/RequestAdder/main.c +++ b/examples/RequestAdder/main.c @@ -18,10 +18,13 @@ #include #include #include +#include #define STREAM_HISTORY 8 #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY +bool sended = false; + void on_reply( uxrSession* session, uxrObjectId object_id, @@ -38,6 +41,8 @@ void on_reply( uint64_t result; ucdr_deserialize_uint64_t(ub, &result); + sended = false; + #ifdef WIN32 printf("Reply received: %I64u [id: %d]\n", result, reply_id); #else @@ -55,7 +60,8 @@ int main(int args, char** argv) char* ip = argv[1]; char* port = argv[2]; - uint32_t key = (args == 4) ? (uint32_t)atoi(argv[3]) : 0xAAAABBBB; + srand(time(NULL)); // Initialization, should only be called once. + uint32_t key = rand(); // Transport uxrUDPTransport transport; @@ -102,7 +108,7 @@ int main(int args, char** argv) "reply_type=\"reply_type\">" "" ""; - uint16_t requester_req = uxr_buffer_create_requester_xml(&session, reliable_out, requester_id, participant_id, requester_xml, UXR_REPLACE); + uint16_t requester_req = uxr_buffer_create_requester_ref(&session, reliable_out, requester_id, participant_id, "repli1", UXR_REPLACE); // Send create entities message and wait its status uint8_t status[2]; @@ -110,7 +116,7 @@ int main(int args, char** argv) if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 2)) { printf("Error at create entities: participant: %i requester: %i\n", status[0], status[1]); - return 1; + // return 1; } // Request replies @@ -120,21 +126,26 @@ int main(int args, char** argv) // Write requests bool connected = true; - uint32_t count = 0; - while (connected) + uint32_t count = atoi(argv[3]); + while (1) { - uint8_t request[2 * 4] = {0}; - ucdrBuffer ub; - - ucdr_init_buffer(&ub, request, sizeof(request)); - ucdr_serialize_uint32_t(&ub, count); - ucdr_serialize_uint32_t(&ub, count); - - uint16_t request_id = uxr_buffer_request(&session, reliable_out, requester_id, request, sizeof(request)); - printf("Request sent: (%d + %d) [id: %d]\n", count, count, request_id); - connected = uxr_run_session_time(&session, 1000); - - ++count; + if (!sended) + { + uint8_t request[2 * 4] = {0}; + ucdrBuffer ub; + + ucdr_init_buffer(&ub, request, sizeof(request)); + ucdr_serialize_uint32_t(&ub, count); + ucdr_serialize_uint32_t(&ub, count); + + uint16_t request_id = uxr_buffer_request(&session, reliable_out, requester_id, request, sizeof(request)); + printf("Request sent: (%d + %d) [id: %d]\n", count, count, request_id); + + ++count; + sended = true; + } + + connected = uxr_run_session_time(&session, 10); } return 0; diff --git a/examples/SubscribeHelloWorld/main.c b/examples/SubscribeHelloWorld/main.c index 13e7973e6..465b4f5c8 100644 --- a/examples/SubscribeHelloWorld/main.c +++ b/examples/SubscribeHelloWorld/main.c @@ -150,7 +150,7 @@ int main(int args, char** argv) { // uint8_t read_data_status; // connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); - connected = uxr_run_session_time(&session, 10); + connected = uxr_run_session_timeout(&session, 1); } // Delete resources From ee356ec6aaab816c81a664dea4158ec2231b7e8a Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Tue, 1 Sep 2020 15:26:03 +0200 Subject: [PATCH 07/25] Updates --- src/c/brokerless/brokerless.c | 2 +- src/c/brokerless/brokerless_internal.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 315627622..cd26756e8 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -152,7 +152,7 @@ bool check_brokerless_sample_id(SampleIdentity sample_id) { // TODO (pablogs9): Check if requester id stored in the sample_id still exists - return !memcmp(&sample_id.writer_guid.entityId.entityKey, (uint8_t*)(&client_key), 3) && + return !memcmp(&sample_id.writer_guid.entityId.entityKey, (uint8_t*)(&client_key), 3) && !memcmp(&sample_id.writer_guid.entityId.entityKind, (uint8_t*)(&client_key) + 3, 1); } diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h index 1a1335990..0bf1d9bcc 100644 --- a/src/c/brokerless/brokerless_internal.h +++ b/src/c/brokerless/brokerless_internal.h @@ -26,7 +26,7 @@ extern "C" #include #include -typedef unsigned long hash_int_t; +typedef uint32_t hash_int_t; #define BROKERLESS_MESSAGE_QUEUE_LEN 100 #define BROKERLESS_ENTITY_MAP_LEN 10 From 423fd49cb89506923e2cdc972b895b94397afe0b Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Wed, 2 Sep 2020 10:06:11 +0200 Subject: [PATCH 08/25] Adding XML support --- src/c/brokerless/brokerless.c | 148 ++++++++++++++++++++++- src/c/core/session/create_entities_xml.c | 9 +- 2 files changed, 154 insertions(+), 3 deletions(-) diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index cd26756e8..00419a612 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -43,7 +43,7 @@ static brokerlessEntityMap_t brokerlessEntityMap; static uint8_t brokerlessBuffer[BROKERLESS_BUFFER_SIZE]; //================================================================== -// PRIVATE +// PRIVATE UTILS //================================================================== // djb2 by Dan Bernstein: http://www.cse.yorku.ca/~oz/hash.html @@ -60,6 +60,66 @@ void hash_brokerless(unsigned char *str, char* hash) } } +// Find first occurrence of tag in XML +bool find_tag_xml(char * xml, size_t len, char * tag, char ** content, size_t * content_len) +{ + size_t tag_len = strlen(tag); + bool found_begin = false; + bool found_end = false; + for (size_t i = 0; i < len; i++) + { + if (!found_begin && 0 == memcmp(&xml[i], tag, tag_len)) + { + size_t tag_opener_len = 0; + while(xml[i+tag_opener_len] != '>') + tag_opener_len++; + *content = &xml[i+tag_opener_len+1]; + found_begin = true; + } + else if(found_begin && 0 == memcmp(&xml[i], tag, tag_len) ) + { + *content_len = &xml[i-2] - *content; + found_end = true; + break; + } + } + + return found_begin && found_end; +} + +// Find property in first occurrence of tag in XML +bool find_tag_property(char * xml, size_t len, char * tag, char * property, char ** content, size_t * content_len) +{ + size_t tag_len = strlen(tag); + size_t property_len = strlen(property); + + bool found_tag = false; + bool found_property = false; + for (size_t i = 0; i < len; i++) + { + if (!found_tag && 0 == memcmp(&xml[i], tag, tag_len)) + { + found_tag = true; + } + else if(found_tag && 0 == memcmp(&xml[i], property, property_len) ) + { + *content = &xml[i+property_len+2]; + i += property_len+2; + *content_len = 0; + while(xml[i + (*content_len)] != '"') + *content_len += 1; + found_property = true; + break; + } + } + + return found_tag && found_property; +} + +//================================================================== +// PRIVATE +//================================================================== + void init_brokerless(uint32_t key) { brokerlessMessageQueue.index = 0; @@ -97,6 +157,92 @@ bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, uint32_t lenght, uxrO return false; } +bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) +{ + bool found = true; + char name_type_buffer[100]; + + if (id.type == UXR_DATAWRITER_ID || id.type == UXR_DATAREADER_ID) + { + char xml_strings[3][12] = { "dds", + "data_writer", + "topic" + }; + if (id.type == UXR_DATAREADER_ID){ + memcpy(xml_strings[1], "data_reader\0", 12); + } + + char * content_in = xml; + char * content_out; + size_t content_len_in = strlen(content_in); + size_t content_len_out; + + for (size_t i = 0; i < 3; i++) + { + printf("Looking %s\n", xml_strings[i]); + if(find_tag_xml(content_in, content_len_in, xml_strings[i], &content_out, &content_len_out)){ + content_in = content_out; + content_len_in = content_len_out; + } else { + printf("Error looking %s\n", xml_strings[i]); + return false; + } + } + + size_t topic_name_len; + size_t type_name_len; + + found &= find_tag_xml(content_in, content_len_in, "name", &content_out, &topic_name_len); + memcpy(name_type_buffer, content_out, topic_name_len); + + found &= find_tag_xml(content_in, content_len_in, "dataType", &content_out, &type_name_len); + memcpy(&name_type_buffer[topic_name_len], content_out, type_name_len); + + name_type_buffer[topic_name_len+type_name_len] = '\0'; + + found &= add_brokerless_entity_hash(name_type_buffer, id); + } + else if (id.type == UXR_REQUESTER_ID || id.type == UXR_REPLIER_ID) + { + char * content_out; + size_t service_name_len; + size_t request_type_name_len; + size_t reply_type_name_len; + + found &= find_tag_property( xml, + strlen(xml), + (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", + "service_name", + &content_out, + &service_name_len); + + memcpy(name_type_buffer, content_out, service_name_len); + + found &= find_tag_property( xml, + strlen(xml), + (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", + "request_type", + &content_out, + &request_type_name_len); + + memcpy(&name_type_buffer[service_name_len], content_out, service_name_len); + + found &= find_tag_property( xml, + strlen(xml), + (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", + "reply_type", + &content_out, + &reply_type_name_len); + + memcpy(&name_type_buffer[service_name_len+request_type_name_len], content_out, service_name_len); + + name_type_buffer[service_name_len+request_type_name_len+reply_type_name_len] = '\0'; + } + + return found; +} + + bool add_brokerless_entity_hash(char* ref, uxrObjectId id) { if (brokerlessEntityMap.index < BROKERLESS_ENTITY_MAP_LEN - 1) diff --git a/src/c/core/session/create_entities_xml.c b/src/c/core/session/create_entities_xml.c index 7a266c4fc..6c35af3ff 100644 --- a/src/c/core/session/create_entities_xml.c +++ b/src/c/core/session/create_entities_xml.c @@ -69,7 +69,7 @@ uint16_t uxr_buffer_create_datawriter_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER; uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data); - // TODO (pablogs9): ALERT! Is not possible to parse the XML here for extracting the name/type; + add_brokerless_entity_hash_from_xml(xml, object_id); return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } @@ -83,7 +83,8 @@ uint16_t uxr_buffer_create_datareader_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAREADER; uxr_object_id_to_raw(subscriber_id, payload.object_representation._.data_reader.subscriber_id.data); - // HERE WE CAN CATCH THE TYPE AND THE NAME OR REFERENCE AND ASSOCIATE IT WITH ITS NUMBER + add_brokerless_entity_hash_from_xml(xml, object_id); + return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } @@ -99,6 +100,8 @@ uint16_t uxr_buffer_create_requester_xml( payload.object_representation.kind = DDS_XRCE_OBJK_REQUESTER; uxr_object_id_to_raw(participant_id, payload.object_representation._.requester.participant_id.data); + add_brokerless_entity_hash_from_xml(xml, object_id); + return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } @@ -114,6 +117,8 @@ uint16_t uxr_buffer_create_replier_xml( payload.object_representation.kind = DDS_XRCE_OBJK_REPLIER; uxr_object_id_to_raw(participant_id, payload.object_representation._.replier.participant_id.data); + add_brokerless_entity_hash_from_xml(xml, object_id); + return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } From 3d781d76035e9ee6f9139e3c363f00fff20c7305 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Wed, 2 Sep 2020 10:32:25 +0200 Subject: [PATCH 09/25] Update services --- src/c/brokerless/brokerless.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 00419a612..f8f4f2bd4 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -200,7 +200,7 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) name_type_buffer[topic_name_len+type_name_len] = '\0'; - found &= add_brokerless_entity_hash(name_type_buffer, id); + found &= add_brokerless_entity_hash(name_type_buffer, id); } else if (id.type == UXR_REQUESTER_ID || id.type == UXR_REPLIER_ID) { @@ -237,6 +237,8 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) memcpy(&name_type_buffer[service_name_len+request_type_name_len], content_out, service_name_len); name_type_buffer[service_name_len+request_type_name_len+reply_type_name_len] = '\0'; + + found &= add_brokerless_entity_hash(name_type_buffer, id); } return found; From b7b6fe64c3fc437ae125e9b0292db06cb8fbb3d1 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Wed, 2 Sep 2020 15:17:15 +0200 Subject: [PATCH 10/25] Conditional build --- CMakeLists.txt | 1 + include/uxr/client/config.h.in | 2 + .../client/core/session/stream/stream_id.h | 2 +- src/c/brokerless/brokerless.c | 48 +++++++++++++-- src/c/brokerless/brokerless_internal.h | 15 +++-- src/c/core/session/create_entities_ref.c | 8 +++ src/c/core/session/create_entities_xml.c | 9 +++ src/c/core/session/session.c | 60 ++++--------------- src/c/core/session/write_access.c | 8 ++- 9 files changed, 90 insertions(+), 63 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54d3c5b82..ec76bdb03 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ set(UCLIENT_MIN_HEARTBEAT_TIME_INTERVAL 1 CACHE STRING "Set the time interval be 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_BROKERLESS_ENABLE "Enable brokerless transport (experimental)." ON) ############################################################################### # Dependencies diff --git a/include/uxr/client/config.h.in b/include/uxr/client/config.h.in index 220934d64..b2f638440 100644 --- a/include/uxr/client/config.h.in +++ b/include/uxr/client/config.h.in @@ -54,4 +54,6 @@ #define UXR_CONFIG_SERIAL_TRANSPORT_MTU @UCLIENT_SERIAL_TRANSPORT_MTU@ #endif +#cmakedefine UCLIENT_BROKERLESS_ENABLE + #endif // _UXR_CLIENT_CONFIG_H_ diff --git a/include/uxr/client/core/session/stream/stream_id.h b/include/uxr/client/core/session/stream/stream_id.h index b7933a8dd..c120c26f2 100644 --- a/include/uxr/client/core/session/stream/stream_id.h +++ b/include/uxr/client/core/session/stream/stream_id.h @@ -46,7 +46,7 @@ typedef enum uxrStreamType /** Identifies a reliable stream. */ UXR_RELIABLE_STREAM, /** Identifies a brokerless stream. */ - UXR_BROKERLESS + UCLIENT_BROKERLESS } uxrStreamType; diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index f8f4f2bd4..00c839a29 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -349,13 +349,13 @@ bool flush_brokerless_queues() return false; } -bool listen_brokerless(uint8_t** data, int timeout, uxrObjectId** id) -{ +bool listen_brokerless(uxrSession* session, int timeout) +{ size_t readed_bytes = 0; if (brokerlessEntityMap.datareaders || brokerlessEntityMap.requesters || brokerlessEntityMap.repliers){ readed_bytes = brokerless_broadcast_recv(brokerlessBuffer, BROKERLESS_BUFFER_SIZE, timeout); } - + if(0 != readed_bytes){ ucdrBuffer reader; @@ -367,9 +367,45 @@ bool listen_brokerless(uint8_t** data, int timeout, uxrObjectId** id) int32_t hash_index = find_brokerless_hash_from_hash(hash); if (-1 != hash_index && brokerlessEntityMap.queue[hash_index].id.type != UXR_DATAWRITER_ID) - { - *id = &brokerlessEntityMap.queue[hash_index].id; - *data = reader.iterator; + { + uxrObjectId * object_id = &brokerlessEntityMap.queue[hash_index].id; + + //CALL CALLBACK + // request_id is related to the uxr_buffer_request_data request, so it can determine some limitations imposed into the communication -> NOT IMPLEMENTED BY NOW + if (object_id->type == UXR_DATAREADER_ID) + { + uxrStreamId stream = {0, 0, UCLIENT_BROKERLESS, UXR_INPUT_STREAM}; + uint32_t length; + ucdr_deserialize_uint32_t(&reader, &length); + session->on_topic(session, *object_id, 0, stream, &reader, length, session->on_topic_args); + } + else + { + bool is_from_requester; + SampleIdentity sample_id; + uint32_t length; + + ucdr_deserialize_bool(&reader, &is_from_requester); + + // sample_id deserialization is done inside conditional in order to not deserialize when message should be dropped + + if (is_from_requester && object_id->type == UXR_REPLIER_ID) + { + uxr_deserialize_SampleIdentity(&reader, &sample_id); + ucdr_deserialize_uint32_t(&reader, &length); + session->on_request(session, *object_id, 0, &sample_id, &reader, length, session->on_request_args); + } + else if(!is_from_requester && object_id->type == UXR_REQUESTER_ID) + { + uxr_deserialize_SampleIdentity(&reader, &sample_id); + if (check_brokerless_sample_id(sample_id)) + { + ucdr_deserialize_uint32_t(&reader, &length); + session->on_reply(session, *object_id, 0, sample_id.sequence_number.low, &reader, length, session->on_reply_args); + } + } + + } return true; } } diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h index 0bf1d9bcc..c74456bab 100644 --- a/src/c/brokerless/brokerless_internal.h +++ b/src/c/brokerless/brokerless_internal.h @@ -22,6 +22,8 @@ extern "C" #include #include +#include +#include #include #include @@ -66,14 +68,17 @@ typedef struct { // Internal API -// TODO(Pablogs9): Complete this header list - -void init_brokerless(); +void init_brokerless(uint32_t key); bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id); bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id, SampleIdentity sample_id); -bool add_brokerless_entity_hash(char* hash, uxrObjectId id); +bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id); +bool add_brokerless_entity_hash(char* ref, uxrObjectId id); +int32_t find_brokerless_hash_from_id(uxrObjectId id); +int32_t find_brokerless_hash_from_hash(char* hash); +bool check_brokerless_sample_id(SampleIdentity sample_id); +void fill_brokerless_sample_id(SampleIdentity* sample_id, uxrObjectId id); bool flush_brokerless_queues(); - +bool listen_brokerless(uxrSession* session, int timeout); #ifdef __cplusplus } diff --git a/src/c/core/session/create_entities_ref.c b/src/c/core/session/create_entities_ref.c index 9ad95aef4..949e88dac 100644 --- a/src/c/core/session/create_entities_ref.c +++ b/src/c/core/session/create_entities_ref.c @@ -44,7 +44,9 @@ uint16_t uxr_buffer_create_datawriter_ref(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER; uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_entity_hash(ref, object_id); +#endif return create_entity_ref(session, stream_id, object_id, ref, mode, &payload); } @@ -57,7 +59,9 @@ uint16_t uxr_buffer_create_datareader_ref(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAREADER; uxr_object_id_to_raw(subscriber_id, payload.object_representation._.data_reader.subscriber_id.data); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_entity_hash(ref, object_id); +#endif return create_entity_ref(session, stream_id, object_id, ref, mode, &payload); } @@ -74,7 +78,9 @@ uint16_t uxr_buffer_create_requester_ref( payload.object_representation.kind = DDS_XRCE_OBJK_REQUESTER; uxr_object_id_to_raw(participant_id, payload.object_representation._.requester.participant_id.data); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_entity_hash(ref, object_id); +#endif return create_entity_ref(session, stream_id, object_id, ref, mode, &payload); } @@ -91,7 +97,9 @@ uint16_t uxr_buffer_create_replier_ref( payload.object_representation.kind = DDS_XRCE_OBJK_REPLIER; uxr_object_id_to_raw(participant_id, payload.object_representation._.replier.participant_id.data); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_entity_hash(ref, object_id); +#endif return create_entity_ref(session, stream_id, object_id, ref, mode, &payload); } diff --git a/src/c/core/session/create_entities_xml.c b/src/c/core/session/create_entities_xml.c index 6c35af3ff..ef190bad0 100644 --- a/src/c/core/session/create_entities_xml.c +++ b/src/c/core/session/create_entities_xml.c @@ -2,6 +2,7 @@ #include #include "common_create_entities_internal.h" +#include "../../brokerless/brokerless_internal.h" #include @@ -69,7 +70,9 @@ uint16_t uxr_buffer_create_datawriter_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER; uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_entity_hash_from_xml(xml, object_id); +#endif return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } @@ -83,7 +86,9 @@ uint16_t uxr_buffer_create_datareader_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAREADER; uxr_object_id_to_raw(subscriber_id, payload.object_representation._.data_reader.subscriber_id.data); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_entity_hash_from_xml(xml, object_id); +#endif return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } @@ -100,7 +105,9 @@ uint16_t uxr_buffer_create_requester_xml( payload.object_representation.kind = DDS_XRCE_OBJK_REQUESTER; uxr_object_id_to_raw(participant_id, payload.object_representation._.requester.participant_id.data); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_entity_hash_from_xml(xml, object_id); +#endif return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } @@ -117,7 +124,9 @@ uint16_t uxr_buffer_create_replier_xml( payload.object_representation.kind = DDS_XRCE_OBJK_REPLIER; uxr_object_id_to_raw(participant_id, payload.object_representation._.replier.participant_id.data); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_entity_hash_from_xml(xml, object_id); +#endif return create_entity_xml(session, stream_id, object_id, xml, mode, &payload); } diff --git a/src/c/core/session/session.c b/src/c/core/session/session.c index 8ae39db8e..6961405db 100644 --- a/src/c/core/session/session.c +++ b/src/c/core/session/session.c @@ -82,7 +82,10 @@ void uxr_init_session(uxrSession* session, uxrCommunication* comm, uint32_t key) uxr_init_session_info(&session->info, 0x81, key); uxr_init_stream_storage(&session->streams); + +#ifdef UCLIENT_BROKERLESS_ENABLE init_brokerless(key); +#endif } void uxr_set_status_callback(uxrSession* session, uxrOnStatusFunc on_status_func, void* args) @@ -372,7 +375,10 @@ bool uxr_buffer_performance(uxrSession *session, void uxr_flash_output_streams(uxrSession* session) { + +#ifdef UCLIENT_BROKERLESS_ENABLE flush_brokerless_queues(); +#endif for(uint8_t i = 0; i < session->streams.output_best_effort_size; ++i) { @@ -415,56 +421,10 @@ bool listen_message(uxrSession* session, int poll_ms) read_message(session, &ub); } - uint8_t* data_brokerless; uxrObjectId* object_id; - bool must_be_read_brokerless = listen_brokerless(&data_brokerless, poll_ms, &object_id); - if(must_be_read_brokerless) - { - ucdrBuffer temp_buffer; - // TODO (pablogs9): Here the available buffer size must be known, using BROKERLESS_BUFFER_SIZE can cause segfault. - ucdr_init_buffer(&temp_buffer, data_brokerless, BROKERLESS_BUFFER_SIZE); - - //CALL CALLBACK - // object_id is the datareader (or service equivalent) that can be used to identify which topic should the callback must handle - // request_id is related to the uxr_buffer_request_data request, so it can determine some limitations imposed into the communication -> NOT IMPLEMENTED BY NOW - // stream_id should point to a new type of Brokerless stream -> NOT IMPLEMENTED BY NOW - if (object_id->type == UXR_DATAREADER_ID) - { - uxrStreamId stream = {0, 0, UXR_BROKERLESS, UXR_INPUT_STREAM}; - uint32_t length; - ucdr_deserialize_uint32_t(&temp_buffer, &length); - session->on_topic(session, *object_id, 0, stream, &temp_buffer, length, session->on_topic_args); - } - else - { - bool is_from_requester; - SampleIdentity sample_id; - uint32_t length; - - ucdr_deserialize_bool(&temp_buffer, &is_from_requester); - - // sample_id deserialization is done inside conditional in order to not deserialize when message should be dropped - - if (is_from_requester && object_id->type == UXR_REPLIER_ID) - { - uxr_deserialize_SampleIdentity(&temp_buffer, &sample_id); - ucdr_deserialize_uint32_t(&temp_buffer, &length); - session->on_request(session, *object_id, 0, &sample_id, &temp_buffer, length, session->on_request_args); - } - else if(!is_from_requester && object_id->type == UXR_REQUESTER_ID) - { - uxr_deserialize_SampleIdentity(&temp_buffer, &sample_id); - if (check_brokerless_sample_id(sample_id)) - { - ucdr_deserialize_uint32_t(&temp_buffer, &length); - session->on_reply(session, *object_id, 0, sample_id.sequence_number.low, &temp_buffer, length, session->on_reply_args); - } - } - - } - - - } - +#ifdef UCLIENT_BROKERLESS_ENABLE + listen_brokerless(session, poll_ms); +#endif + return must_be_read; } diff --git a/src/c/core/session/write_access.c b/src/c/core/session/write_access.c index f810102a5..069196951 100644 --- a/src/c/core/session/write_access.c +++ b/src/c/core/session/write_access.c @@ -29,10 +29,12 @@ uint16_t uxr_buffer_request( WRITE_DATA_Payload_Data payload; rv = uxr_init_base_object_request(&session->info, requester_id, &payload.base); uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload); - + +#ifdef UCLIENT_BROKERLESS_ENABLE SampleIdentity sample_id; sample_id.sequence_number.low = rv; add_brokerless_message_with_sample_id(&ub, len, requester_id, sample_id); +#endif ucdr_serialize_array_uint8_t(&ub, buffer, len); } @@ -60,7 +62,9 @@ uint16_t uxr_buffer_reply( uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload); uxr_serialize_SampleIdentity(&ub, sample_id); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_message_with_sample_id(&ub, len, replier_id, *sample_id); +#endif ucdr_serialize_array_uint8_t(&ub, buffer, len); } @@ -84,7 +88,9 @@ bool uxr_prepare_output_stream(uxrSession* session, uxrStreamId stream_id, uxrOb ucdr_init_buffer(ub, ub->iterator, (size_t)(ub->final - ub->iterator)); ucdr_set_on_full_buffer_callback(ub, on_full_buffer, args); +#ifdef UCLIENT_BROKERLESS_ENABLE add_brokerless_message(ub, topic_size, datawriter_id); +#endif } return !ub->error; From 9e1c1306f7cf5ad31b12118328ae4fa7a7298e8d Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Thu, 3 Sep 2020 10:31:35 +0200 Subject: [PATCH 11/25] Added examples --- examples/BrokerlessPublisher/CMakeLists.txt | 49 +++++++++ examples/BrokerlessPublisher/main.c | 95 ++++++++++++++++ examples/BrokerlessSubscriber/CMakeLists.txt | 50 +++++++++ examples/BrokerlessSubscriber/main.c | 108 +++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 examples/BrokerlessPublisher/CMakeLists.txt create mode 100644 examples/BrokerlessPublisher/main.c create mode 100644 examples/BrokerlessSubscriber/CMakeLists.txt create mode 100644 examples/BrokerlessSubscriber/main.c diff --git a/examples/BrokerlessPublisher/CMakeLists.txt b/examples/BrokerlessPublisher/CMakeLists.txt new file mode 100644 index 000000000..1dd2d00c1 --- /dev/null +++ b/examples/BrokerlessPublisher/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright 2017 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) +if (${CMAKE_VERSION} VERSION_GREATER 3.0) + cmake_policy(SET CMP0048 NEW) +endif() + +project(BrokerlessPublisher) + +if(NOT UCLIENT_BUILD_EXAMPLES) + find_package(microxrcedds_client REQUIRED) +endif() + +if(NOT UCLIENT_PROFILE_UDP) + message(WARNING "Can not compile example: The UCLIENT_PROFILE_UDP must be enabled.") +else() + add_executable(${PROJECT_NAME} main.c) + if(MSVC OR MSVC_IDE) + target_compile_options(${PROJECT_NAME} PRIVATE /wd4996) + endif() + + set_target_properties(${PROJECT_NAME} PROPERTIES + C_STANDARD 99 + C_STANDARD_REQUIRED YES + ) + + target_link_libraries(${PROJECT_NAME} microxrcedds_client $<$:-Wl,--gc-section,--no-export-dynamic>) + + if(UCLIENT_INSTALL_EXAMPLES) + install( + TARGETS + ${PROJECT_NAME} + RUNTIME DESTINATION + ${BIN_INSTALL_DIR} + ) + endif() +endif() diff --git a/examples/BrokerlessPublisher/main.c b/examples/BrokerlessPublisher/main.c new file mode 100644 index 000000000..eade9b7d1 --- /dev/null +++ b/examples/BrokerlessPublisher/main.c @@ -0,0 +1,95 @@ +// Copyright 2017 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. + +#include +#include +#include + +#include //printf +#include //strcmp +#include //atoi + +#define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU + +int main(int args, char** argv) +{ + // Session + uxrSession session; + uxr_init_session(&session, &brokerless_comm_stub, 0xAAAABBBB); + + // Streams + uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; + uxrStreamId best_effort_output = uxr_create_output_best_effort_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE); + + // Create entities + uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); + const char* participant_xml = "" + "" + "" + "default_xrce_participant" + "" + "" + ""; + uint16_t participant_req = uxr_buffer_create_participant_xml(&session, best_effort_output, participant_id, 0, participant_xml, UXR_REPLACE); + + uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); + const char* topic_xml = "" + "" + "HelloWorldTopic" + "HelloWorld" + "" + ""; + uint16_t topic_req = uxr_buffer_create_topic_xml(&session, best_effort_output, topic_id, participant_id, topic_xml, UXR_REPLACE); + + uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); + const char* publisher_xml = ""; + uint16_t publisher_req = uxr_buffer_create_publisher_xml(&session, best_effort_output, publisher_id, participant_id, publisher_xml, UXR_REPLACE); + + uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); + const char* datawriter_xml = "" + "" + "" + "NO_KEY" + "HelloWorldTopic" + "HelloWorld" + "" + "" + ""; + uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, best_effort_output, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); + + // Write topics + char data[50]; + data[49] = '\0'; + memset(data, 96+1, 49); + + while(1) + { + ucdrBuffer ub; + + memset(data, 96+((data[0]-96+1)%25), 49); + + uxr_prepare_output_stream(&session, best_effort_output, datawriter_id, &ub, 50); + ucdr_serialize_array_char(&ub, data, 50); + + printf("Send topic: %s\n", data); + + uxr_run_session_timeout(&session, 10); + sleep(1); + } + + // Delete resources + uxr_delete_session(&session); + + return 0; +} diff --git a/examples/BrokerlessSubscriber/CMakeLists.txt b/examples/BrokerlessSubscriber/CMakeLists.txt new file mode 100644 index 000000000..37f73b846 --- /dev/null +++ b/examples/BrokerlessSubscriber/CMakeLists.txt @@ -0,0 +1,50 @@ +# Copyright 2017 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) +if (${CMAKE_VERSION} VERSION_GREATER 3.0) + cmake_policy(SET CMP0048 NEW) +endif() + +project(BrokerlessSubscriber) + +if(NOT UCLIENT_BUILD_EXAMPLES) + find_package(microxrcedds_client REQUIRED) +endif() + +if(NOT UCLIENT_PROFILE_UDP) + message(WARNING "Can not compile example: The UCLIENT_PROFILE_UDP must be enabled.") +else() + add_executable(${PROJECT_NAME} main.c) + if(MSVC OR MSVC_IDE) + target_compile_options(${PROJECT_NAME} PRIVATE /wd4996) + endif() + + set_target_properties(${PROJECT_NAME} PROPERTIES + C_STANDARD 99 + C_STANDARD_REQUIRED YES + ) + + + target_link_libraries(${PROJECT_NAME} microxrcedds_client $<$:-Wl,--gc-section,--no-export-dynamic>) + + if(UCLIENT_INSTALL_EXAMPLES) + install( + TARGETS + ${PROJECT_NAME} + RUNTIME DESTINATION + ${BIN_INSTALL_DIR} + ) + endif() +endif() diff --git a/examples/BrokerlessSubscriber/main.c b/examples/BrokerlessSubscriber/main.c new file mode 100644 index 000000000..a5a901db0 --- /dev/null +++ b/examples/BrokerlessSubscriber/main.c @@ -0,0 +1,108 @@ +// Copyright 2017 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. + +#include +#include + +#include //printf +#include //strcmp +#include //atoi + +#define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU + +uint32_t last_index = -1; +void on_topic( + uxrSession* session, + uxrObjectId object_id, + uint16_t request_id, + uxrStreamId stream_id, + struct ucdrBuffer* ub, + uint16_t length, + void* args) +{ + (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length; + + char data[50]; + ucdr_deserialize_array_char(ub, data, 50); + + printf("Received topic: %s\n", data); +} + +int main(int args, char** argv) +{ + + // Session + uxrSession session; + uxr_init_session(&session, &brokerless_comm_stub, 0xCCCCDDDD); + uxr_set_topic_callback(&session, on_topic, NULL); + + // Streams + uint8_t output_best_effort_stream_buffer[BUFFER_SIZE]; + uxrStreamId best_effort_output = uxr_create_output_best_effort_stream(&session, output_best_effort_stream_buffer, BUFFER_SIZE); + + uxrStreamId best_effort_input = uxr_create_input_best_effort_stream(&session); + + // Create entities + uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); + const char* participant_xml = "" + "" + "" + "default_xrce_participant" + "" + "" + ""; + uint16_t participant_req = uxr_buffer_create_participant_xml(&session, best_effort_output, participant_id, 0, participant_xml, UXR_REPLACE); + + uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); + const char* topic_xml = "" + "" + "HelloWorldTopic" + "HelloWorld" + "" + ""; + uint16_t topic_req = uxr_buffer_create_topic_xml(&session, best_effort_output, topic_id, participant_id, topic_xml, UXR_REPLACE); + + uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); + const char* subscriber_xml = ""; + uint16_t subscriber_req = uxr_buffer_create_subscriber_xml(&session, best_effort_output, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); + + uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); + const char* datareader_xml = "" + "" + "" + "NO_KEY" + "HelloWorldTopic" + "HelloWorld" + "" + "" + ""; + uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, best_effort_output, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); + + // Request topics + uxrDeliveryControl delivery_control = {0}; + delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED; + uint16_t read_data_req = uxr_buffer_request_data(&session, best_effort_output, datareader_id, best_effort_input, &delivery_control); + + // Read topics + bool connected = true; + while(true) + { + connected = uxr_run_session_timeout(&session, 10); + } + + // Delete resources + uxr_delete_session(&session); + + return 0; +} From e13c9c547396640dc8c1609ae95f7e0a4d194cee Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Thu, 3 Sep 2020 10:33:21 +0200 Subject: [PATCH 12/25] Update --- CMakeLists.txt | 13 +++++- include/uxr/client/brokerless/brokerless.h | 45 +++++++++++++++++++ include/uxr/client/config.h.in | 4 ++ src/c/brokerless/brokerless.c | 15 +++---- src/c/brokerless/brokerless_internal.h | 8 +--- .../udp_transport_broadcast_posix.c | 14 +++--- 6 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 include/uxr/client/brokerless/brokerless.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ec76bdb03..5e86d34a6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,10 @@ 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_BROKERLESS_ENABLE "Enable brokerless transport (experimental)." ON) +set(UCLIENT_BROKERLESS_PORT 9999 CACHE STRING "Brokerless UDP port (experimental)") +set(UCLIENT_BROKERLESS_ENTITY_MAP_LEN 10 CACHE STRING "Brokerless entity map length port (experimental)") +set(UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN 100 CACHE STRING "Brokerless message queue length (experimental)") +set(UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN 500 CACHE STRING "Brokerless internal buffer length (experimental)") ############################################################################### # Dependencies @@ -229,8 +233,8 @@ set(SRCS src/c/core/session/create_entities_xml.c src/c/core/session/read_access.c src/c/core/session/write_access.c - src/c/brokerless/brokerless.c - src/c/brokerless/udp_transport_broadcast_posix.c + $<$:src/c/brokerless/brokerless.c> + $<$:src/c/brokerless/udp_transport_broadcast_posix.c> $<$,$>:src/c/core/log/log.c> ${_transport_src} ) @@ -351,6 +355,11 @@ if(UCLIENT_BUILD_EXAMPLES) add_subdirectory(examples/SubscribeHelloWorldP2P) endif() +if(UCLIENT_BUILD_EXAMPLES AND UCLIENT_BROKERLESS_ENABLE) + add_subdirectory(examples/BrokerlessPublisher) + add_subdirectory(examples/BrokerlessSubscriber) +endif() + ############################################################################### # Tests ############################################################################### diff --git a/include/uxr/client/brokerless/brokerless.h b/include/uxr/client/brokerless/brokerless.h new file mode 100644 index 000000000..fabd3b8b1 --- /dev/null +++ b/include/uxr/client/brokerless/brokerless.h @@ -0,0 +1,45 @@ +// Copyright 2017 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 _SRC_C_BROKERLESS_BROKERLESS_H_ +#define _SRC_C_BROKERLESS_BROKERLESS_H_ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +bool brokerless_send_stub(void* instance, const uint8_t* buf, size_t len){ + return true; +} + +bool brokerless_recv_stub(void* instance, uint8_t** buf, size_t* len, int timeout){ + return true; +} + +const uxrCommunication brokerless_comm_stub = { + NULL, + brokerless_send_stub, + brokerless_recv_stub, + NULL, + 0 +}; + +#ifdef __cplusplus +} +#endif + +#endif // _SRC_C_BROKERLESS_BROKERLESS_H_ diff --git a/include/uxr/client/config.h.in b/include/uxr/client/config.h.in index b2f638440..45a214de2 100644 --- a/include/uxr/client/config.h.in +++ b/include/uxr/client/config.h.in @@ -55,5 +55,9 @@ #endif #cmakedefine UCLIENT_BROKERLESS_ENABLE +#define UCLIENT_BROKERLESS_PORT @UCLIENT_BROKERLESS_PORT@ +#define UCLIENT_BROKERLESS_ENTITY_MAP_LEN @UCLIENT_BROKERLESS_ENTITY_MAP_LEN@ +#define UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN @UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN@ +#define UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN @UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN@ #endif // _UXR_CLIENT_CONFIG_H_ diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 00c839a29..e82614de7 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -40,7 +40,7 @@ static uint32_t client_key; static brokerlessMessageQueue_t brokerlessMessageQueue; static brokerlessEntityMap_t brokerlessEntityMap; -static uint8_t brokerlessBuffer[BROKERLESS_BUFFER_SIZE]; +static uint8_t brokerlessBuffer[UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN]; //================================================================== // PRIVATE UTILS @@ -142,7 +142,7 @@ bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id) bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id, SampleIdentity sample_id) { - if (brokerlessMessageQueue.index < BROKERLESS_MESSAGE_QUEUE_LEN - 1) + if (brokerlessMessageQueue.index < UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN - 1) { brokerlessMessageQueue.queue[brokerlessMessageQueue.index].data = ub->iterator; brokerlessMessageQueue.queue[brokerlessMessageQueue.index].lenght = lenght; @@ -179,12 +179,10 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) for (size_t i = 0; i < 3; i++) { - printf("Looking %s\n", xml_strings[i]); if(find_tag_xml(content_in, content_len_in, xml_strings[i], &content_out, &content_len_out)){ content_in = content_out; content_len_in = content_len_out; } else { - printf("Error looking %s\n", xml_strings[i]); return false; } } @@ -247,7 +245,7 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) bool add_brokerless_entity_hash(char* ref, uxrObjectId id) { - if (brokerlessEntityMap.index < BROKERLESS_ENTITY_MAP_LEN - 1) + if (brokerlessEntityMap.index < UCLIENT_BROKERLESS_ENTITY_MAP_LEN - 1) { hash_brokerless((unsigned char*) ref, brokerlessEntityMap.queue[brokerlessEntityMap.index].hash); @@ -323,7 +321,7 @@ bool flush_brokerless_queues() if (-1 != hash_index) { ucdrBuffer writer; - ucdr_init_buffer(&writer, brokerlessBuffer, BROKERLESS_BUFFER_SIZE); + ucdr_init_buffer(&writer, brokerlessBuffer, UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN); ucdr_serialize_array_char(&writer, brokerlessEntityMap.queue[hash_index].hash, BROKERLESS_HASH_SIZE); if (brokerlessMessageQueue.queue[i].id.type == UXR_REQUESTER_ID || brokerlessMessageQueue.queue[i].id.type == UXR_REPLIER_ID){ @@ -353,7 +351,7 @@ bool listen_brokerless(uxrSession* session, int timeout) { size_t readed_bytes = 0; if (brokerlessEntityMap.datareaders || brokerlessEntityMap.requesters || brokerlessEntityMap.repliers){ - readed_bytes = brokerless_broadcast_recv(brokerlessBuffer, BROKERLESS_BUFFER_SIZE, timeout); + readed_bytes = brokerless_broadcast_recv(brokerlessBuffer, UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN, timeout); } if(0 != readed_bytes){ @@ -370,8 +368,7 @@ bool listen_brokerless(uxrSession* session, int timeout) { uxrObjectId * object_id = &brokerlessEntityMap.queue[hash_index].id; - //CALL CALLBACK - // request_id is related to the uxr_buffer_request_data request, so it can determine some limitations imposed into the communication -> NOT IMPLEMENTED BY NOW + // TODO (pablogs9): request_id is related to the uxr_buffer_request_data request, so it can determine some limitations imposed into the communication -> NOT IMPLEMENTED BY NOW if (object_id->type == UXR_DATAREADER_ID) { uxrStreamId stream = {0, 0, UCLIENT_BROKERLESS, UXR_INPUT_STREAM}; diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h index c74456bab..c5791a1a2 100644 --- a/src/c/brokerless/brokerless_internal.h +++ b/src/c/brokerless/brokerless_internal.h @@ -29,11 +29,7 @@ extern "C" #include typedef uint32_t hash_int_t; - -#define BROKERLESS_MESSAGE_QUEUE_LEN 100 -#define BROKERLESS_ENTITY_MAP_LEN 10 #define BROKERLESS_HASH_SIZE sizeof(hash_int_t) -#define BROKERLESS_BUFFER_SIZE 1000 // Outcomming message queue @@ -45,7 +41,7 @@ typedef struct { } brokerlessMessage_t; typedef struct { - brokerlessMessage_t queue[BROKERLESS_MESSAGE_QUEUE_LEN]; + brokerlessMessage_t queue[UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN]; uint8_t index; } brokerlessMessageQueue_t; @@ -58,7 +54,7 @@ typedef struct { typedef struct { - brokerlessEntityHash_t queue[BROKERLESS_ENTITY_MAP_LEN]; + brokerlessEntityHash_t queue[UCLIENT_BROKERLESS_ENTITY_MAP_LEN]; uint8_t index; uint8_t datawriters; uint8_t datareaders; diff --git a/src/c/brokerless/udp_transport_broadcast_posix.c b/src/c/brokerless/udp_transport_broadcast_posix.c index 23d35084c..f31f367ee 100644 --- a/src/c/brokerless/udp_transport_broadcast_posix.c +++ b/src/c/brokerless/udp_transport_broadcast_posix.c @@ -1,4 +1,6 @@ +#include "brokerless_internal.h" + #include #include @@ -8,7 +10,6 @@ #include #define BROADCAST_DEFAULT_IP "255.255.255.255" -#define BROADCAST_DEFAULT_PORT 9000 int fd_recv; int fd_send; @@ -28,12 +29,12 @@ bool brokerless_init_transport() memset(&send_addr, 0, sizeof send_addr); send_addr.sin_family = AF_INET; - send_addr.sin_port = (in_port_t) htons(BROADCAST_DEFAULT_PORT); + send_addr.sin_port = (in_port_t) htons(UCLIENT_BROKERLESS_PORT); inet_aton(BROADCAST_DEFAULT_IP, &send_addr.sin_addr); memset(&recv_addr, 0, sizeof recv_addr); recv_addr.sin_family = AF_INET; - recv_addr.sin_port = (in_port_t) htons(BROADCAST_DEFAULT_PORT); + recv_addr.sin_port = (in_port_t) htons(UCLIENT_BROKERLESS_PORT); recv_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(fd_recv, (struct sockaddr*) &recv_addr, sizeof recv_addr); @@ -51,9 +52,7 @@ size_t brokerless_broadcast_send( size_t len) { size_t rv = 0; - - // printf("Sending %d bytes brokerless\n",len); - + ssize_t bytes_sent = sendto(fd_send, buf, len, 0, (struct sockaddr*) &send_addr, sizeof(send_addr)); if (0 > bytes_sent) { rv = 0; @@ -84,9 +83,6 @@ size_t brokerless_broadcast_recv( ssize_t readed_bytes = recvfrom(fd_recv, (void*)buf, len, 0, &from, &fromlen); - // if(readed_bytes != -1) - // printf("Received %d/%d bytes brokerless from %s:%d Timeout %d\n", readed_bytes, len, inet_ntoa(from.sin_addr), ntohs(from.sin_port), timeout); - return (readed_bytes > 0) ? readed_bytes : 0; } From c901d92869317c1806b6598ecef25208099b1066 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Thu, 3 Sep 2020 11:42:33 +0200 Subject: [PATCH 13/25] Fix --- include/uxr/client/core/session/stream/stream_id.h | 2 +- src/c/brokerless/brokerless.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uxr/client/core/session/stream/stream_id.h b/include/uxr/client/core/session/stream/stream_id.h index c120c26f2..b7933a8dd 100644 --- a/include/uxr/client/core/session/stream/stream_id.h +++ b/include/uxr/client/core/session/stream/stream_id.h @@ -46,7 +46,7 @@ typedef enum uxrStreamType /** Identifies a reliable stream. */ UXR_RELIABLE_STREAM, /** Identifies a brokerless stream. */ - UCLIENT_BROKERLESS + UXR_BROKERLESS } uxrStreamType; diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index e82614de7..3ebc37cfe 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -371,7 +371,7 @@ bool listen_brokerless(uxrSession* session, int timeout) // TODO (pablogs9): request_id is related to the uxr_buffer_request_data request, so it can determine some limitations imposed into the communication -> NOT IMPLEMENTED BY NOW if (object_id->type == UXR_DATAREADER_ID) { - uxrStreamId stream = {0, 0, UCLIENT_BROKERLESS, UXR_INPUT_STREAM}; + uxrStreamId stream = {0, 0, UXR_BROKERLESS, UXR_INPUT_STREAM}; uint32_t length; ucdr_deserialize_uint32_t(&reader, &length); session->on_topic(session, *object_id, 0, stream, &reader, length, session->on_topic_args); From 24f71eead378cab6fea4a8d0acfdeff8bebc8dda Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Thu, 3 Sep 2020 12:02:03 +0200 Subject: [PATCH 14/25] Fix warnings --- examples/BrokerlessPublisher/main.c | 1 + examples/PublishHelloWorld/main.c | 1 + include/uxr/client/brokerless/brokerless.h | 2 +- src/c/brokerless/brokerless.c | 36 +++++++++---------- src/c/brokerless/brokerless_internal.h | 10 +++--- .../udp_transport_broadcast_posix.c | 8 ++--- src/c/core/session/stream/stream_id.c | 1 + 7 files changed, 31 insertions(+), 28 deletions(-) diff --git a/examples/BrokerlessPublisher/main.c b/examples/BrokerlessPublisher/main.c index eade9b7d1..b4009fedb 100644 --- a/examples/BrokerlessPublisher/main.c +++ b/examples/BrokerlessPublisher/main.c @@ -19,6 +19,7 @@ #include //printf #include //strcmp #include //atoi +#include //sleep #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU diff --git a/examples/PublishHelloWorld/main.c b/examples/PublishHelloWorld/main.c index e8cf12277..6aa33038c 100644 --- a/examples/PublishHelloWorld/main.c +++ b/examples/PublishHelloWorld/main.c @@ -20,6 +20,7 @@ #include //printf #include //strcmp #include //atoi +#include //sleep #define STREAM_HISTORY 8 #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY diff --git a/include/uxr/client/brokerless/brokerless.h b/include/uxr/client/brokerless/brokerless.h index fabd3b8b1..661ee9da8 100644 --- a/include/uxr/client/brokerless/brokerless.h +++ b/include/uxr/client/brokerless/brokerless.h @@ -30,7 +30,7 @@ bool brokerless_recv_stub(void* instance, uint8_t** buf, size_t* len, int timeou return true; } -const uxrCommunication brokerless_comm_stub = { +uxrCommunication brokerless_comm_stub = { NULL, brokerless_send_stub, brokerless_recv_stub, diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 3ebc37cfe..373037c56 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -52,8 +52,8 @@ void hash_brokerless(unsigned char *str, char* hash) hash_int_t int_hash = 5381; int c; - while (c = *str++) - int_hash = ((int_hash << 5) + int_hash) + c; /* hash * 33 + c */ + while ((c = *str++)) + int_hash = ((int_hash << 5) + int_hash) + (hash_int_t)c; /* hash * 33 + c */ for (size_t i = 0; i < BROKERLESS_HASH_SIZE; i++){ hash[i] = ((char*)&int_hash)[i]; @@ -61,7 +61,7 @@ void hash_brokerless(unsigned char *str, char* hash) } // Find first occurrence of tag in XML -bool find_tag_xml(char * xml, size_t len, char * tag, char ** content, size_t * content_len) +bool find_tag_xml(const char * xml, size_t len, char * tag, const char ** content, size_t * content_len) { size_t tag_len = strlen(tag); bool found_begin = false; @@ -78,7 +78,7 @@ bool find_tag_xml(char * xml, size_t len, char * tag, char ** content, size_t * } else if(found_begin && 0 == memcmp(&xml[i], tag, tag_len) ) { - *content_len = &xml[i-2] - *content; + *content_len = (size_t)(&xml[i-2] - *content); found_end = true; break; } @@ -88,7 +88,7 @@ bool find_tag_xml(char * xml, size_t len, char * tag, char ** content, size_t * } // Find property in first occurrence of tag in XML -bool find_tag_property(char * xml, size_t len, char * tag, char * property, char ** content, size_t * content_len) +bool find_tag_property(const char * xml, size_t len, char * tag, char * property, const char ** content, size_t * content_len) { size_t tag_len = strlen(tag); size_t property_len = strlen(property); @@ -140,7 +140,7 @@ bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id) return add_brokerless_message_with_sample_id(ub, lenght, id, sample_id); } -bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id, SampleIdentity sample_id) +bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, size_t lenght, uxrObjectId id, SampleIdentity sample_id) { if (brokerlessMessageQueue.index < UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN - 1) { @@ -172,14 +172,14 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) memcpy(xml_strings[1], "data_reader\0", 12); } - char * content_in = xml; + const char * content_in = xml; char * content_out; size_t content_len_in = strlen(content_in); size_t content_len_out; for (size_t i = 0; i < 3; i++) { - if(find_tag_xml(content_in, content_len_in, xml_strings[i], &content_out, &content_len_out)){ + if(find_tag_xml(content_in, content_len_in, xml_strings[i], (const char **)&content_out, &content_len_out)){ content_in = content_out; content_len_in = content_len_out; } else { @@ -190,10 +190,10 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) size_t topic_name_len; size_t type_name_len; - found &= find_tag_xml(content_in, content_len_in, "name", &content_out, &topic_name_len); + found &= find_tag_xml(content_in, content_len_in, "name", (const char **)&content_out, &topic_name_len); memcpy(name_type_buffer, content_out, topic_name_len); - found &= find_tag_xml(content_in, content_len_in, "dataType", &content_out, &type_name_len); + found &= find_tag_xml(content_in, content_len_in, "dataType", (const char **)&content_out, &type_name_len); memcpy(&name_type_buffer[topic_name_len], content_out, type_name_len); name_type_buffer[topic_name_len+type_name_len] = '\0'; @@ -211,7 +211,7 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) strlen(xml), (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", "service_name", - &content_out, + (const char **)&content_out, &service_name_len); memcpy(name_type_buffer, content_out, service_name_len); @@ -220,7 +220,7 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) strlen(xml), (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", "request_type", - &content_out, + (const char **)&content_out, &request_type_name_len); memcpy(&name_type_buffer[service_name_len], content_out, service_name_len); @@ -229,7 +229,7 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) strlen(xml), (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", "reply_type", - &content_out, + (const char **)&content_out, &reply_type_name_len); memcpy(&name_type_buffer[service_name_len+request_type_name_len], content_out, service_name_len); @@ -243,7 +243,7 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) } -bool add_brokerless_entity_hash(char* ref, uxrObjectId id) +bool add_brokerless_entity_hash(const char* ref, uxrObjectId id) { if (brokerlessEntityMap.index < UCLIENT_BROKERLESS_ENTITY_MAP_LEN - 1) { @@ -336,7 +336,7 @@ bool flush_brokerless_queues() uxr_serialize_SampleIdentity(&writer, &brokerlessMessageQueue.queue[i].sample_id); } - ucdr_serialize_sequence_char(&writer, (char*) brokerlessMessageQueue.queue[i].data, brokerlessMessageQueue.queue[i].lenght); + ucdr_serialize_sequence_char(&writer, (char*) brokerlessMessageQueue.queue[i].data, (uint32_t)brokerlessMessageQueue.queue[i].lenght); brokerless_broadcast_send(writer.init, ucdr_buffer_length(&writer)); } @@ -374,7 +374,7 @@ bool listen_brokerless(uxrSession* session, int timeout) uxrStreamId stream = {0, 0, UXR_BROKERLESS, UXR_INPUT_STREAM}; uint32_t length; ucdr_deserialize_uint32_t(&reader, &length); - session->on_topic(session, *object_id, 0, stream, &reader, length, session->on_topic_args); + session->on_topic(session, *object_id, 0, stream, &reader, (uint16_t)length, session->on_topic_args); } else { @@ -390,7 +390,7 @@ bool listen_brokerless(uxrSession* session, int timeout) { uxr_deserialize_SampleIdentity(&reader, &sample_id); ucdr_deserialize_uint32_t(&reader, &length); - session->on_request(session, *object_id, 0, &sample_id, &reader, length, session->on_request_args); + session->on_request(session, *object_id, 0, &sample_id, &reader, (uint16_t)length, session->on_request_args); } else if(!is_from_requester && object_id->type == UXR_REQUESTER_ID) { @@ -398,7 +398,7 @@ bool listen_brokerless(uxrSession* session, int timeout) if (check_brokerless_sample_id(sample_id)) { ucdr_deserialize_uint32_t(&reader, &length); - session->on_reply(session, *object_id, 0, sample_id.sequence_number.low, &reader, length, session->on_reply_args); + session->on_reply(session, *object_id, 0, (uint16_t)sample_id.sequence_number.low, &reader, (uint16_t)length, session->on_reply_args); } } diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h index c5791a1a2..0fb45bcef 100644 --- a/src/c/brokerless/brokerless_internal.h +++ b/src/c/brokerless/brokerless_internal.h @@ -35,14 +35,14 @@ typedef uint32_t hash_int_t; typedef struct { uint8_t *data; - uint32_t lenght; + size_t lenght; uxrObjectId id; SampleIdentity sample_id; } brokerlessMessage_t; typedef struct { brokerlessMessage_t queue[UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN]; - uint8_t index; + size_t index; } brokerlessMessageQueue_t; // Entities map @@ -55,7 +55,7 @@ typedef struct { typedef struct { brokerlessEntityHash_t queue[UCLIENT_BROKERLESS_ENTITY_MAP_LEN]; - uint8_t index; + size_t index; uint8_t datawriters; uint8_t datareaders; uint8_t requesters; @@ -66,9 +66,9 @@ typedef struct { void init_brokerless(uint32_t key); bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id); -bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id, SampleIdentity sample_id); +bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, size_t lenght, uxrObjectId id, SampleIdentity sample_id); bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id); -bool add_brokerless_entity_hash(char* ref, uxrObjectId id); +bool add_brokerless_entity_hash(const char* ref, uxrObjectId id); int32_t find_brokerless_hash_from_id(uxrObjectId id); int32_t find_brokerless_hash_from_hash(char* hash); bool check_brokerless_sample_id(SampleIdentity sample_id); diff --git a/src/c/brokerless/udp_transport_broadcast_posix.c b/src/c/brokerless/udp_transport_broadcast_posix.c index f31f367ee..896b248a0 100644 --- a/src/c/brokerless/udp_transport_broadcast_posix.c +++ b/src/c/brokerless/udp_transport_broadcast_posix.c @@ -57,7 +57,7 @@ size_t brokerless_broadcast_send( if (0 > bytes_sent) { rv = 0; } else { - rv = bytes_sent; + rv = (size_t)bytes_sent; } return rv; @@ -78,11 +78,11 @@ size_t brokerless_broadcast_recv( setsockopt(fd_recv, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); struct sockaddr_in from; - int fromlen; + uint fromlen; fromlen = sizeof(from); - ssize_t readed_bytes = recvfrom(fd_recv, (void*)buf, len, 0, &from, &fromlen); + ssize_t readed_bytes = recvfrom(fd_recv, (void*)buf, len, 0, (struct sockaddr * restrict)&from, (socklen_t * restrict)&fromlen); - return (readed_bytes > 0) ? readed_bytes : 0; + return (readed_bytes > 0) ? (size_t)readed_bytes : 0; } diff --git a/src/c/core/session/stream/stream_id.c b/src/c/core/session/stream/stream_id.c index 27a15867b..0f7529587 100644 --- a/src/c/core/session/stream/stream_id.c +++ b/src/c/core/session/stream/stream_id.c @@ -20,6 +20,7 @@ uxrStreamId uxr_stream_id(uint8_t index, uxrStreamType type, uxrStreamDirection case UXR_NONE_STREAM: stream_id.raw = 0; break; + case UXR_BROKERLESS: case UXR_BEST_EFFORT_STREAM: stream_id.raw = (uint8_t)(index + BEST_EFFORT_STREAM_THRESHOLD); break; From 1cd3f85be9763c6d383712c98495a57b890fff70 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Thu, 3 Sep 2020 12:17:13 +0200 Subject: [PATCH 15/25] Typo --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e86d34a6..f67a684a0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ set(UCLIENT_MIN_HEARTBEAT_TIME_INTERVAL 1 CACHE STRING "Set the time interval be 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_BROKERLESS_ENABLE "Enable brokerless transport (experimental)." ON) set(UCLIENT_BROKERLESS_PORT 9999 CACHE STRING "Brokerless UDP port (experimental)") set(UCLIENT_BROKERLESS_ENTITY_MAP_LEN 10 CACHE STRING "Brokerless entity map length port (experimental)") From eded7e2227841fa5aa104a283421748102d3b31a Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Fri, 4 Sep 2020 09:00:30 +0200 Subject: [PATCH 16/25] Use on_data_flag --- include/uxr/client/brokerless/brokerless.h | 2 +- src/c/brokerless/brokerless.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/uxr/client/brokerless/brokerless.h b/include/uxr/client/brokerless/brokerless.h index 661ee9da8..0acc3f41d 100644 --- a/include/uxr/client/brokerless/brokerless.h +++ b/include/uxr/client/brokerless/brokerless.h @@ -27,7 +27,7 @@ bool brokerless_send_stub(void* instance, const uint8_t* buf, size_t len){ } bool brokerless_recv_stub(void* instance, uint8_t** buf, size_t* len, int timeout){ - return true; + return false; } uxrCommunication brokerless_comm_stub = { diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 373037c56..7e5f297a4 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -374,6 +374,7 @@ bool listen_brokerless(uxrSession* session, int timeout) uxrStreamId stream = {0, 0, UXR_BROKERLESS, UXR_INPUT_STREAM}; uint32_t length; ucdr_deserialize_uint32_t(&reader, &length); + session->on_data_flag = true; session->on_topic(session, *object_id, 0, stream, &reader, (uint16_t)length, session->on_topic_args); } else @@ -390,6 +391,7 @@ bool listen_brokerless(uxrSession* session, int timeout) { uxr_deserialize_SampleIdentity(&reader, &sample_id); ucdr_deserialize_uint32_t(&reader, &length); + session->on_data_flag = true; session->on_request(session, *object_id, 0, &sample_id, &reader, (uint16_t)length, session->on_request_args); } else if(!is_from_requester && object_id->type == UXR_REQUESTER_ID) @@ -398,6 +400,7 @@ bool listen_brokerless(uxrSession* session, int timeout) if (check_brokerless_sample_id(sample_id)) { ucdr_deserialize_uint32_t(&reader, &length); + session->on_data_flag = true; session->on_reply(session, *object_id, 0, (uint16_t)sample_id.sequence_number.low, &reader, (uint16_t)length, session->on_reply_args); } } From 87c5ca08058252a2dd2542f8dd575c46978bcd9e Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Fri, 4 Sep 2020 09:56:17 +0200 Subject: [PATCH 17/25] Fixes --- src/c/brokerless/brokerless.c | 47 ++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 7e5f297a4..3ed59e7a4 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -66,9 +66,9 @@ bool find_tag_xml(const char * xml, size_t len, char * tag, const char ** conten size_t tag_len = strlen(tag); bool found_begin = false; bool found_end = false; - for (size_t i = 0; i < len; i++) + for (size_t i = 1; i < len; i++) { - if (!found_begin && 0 == memcmp(&xml[i], tag, tag_len)) + if (!found_begin && 0 == memcmp(&xml[i], tag, tag_len) && xml[i-1] == '<') { size_t tag_opener_len = 0; while(xml[i+tag_opener_len] != '>') @@ -76,7 +76,7 @@ bool find_tag_xml(const char * xml, size_t len, char * tag, const char ** conten *content = &xml[i+tag_opener_len+1]; found_begin = true; } - else if(found_begin && 0 == memcmp(&xml[i], tag, tag_len) ) + else if(found_begin && 0 == memcmp(&xml[i], tag, tag_len) && xml[i-1] == '/') { *content_len = (size_t)(&xml[i-2] - *content); found_end = true; @@ -95,13 +95,13 @@ bool find_tag_property(const char * xml, size_t len, char * tag, char * property bool found_tag = false; bool found_property = false; - for (size_t i = 0; i < len; i++) + for (size_t i = 1; i < len; i++) { - if (!found_tag && 0 == memcmp(&xml[i], tag, tag_len)) + if (!found_tag && 0 == memcmp(&xml[i], tag, tag_len) && xml[i-1] == '<') { found_tag = true; } - else if(found_tag && 0 == memcmp(&xml[i], property, property_len) ) + else if(found_tag && 0 == memcmp(&xml[i], property, property_len)) { *content = &xml[i+property_len+2]; i += property_len+2; @@ -214,7 +214,8 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) (const char **)&content_out, &service_name_len); - memcpy(name_type_buffer, content_out, service_name_len); + if (found) + memcpy(name_type_buffer, content_out, service_name_len); found &= find_tag_property( xml, strlen(xml), @@ -222,8 +223,8 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) "request_type", (const char **)&content_out, &request_type_name_len); - - memcpy(&name_type_buffer[service_name_len], content_out, service_name_len); + if (found) + memcpy(&name_type_buffer[service_name_len], content_out, service_name_len); found &= find_tag_property( xml, strlen(xml), @@ -232,11 +233,15 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) (const char **)&content_out, &reply_type_name_len); - memcpy(&name_type_buffer[service_name_len+request_type_name_len], content_out, service_name_len); - - name_type_buffer[service_name_len+request_type_name_len+reply_type_name_len] = '\0'; + if (found){ + memcpy(&name_type_buffer[service_name_len+request_type_name_len], content_out, service_name_len); + name_type_buffer[service_name_len+request_type_name_len+reply_type_name_len] = '\0'; + } + if (found) + found &= add_brokerless_entity_hash(name_type_buffer, id); found &= add_brokerless_entity_hash(name_type_buffer, id); + found &= add_brokerless_entity_hash(name_type_buffer, id); } return found; @@ -249,7 +254,8 @@ bool add_brokerless_entity_hash(const char* ref, uxrObjectId id) { hash_brokerless((unsigned char*) ref, brokerlessEntityMap.queue[brokerlessEntityMap.index].hash); - brokerlessEntityMap.queue[brokerlessMessageQueue.index].id = id; + brokerlessEntityMap.queue[brokerlessEntityMap.index].id.id = id.id; + brokerlessEntityMap.queue[brokerlessEntityMap.index].id.type = id.type; if (id.type == UXR_DATAREADER_ID){ brokerlessEntityMap.datareaders++; @@ -294,6 +300,19 @@ int32_t find_brokerless_hash_from_hash(char* hash) return -1; } +int32_t find_brokerless_hash_from_hash_only_reader(char* hash) +{ + for (size_t i = 0; i < brokerlessEntityMap.index; i++) + { + if (0 == memcmp((void*) hash, (void*) brokerlessEntityMap.queue[i].hash, BROKERLESS_HASH_SIZE) && + brokerlessEntityMap.queue[i].id.type != UXR_DATAWRITER_ID) + { + return (int32_t) i; + } + } + return -1; +} + bool check_brokerless_sample_id(SampleIdentity sample_id) { // TODO (pablogs9): Check if requester id stored in the sample_id still exists @@ -362,7 +381,7 @@ bool listen_brokerless(uxrSession* session, int timeout) char hash[BROKERLESS_HASH_SIZE]; ucdr_deserialize_array_char(&reader, hash, BROKERLESS_HASH_SIZE); - int32_t hash_index = find_brokerless_hash_from_hash(hash); + int32_t hash_index = find_brokerless_hash_from_hash_only_reader(hash); if (-1 != hash_index && brokerlessEntityMap.queue[hash_index].id.type != UXR_DATAWRITER_ID) { From 6d7a7b297f613ea2776c8475fed07ab5624ecaa3 Mon Sep 17 00:00:00 2001 From: Jose Antonio Moral Date: Wed, 9 Sep 2020 11:19:11 +0200 Subject: [PATCH 18/25] Code styling, minor improvements/fixes --- CMakeLists.txt | 12 +- examples/BrokerlessPublisher/CMakeLists.txt | 4 +- examples/BrokerlessSubscriber/CMakeLists.txt | 4 +- include/uxr/client/config.h.in | 2 +- .../client/core/session/stream/stream_id.h | 2 +- src/c/brokerless/brokerless.c | 248 ++++++++++-------- src/c/brokerless/brokerless_internal.h | 16 +- .../udp_transport_broadcast_posix.c | 12 +- src/c/core/session/create_entities_ref.c | 8 +- src/c/core/session/create_entities_xml.c | 8 +- src/c/core/session/session.c | 8 +- src/c/core/session/stream/stream_id.c | 2 +- src/c/core/session/write_access.c | 9 +- 13 files changed, 185 insertions(+), 150 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f67a684a0..d3bbf8d1e 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,11 @@ 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_BROKERLESS_ENABLE "Enable brokerless transport (experimental)." ON) +option(UCLIENT_PROFILE_BROKERLESS "Enable brokerless transport (experimental)." ON) +if(NOT UCLIENT_PROFILE_UDP) + set(UCLIENT_PROFILE_BROKERLESS OFF) +endif() + set(UCLIENT_BROKERLESS_PORT 9999 CACHE STRING "Brokerless UDP port (experimental)") set(UCLIENT_BROKERLESS_ENTITY_MAP_LEN 10 CACHE STRING "Brokerless entity map length port (experimental)") set(UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN 100 CACHE STRING "Brokerless message queue length (experimental)") @@ -234,8 +238,8 @@ set(SRCS src/c/core/session/create_entities_xml.c src/c/core/session/read_access.c src/c/core/session/write_access.c - $<$:src/c/brokerless/brokerless.c> - $<$:src/c/brokerless/udp_transport_broadcast_posix.c> + $<$:src/c/brokerless/brokerless.c> + $<$:src/c/brokerless/udp_transport_broadcast_posix.c> $<$,$>:src/c/core/log/log.c> ${_transport_src} ) @@ -356,7 +360,7 @@ if(UCLIENT_BUILD_EXAMPLES) add_subdirectory(examples/SubscribeHelloWorldP2P) endif() -if(UCLIENT_BUILD_EXAMPLES AND UCLIENT_BROKERLESS_ENABLE) +if(UCLIENT_BUILD_EXAMPLES AND UCLIENT_PROFILE_BROKERLESS) add_subdirectory(examples/BrokerlessPublisher) add_subdirectory(examples/BrokerlessSubscriber) endif() diff --git a/examples/BrokerlessPublisher/CMakeLists.txt b/examples/BrokerlessPublisher/CMakeLists.txt index 1dd2d00c1..7c171fcf8 100644 --- a/examples/BrokerlessPublisher/CMakeLists.txt +++ b/examples/BrokerlessPublisher/CMakeLists.txt @@ -23,8 +23,8 @@ if(NOT UCLIENT_BUILD_EXAMPLES) find_package(microxrcedds_client REQUIRED) endif() -if(NOT UCLIENT_PROFILE_UDP) - message(WARNING "Can not compile example: The UCLIENT_PROFILE_UDP must be enabled.") +if(NOT UCLIENT_PROFILE_UDP OR NOT UCLIENT_PROFILE_BROKERLESS) + message(WARNING "Can not compile example: The UCLIENT_PROFILE_UDP and UCLIENT_PROFILE_BROKERLESS must be enabled.") else() add_executable(${PROJECT_NAME} main.c) if(MSVC OR MSVC_IDE) diff --git a/examples/BrokerlessSubscriber/CMakeLists.txt b/examples/BrokerlessSubscriber/CMakeLists.txt index 37f73b846..be98dd345 100644 --- a/examples/BrokerlessSubscriber/CMakeLists.txt +++ b/examples/BrokerlessSubscriber/CMakeLists.txt @@ -23,8 +23,8 @@ if(NOT UCLIENT_BUILD_EXAMPLES) find_package(microxrcedds_client REQUIRED) endif() -if(NOT UCLIENT_PROFILE_UDP) - message(WARNING "Can not compile example: The UCLIENT_PROFILE_UDP must be enabled.") +if(NOT UCLIENT_PROFILE_UDP OR NOT UCLIENT_PROFILE_BROKERLESS) + message(WARNING "Can not compile example: The UCLIENT_PROFILE_UDP and UCLIENT_PROFILE_BROKERLESS must be enabled.") else() add_executable(${PROJECT_NAME} main.c) if(MSVC OR MSVC_IDE) diff --git a/include/uxr/client/config.h.in b/include/uxr/client/config.h.in index 45a214de2..a64253651 100644 --- a/include/uxr/client/config.h.in +++ b/include/uxr/client/config.h.in @@ -25,6 +25,7 @@ #cmakedefine UCLIENT_PROFILE_UDP #cmakedefine UCLIENT_PROFILE_TCP #cmakedefine UCLIENT_PROFILE_SERIAL +#cmakedefine UCLIENT_PROFILE_BROKERLESS #cmakedefine UCLIENT_PLATFORM_POSIX #cmakedefine UCLIENT_PLATFORM_POSIX_NOPOLL @@ -54,7 +55,6 @@ #define UXR_CONFIG_SERIAL_TRANSPORT_MTU @UCLIENT_SERIAL_TRANSPORT_MTU@ #endif -#cmakedefine UCLIENT_BROKERLESS_ENABLE #define UCLIENT_BROKERLESS_PORT @UCLIENT_BROKERLESS_PORT@ #define UCLIENT_BROKERLESS_ENTITY_MAP_LEN @UCLIENT_BROKERLESS_ENTITY_MAP_LEN@ #define UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN @UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN@ diff --git a/include/uxr/client/core/session/stream/stream_id.h b/include/uxr/client/core/session/stream/stream_id.h index b7933a8dd..ef4c651cf 100644 --- a/include/uxr/client/core/session/stream/stream_id.h +++ b/include/uxr/client/core/session/stream/stream_id.h @@ -46,7 +46,7 @@ typedef enum uxrStreamType /** Identifies a reliable stream. */ UXR_RELIABLE_STREAM, /** Identifies a brokerless stream. */ - UXR_BROKERLESS + UXR_BROKERLESS_STREAM } uxrStreamType; diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 3ed59e7a4..52f74d3f8 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -50,14 +50,17 @@ static uint8_t brokerlessBuffer[UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN]; void hash_brokerless(unsigned char *str, char* hash) { hash_int_t int_hash = 5381; - int c; + int c; while ((c = *str++)) + { int_hash = ((int_hash << 5) + int_hash) + (hash_int_t)c; /* hash * 33 + c */ + } - for (size_t i = 0; i < BROKERLESS_HASH_SIZE; i++){ - hash[i] = ((char*)&int_hash)[i]; - } + for (size_t i = 0; i < BROKERLESS_HASH_SIZE; i++) + { + hash[i] = ((char*)&int_hash)[i]; + } } // Find first occurrence of tag in XML @@ -72,7 +75,9 @@ bool find_tag_xml(const char * xml, size_t len, char * tag, const char ** conten { size_t tag_opener_len = 0; while(xml[i+tag_opener_len] != '>') + { tag_opener_len++; + } *content = &xml[i+tag_opener_len+1]; found_begin = true; } @@ -107,7 +112,9 @@ bool find_tag_property(const char * xml, size_t len, char * tag, char * property i += property_len+2; *content_len = 0; while(xml[i + (*content_len)] != '"') + { *content_len += 1; + } found_property = true; break; } @@ -135,7 +142,7 @@ void init_brokerless(uint32_t key) } bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id) -{ +{ SampleIdentity sample_id = {0}; return add_brokerless_message_with_sample_id(ub, lenght, id, sample_id); } @@ -153,7 +160,7 @@ bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, size_t lenght, uxrObj return true; } - + return false; } @@ -162,86 +169,100 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) bool found = true; char name_type_buffer[100]; - if (id.type == UXR_DATAWRITER_ID || id.type == UXR_DATAREADER_ID) + switch (id.type) { - char xml_strings[3][12] = { "dds", - "data_writer", - "topic" - }; - if (id.type == UXR_DATAREADER_ID){ - memcpy(xml_strings[1], "data_reader\0", 12); - } - - const char * content_in = xml; - char * content_out; - size_t content_len_in = strlen(content_in); - size_t content_len_out; - - for (size_t i = 0; i < 3; i++) - { - if(find_tag_xml(content_in, content_len_in, xml_strings[i], (const char **)&content_out, &content_len_out)){ - content_in = content_out; - content_len_in = content_len_out; - } else { - return false; + case UXR_DATAREADER_ID: + case UXR_DATAWRITER_ID: + { + const char * data_reader_or_writer = (id.type == UXR_DATAREADER_ID) ? "data_reader\0" : "data_writer\0"; + char xml_strings[3][12] = + { + "dds", + "", + "topic" + }; + memmove(xml_strings[1], data_reader_or_writer, 12); + + const char * content_in = xml; + char * content_out; + size_t content_len_in = strlen(content_in); + size_t content_len_out; + + for (size_t i = 0; i < 3; i++) + { + if(find_tag_xml(content_in, content_len_in, xml_strings[i], (const char **)&content_out, &content_len_out)) + { + content_in = content_out; + content_len_in = content_len_out; + } + else + { + return false; + } } - } - - size_t topic_name_len; - size_t type_name_len; - found &= find_tag_xml(content_in, content_len_in, "name", (const char **)&content_out, &topic_name_len); - memcpy(name_type_buffer, content_out, topic_name_len); + size_t topic_name_len; + size_t type_name_len; - found &= find_tag_xml(content_in, content_len_in, "dataType", (const char **)&content_out, &type_name_len); - memcpy(&name_type_buffer[topic_name_len], content_out, type_name_len); + found &= find_tag_xml(content_in, content_len_in, "name", (const char **)&content_out, &topic_name_len); + memcpy(name_type_buffer, content_out, topic_name_len); - name_type_buffer[topic_name_len+type_name_len] = '\0'; + found &= find_tag_xml(content_in, content_len_in, "dataType", (const char **)&content_out, &type_name_len); + memcpy(&name_type_buffer[topic_name_len], content_out, type_name_len); - found &= add_brokerless_entity_hash(name_type_buffer, id); - } - else if (id.type == UXR_REQUESTER_ID || id.type == UXR_REPLIER_ID) - { - char * content_out; - size_t service_name_len; - size_t request_type_name_len; - size_t reply_type_name_len; + name_type_buffer[topic_name_len+type_name_len] = '\0'; - found &= find_tag_property( xml, - strlen(xml), - (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", - "service_name", - (const char **)&content_out, - &service_name_len); - - if (found) - memcpy(name_type_buffer, content_out, service_name_len); - - found &= find_tag_property( xml, - strlen(xml), - (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", - "request_type", - (const char **)&content_out, - &request_type_name_len); - if (found) - memcpy(&name_type_buffer[service_name_len], content_out, service_name_len); - - found &= find_tag_property( xml, - strlen(xml), - (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", - "reply_type", - (const char **)&content_out, - &reply_type_name_len); - - if (found){ - memcpy(&name_type_buffer[service_name_len+request_type_name_len], content_out, service_name_len); - name_type_buffer[service_name_len+request_type_name_len+reply_type_name_len] = '\0'; + found &= add_brokerless_entity_hash(name_type_buffer, id); + break; } + case UXR_REQUESTER_ID: + case UXR_REPLIER_ID: + { + char * content_out; + size_t service_name_len; + size_t request_type_name_len; + size_t reply_type_name_len; + + found &= find_tag_property(xml, + strlen(xml), + (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", + "service_name", + (const char **)&content_out, + &service_name_len); + if (found) + { + memcpy(name_type_buffer, content_out, service_name_len); + } + + found &= find_tag_property(xml, + strlen(xml), + (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", + "request_type", + (const char **)&content_out, + &request_type_name_len); + if (found) + { + memcpy(&name_type_buffer[service_name_len], content_out, service_name_len); + } + + found &= find_tag_property(xml, + strlen(xml), + (id.type == UXR_REQUESTER_ID) ? "requester" : "replier", + "reply_type", + (const char **)&content_out, + &reply_type_name_len); + if (found) + { + memcpy(&name_type_buffer[service_name_len+request_type_name_len], content_out, service_name_len); + name_type_buffer[service_name_len+request_type_name_len+reply_type_name_len] = '\0'; + } - if (found) - found &= add_brokerless_entity_hash(name_type_buffer, id); - found &= add_brokerless_entity_hash(name_type_buffer, id); - found &= add_brokerless_entity_hash(name_type_buffer, id); + if (found) + { + found &= add_brokerless_entity_hash(name_type_buffer, id); + } + break; + } } return found; @@ -251,27 +272,39 @@ bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id) bool add_brokerless_entity_hash(const char* ref, uxrObjectId id) { if (brokerlessEntityMap.index < UCLIENT_BROKERLESS_ENTITY_MAP_LEN - 1) - { + { hash_brokerless((unsigned char*) ref, brokerlessEntityMap.queue[brokerlessEntityMap.index].hash); brokerlessEntityMap.queue[brokerlessEntityMap.index].id.id = id.id; brokerlessEntityMap.queue[brokerlessEntityMap.index].id.type = id.type; - - if (id.type == UXR_DATAREADER_ID){ - brokerlessEntityMap.datareaders++; - }else if (id.type == UXR_DATAWRITER_ID){ - brokerlessEntityMap.datawriters++; - }else if (id.type == UXR_REQUESTER_ID){ - brokerlessEntityMap.requesters++; - }else if (id.type == UXR_REPLIER_ID){ - brokerlessEntityMap.repliers++; + + switch (id.type) + { + case UXR_DATAREADER_ID: + { + brokerlessEntityMap.datareaders++; + break; + } + case UXR_DATAWRITER_ID: + { + brokerlessEntityMap.datawriters++; + break; + } + case UXR_REQUESTER_ID: + { + brokerlessEntityMap.requesters++; + break; + } + case UXR_REPLIER_ID: + { + brokerlessEntityMap.repliers++; + break; + } } - brokerlessEntityMap.index++; - return true; } - + return false; } @@ -291,7 +324,7 @@ int32_t find_brokerless_hash_from_id(uxrObjectId id) int32_t find_brokerless_hash_from_hash(char* hash) { for (size_t i = 0; i < brokerlessEntityMap.index; i++) - { + { if (0 == memcmp((void*) hash, (void*) brokerlessEntityMap.queue[i].hash, BROKERLESS_HASH_SIZE)) { return (int32_t) i; @@ -303,8 +336,8 @@ int32_t find_brokerless_hash_from_hash(char* hash) int32_t find_brokerless_hash_from_hash_only_reader(char* hash) { for (size_t i = 0; i < brokerlessEntityMap.index; i++) - { - if (0 == memcmp((void*) hash, (void*) brokerlessEntityMap.queue[i].hash, BROKERLESS_HASH_SIZE) && + { + if (0 == memcmp((void*) hash, (void*) brokerlessEntityMap.queue[i].hash, BROKERLESS_HASH_SIZE) && brokerlessEntityMap.queue[i].id.type != UXR_DATAWRITER_ID) { return (int32_t) i; @@ -316,7 +349,7 @@ int32_t find_brokerless_hash_from_hash_only_reader(char* hash) bool check_brokerless_sample_id(SampleIdentity sample_id) { // TODO (pablogs9): Check if requester id stored in the sample_id still exists - + return !memcmp(&sample_id.writer_guid.entityId.entityKey, (uint8_t*)(&client_key), 3) && !memcmp(&sample_id.writer_guid.entityId.entityKind, (uint8_t*)(&client_key) + 3, 1); } @@ -332,18 +365,19 @@ void fill_brokerless_sample_id(SampleIdentity* sample_id, uxrObjectId id) } bool flush_brokerless_queues() -{ +{ for (size_t i = 0; i < brokerlessMessageQueue.index; i++) { int32_t hash_index = find_brokerless_hash_from_id(brokerlessMessageQueue.queue[i].id); - + if (-1 != hash_index) { ucdrBuffer writer; ucdr_init_buffer(&writer, brokerlessBuffer, UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN); ucdr_serialize_array_char(&writer, brokerlessEntityMap.queue[hash_index].hash, BROKERLESS_HASH_SIZE); - if (brokerlessMessageQueue.queue[i].id.type == UXR_REQUESTER_ID || brokerlessMessageQueue.queue[i].id.type == UXR_REPLIER_ID){ + if (brokerlessMessageQueue.queue[i].id.type == UXR_REQUESTER_ID || brokerlessMessageQueue.queue[i].id.type == UXR_REPLIER_ID) + { ucdr_serialize_bool(&writer, brokerlessMessageQueue.queue[i].id.type == UXR_REQUESTER_ID); @@ -351,7 +385,7 @@ bool flush_brokerless_queues() { fill_brokerless_sample_id(&brokerlessMessageQueue.queue[i].sample_id, brokerlessMessageQueue.queue[i].id); } - + uxr_serialize_SampleIdentity(&writer, &brokerlessMessageQueue.queue[i].sample_id); } @@ -362,19 +396,19 @@ bool flush_brokerless_queues() } brokerlessMessageQueue.index = 0; - return false; } bool listen_brokerless(uxrSession* session, int timeout) { size_t readed_bytes = 0; - if (brokerlessEntityMap.datareaders || brokerlessEntityMap.requesters || brokerlessEntityMap.repliers){ + if (brokerlessEntityMap.datareaders || brokerlessEntityMap.requesters || brokerlessEntityMap.repliers) + { readed_bytes = brokerless_broadcast_recv(brokerlessBuffer, UCLIENT_BROKERLESS_INTERNAL_BUFFER_LEN, timeout); } - if(0 != readed_bytes){ - + if(0 != readed_bytes) + { ucdrBuffer reader; ucdr_init_buffer(&reader, brokerlessBuffer, readed_bytes); @@ -384,13 +418,13 @@ bool listen_brokerless(uxrSession* session, int timeout) int32_t hash_index = find_brokerless_hash_from_hash_only_reader(hash); if (-1 != hash_index && brokerlessEntityMap.queue[hash_index].id.type != UXR_DATAWRITER_ID) - { + { uxrObjectId * object_id = &brokerlessEntityMap.queue[hash_index].id; // TODO (pablogs9): request_id is related to the uxr_buffer_request_data request, so it can determine some limitations imposed into the communication -> NOT IMPLEMENTED BY NOW if (object_id->type == UXR_DATAREADER_ID) { - uxrStreamId stream = {0, 0, UXR_BROKERLESS, UXR_INPUT_STREAM}; + uxrStreamId stream = {0, 0, UXR_BROKERLESS_STREAM, UXR_INPUT_STREAM}; uint32_t length; ucdr_deserialize_uint32_t(&reader, &length); session->on_data_flag = true; @@ -405,10 +439,9 @@ bool listen_brokerless(uxrSession* session, int timeout) ucdr_deserialize_bool(&reader, &is_from_requester); // sample_id deserialization is done inside conditional in order to not deserialize when message should be dropped - if (is_from_requester && object_id->type == UXR_REPLIER_ID) - { - uxr_deserialize_SampleIdentity(&reader, &sample_id); + { + uxr_deserialize_SampleIdentity(&reader, &sample_id); ucdr_deserialize_uint32_t(&reader, &length); session->on_data_flag = true; session->on_request(session, *object_id, 0, &sample_id, &reader, (uint16_t)length, session->on_request_args); @@ -423,7 +456,6 @@ bool listen_brokerless(uxrSession* session, int timeout) session->on_reply(session, *object_id, 0, (uint16_t)sample_id.sequence_number.low, &reader, (uint16_t)length, session->on_reply_args); } } - } return true; } diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h index 0fb45bcef..367cce9df 100644 --- a/src/c/brokerless/brokerless_internal.h +++ b/src/c/brokerless/brokerless_internal.h @@ -28,32 +28,36 @@ extern "C" #include #include -typedef uint32_t hash_int_t; +typedef uint32_t hash_int_t; #define BROKERLESS_HASH_SIZE sizeof(hash_int_t) // Outcomming message queue -typedef struct { +typedef struct +{ uint8_t *data; size_t lenght; uxrObjectId id; SampleIdentity sample_id; } brokerlessMessage_t; -typedef struct { +typedef struct +{ brokerlessMessage_t queue[UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN]; size_t index; } brokerlessMessageQueue_t; // Entities map -typedef struct { +typedef struct +{ char hash[BROKERLESS_HASH_SIZE]; uxrObjectId id; } brokerlessEntityHash_t; -typedef struct { +typedef struct +{ brokerlessEntityHash_t queue[UCLIENT_BROKERLESS_ENTITY_MAP_LEN]; size_t index; uint8_t datawriters; @@ -62,7 +66,7 @@ typedef struct { uint8_t repliers; } brokerlessEntityMap_t; -// Internal API +// Internal API (TODO: add documentation) void init_brokerless(uint32_t key); bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id); diff --git a/src/c/brokerless/udp_transport_broadcast_posix.c b/src/c/brokerless/udp_transport_broadcast_posix.c index 896b248a0..0e363c8c4 100644 --- a/src/c/brokerless/udp_transport_broadcast_posix.c +++ b/src/c/brokerless/udp_transport_broadcast_posix.c @@ -52,14 +52,10 @@ size_t brokerless_broadcast_send( size_t len) { size_t rv = 0; - + ssize_t bytes_sent = sendto(fd_send, buf, len, 0, (struct sockaddr*) &send_addr, sizeof(send_addr)); - if (0 > bytes_sent) { - rv = 0; - } else { - rv = (size_t)bytes_sent; - } + rv = (0 > bytes_sent) ? 0 : (size_t)bytes_sent; return rv; } @@ -67,8 +63,7 @@ size_t brokerless_broadcast_recv( uint8_t* buf, size_t len, int timeout) -{ - +{ timeout = (timeout <= 0) ? 1 : timeout; struct timeval tv; @@ -81,6 +76,7 @@ size_t brokerless_broadcast_recv( uint fromlen; fromlen = sizeof(from); + // TODO: what if received packages are not full? ssize_t readed_bytes = recvfrom(fd_recv, (void*)buf, len, 0, (struct sockaddr * restrict)&from, (socklen_t * restrict)&fromlen); return (readed_bytes > 0) ? (size_t)readed_bytes : 0; diff --git a/src/c/core/session/create_entities_ref.c b/src/c/core/session/create_entities_ref.c index 949e88dac..4307d9d71 100644 --- a/src/c/core/session/create_entities_ref.c +++ b/src/c/core/session/create_entities_ref.c @@ -44,7 +44,7 @@ uint16_t uxr_buffer_create_datawriter_ref(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER; uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_entity_hash(ref, object_id); #endif @@ -59,7 +59,7 @@ uint16_t uxr_buffer_create_datareader_ref(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAREADER; uxr_object_id_to_raw(subscriber_id, payload.object_representation._.data_reader.subscriber_id.data); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_entity_hash(ref, object_id); #endif @@ -78,7 +78,7 @@ uint16_t uxr_buffer_create_requester_ref( payload.object_representation.kind = DDS_XRCE_OBJK_REQUESTER; uxr_object_id_to_raw(participant_id, payload.object_representation._.requester.participant_id.data); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_entity_hash(ref, object_id); #endif @@ -97,7 +97,7 @@ uint16_t uxr_buffer_create_replier_ref( payload.object_representation.kind = DDS_XRCE_OBJK_REPLIER; uxr_object_id_to_raw(participant_id, payload.object_representation._.replier.participant_id.data); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_entity_hash(ref, object_id); #endif diff --git a/src/c/core/session/create_entities_xml.c b/src/c/core/session/create_entities_xml.c index ef190bad0..0252434da 100644 --- a/src/c/core/session/create_entities_xml.c +++ b/src/c/core/session/create_entities_xml.c @@ -70,7 +70,7 @@ uint16_t uxr_buffer_create_datawriter_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAWRITER; uxr_object_id_to_raw(publisher_id, payload.object_representation._.data_writer.publisher_id.data); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_entity_hash_from_xml(xml, object_id); #endif @@ -86,7 +86,7 @@ uint16_t uxr_buffer_create_datareader_xml(uxrSession* session, uxrStreamId strea payload.object_representation.kind = DDS_XRCE_OBJK_DATAREADER; uxr_object_id_to_raw(subscriber_id, payload.object_representation._.data_reader.subscriber_id.data); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_entity_hash_from_xml(xml, object_id); #endif @@ -105,7 +105,7 @@ uint16_t uxr_buffer_create_requester_xml( payload.object_representation.kind = DDS_XRCE_OBJK_REQUESTER; uxr_object_id_to_raw(participant_id, payload.object_representation._.requester.participant_id.data); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_entity_hash_from_xml(xml, object_id); #endif @@ -124,7 +124,7 @@ uint16_t uxr_buffer_create_replier_xml( payload.object_representation.kind = DDS_XRCE_OBJK_REPLIER; uxr_object_id_to_raw(participant_id, payload.object_representation._.replier.participant_id.data); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_entity_hash_from_xml(xml, object_id); #endif diff --git a/src/c/core/session/session.c b/src/c/core/session/session.c index 6961405db..e382c5ef4 100644 --- a/src/c/core/session/session.c +++ b/src/c/core/session/session.c @@ -83,8 +83,8 @@ void uxr_init_session(uxrSession* session, uxrCommunication* comm, uint32_t key) uxr_init_session_info(&session->info, 0x81, key); uxr_init_stream_storage(&session->streams); -#ifdef UCLIENT_BROKERLESS_ENABLE - init_brokerless(key); +#ifdef UCLIENT_PROFILE_BROKERLESS + init_brokerless(key); // TODO: should it be desirable to give the user an uxr_init_brokerless_transport() method? #endif } @@ -376,7 +376,7 @@ bool uxr_buffer_performance(uxrSession *session, void uxr_flash_output_streams(uxrSession* session) { -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS flush_brokerless_queues(); #endif @@ -421,7 +421,7 @@ bool listen_message(uxrSession* session, int poll_ms) read_message(session, &ub); } -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS listen_brokerless(session, poll_ms); #endif diff --git a/src/c/core/session/stream/stream_id.c b/src/c/core/session/stream/stream_id.c index 0f7529587..cfcb7bd9c 100644 --- a/src/c/core/session/stream/stream_id.c +++ b/src/c/core/session/stream/stream_id.c @@ -20,7 +20,7 @@ uxrStreamId uxr_stream_id(uint8_t index, uxrStreamType type, uxrStreamDirection case UXR_NONE_STREAM: stream_id.raw = 0; break; - case UXR_BROKERLESS: + case UXR_BROKERLESS_STREAM: case UXR_BEST_EFFORT_STREAM: stream_id.raw = (uint8_t)(index + BEST_EFFORT_STREAM_THRESHOLD); break; diff --git a/src/c/core/session/write_access.c b/src/c/core/session/write_access.c index 069196951..c8b61a550 100644 --- a/src/c/core/session/write_access.c +++ b/src/c/core/session/write_access.c @@ -29,13 +29,12 @@ uint16_t uxr_buffer_request( WRITE_DATA_Payload_Data payload; rv = uxr_init_base_object_request(&session->info, requester_id, &payload.base); uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload); - -#ifdef UCLIENT_BROKERLESS_ENABLE + +#ifdef UCLIENT_PROFILE_BROKERLESS SampleIdentity sample_id; sample_id.sequence_number.low = rv; add_brokerless_message_with_sample_id(&ub, len, requester_id, sample_id); #endif - ucdr_serialize_array_uint8_t(&ub, buffer, len); } @@ -62,7 +61,7 @@ uint16_t uxr_buffer_reply( uxr_serialize_WRITE_DATA_Payload_Data(&ub, &payload); uxr_serialize_SampleIdentity(&ub, sample_id); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_message_with_sample_id(&ub, len, replier_id, *sample_id); #endif @@ -88,7 +87,7 @@ bool uxr_prepare_output_stream(uxrSession* session, uxrStreamId stream_id, uxrOb ucdr_init_buffer(ub, ub->iterator, (size_t)(ub->final - ub->iterator)); ucdr_set_on_full_buffer_callback(ub, on_full_buffer, args); -#ifdef UCLIENT_BROKERLESS_ENABLE +#ifdef UCLIENT_PROFILE_BROKERLESS add_brokerless_message(ub, topic_size, datawriter_id); #endif } From 31976038e0dedd288ab7a47c5fb19be0fb65de73 Mon Sep 17 00:00:00 2001 From: Jose Antonio Moral Date: Wed, 9 Sep 2020 11:24:36 +0200 Subject: [PATCH 19/25] Fix some typos --- src/c/brokerless/brokerless.c | 10 +++++----- src/c/brokerless/brokerless_internal.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 52f74d3f8..046595dc4 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -141,18 +141,18 @@ void init_brokerless(uint32_t key) brokerless_init_transport(); } -bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id) +bool add_brokerless_message(ucdrBuffer* ub, uint32_t length, uxrObjectId id) { SampleIdentity sample_id = {0}; - return add_brokerless_message_with_sample_id(ub, lenght, id, sample_id); + return add_brokerless_message_with_sample_id(ub, length, id, sample_id); } -bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, size_t lenght, uxrObjectId id, SampleIdentity sample_id) +bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, size_t length, uxrObjectId id, SampleIdentity sample_id) { if (brokerlessMessageQueue.index < UCLIENT_BROKERLESS_MESSAGE_QUEUE_LEN - 1) { brokerlessMessageQueue.queue[brokerlessMessageQueue.index].data = ub->iterator; - brokerlessMessageQueue.queue[brokerlessMessageQueue.index].lenght = lenght; + brokerlessMessageQueue.queue[brokerlessMessageQueue.index].length = length; brokerlessMessageQueue.queue[brokerlessMessageQueue.index].id = id; brokerlessMessageQueue.queue[brokerlessMessageQueue.index].sample_id = sample_id; @@ -389,7 +389,7 @@ bool flush_brokerless_queues() uxr_serialize_SampleIdentity(&writer, &brokerlessMessageQueue.queue[i].sample_id); } - ucdr_serialize_sequence_char(&writer, (char*) brokerlessMessageQueue.queue[i].data, (uint32_t)brokerlessMessageQueue.queue[i].lenght); + ucdr_serialize_sequence_char(&writer, (char*) brokerlessMessageQueue.queue[i].data, (uint32_t)brokerlessMessageQueue.queue[i].length); brokerless_broadcast_send(writer.init, ucdr_buffer_length(&writer)); } diff --git a/src/c/brokerless/brokerless_internal.h b/src/c/brokerless/brokerless_internal.h index 367cce9df..fd42b1af4 100644 --- a/src/c/brokerless/brokerless_internal.h +++ b/src/c/brokerless/brokerless_internal.h @@ -36,7 +36,7 @@ typedef uint32_t hash_int_t; typedef struct { uint8_t *data; - size_t lenght; + size_t length; uxrObjectId id; SampleIdentity sample_id; } brokerlessMessage_t; @@ -69,8 +69,8 @@ typedef struct // Internal API (TODO: add documentation) void init_brokerless(uint32_t key); -bool add_brokerless_message(ucdrBuffer* ub, uint32_t lenght, uxrObjectId id); -bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, size_t lenght, uxrObjectId id, SampleIdentity sample_id); +bool add_brokerless_message(ucdrBuffer* ub, uint32_t length, uxrObjectId id); +bool add_brokerless_message_with_sample_id(ucdrBuffer* ub, size_t length, uxrObjectId id, SampleIdentity sample_id); bool add_brokerless_entity_hash_from_xml(const char* xml, uxrObjectId id); bool add_brokerless_entity_hash(const char* ref, uxrObjectId id); int32_t find_brokerless_hash_from_id(uxrObjectId id); From 65c8637068dfa557db2adb0953c2b6a601e2fa20 Mon Sep 17 00:00:00 2001 From: Jose Antonio Moral Date: Wed, 9 Sep 2020 11:29:21 +0200 Subject: [PATCH 20/25] Remove warnings --- include/uxr/client/brokerless/brokerless.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/include/uxr/client/brokerless/brokerless.h b/include/uxr/client/brokerless/brokerless.h index 0acc3f41d..b4a9bc595 100644 --- a/include/uxr/client/brokerless/brokerless.h +++ b/include/uxr/client/brokerless/brokerless.h @@ -22,15 +22,25 @@ extern "C" { #endif -bool brokerless_send_stub(void* instance, const uint8_t* buf, size_t len){ +bool brokerless_send_stub(void* instance, const uint8_t* buf, size_t len) +{ + (void)instance; + (void)buf; + (void)len; return true; } -bool brokerless_recv_stub(void* instance, uint8_t** buf, size_t* len, int timeout){ +bool brokerless_recv_stub(void* instance, uint8_t** buf, size_t* len, int timeout) +{ + (void)instance; + (void)buf; + (void)len; + (void)timeout; return false; } -uxrCommunication brokerless_comm_stub = { +uxrCommunication brokerless_comm_stub = +{ NULL, brokerless_send_stub, brokerless_recv_stub, From 9bc77e9ee6c5b6aa02544cc1f2a34bce9f7ea648 Mon Sep 17 00:00:00 2001 From: Jose Antonio Moral Date: Wed, 9 Sep 2020 15:42:04 +0200 Subject: [PATCH 21/25] Fix tests when using brokerless profile --- src/c/brokerless/brokerless.c | 2 +- src/c/brokerless/udp_transport_broadcast_posix.c | 2 +- test/unitary/session/Session.cpp | 3 +++ test/unitary/session/WriteReadAccess.cpp | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/c/brokerless/brokerless.c b/src/c/brokerless/brokerless.c index 046595dc4..e91d3aebc 100644 --- a/src/c/brokerless/brokerless.c +++ b/src/c/brokerless/brokerless.c @@ -93,7 +93,7 @@ bool find_tag_xml(const char * xml, size_t len, char * tag, const char ** conten } // Find property in first occurrence of tag in XML -bool find_tag_property(const char * xml, size_t len, char * tag, char * property, const char ** content, size_t * content_len) +bool find_tag_property(const char * xml, size_t len, const char * tag, char * property, const char ** content, size_t * content_len) { size_t tag_len = strlen(tag); size_t property_len = strlen(property); diff --git a/src/c/brokerless/udp_transport_broadcast_posix.c b/src/c/brokerless/udp_transport_broadcast_posix.c index 0e363c8c4..e09a2d94b 100644 --- a/src/c/brokerless/udp_transport_broadcast_posix.c +++ b/src/c/brokerless/udp_transport_broadcast_posix.c @@ -77,7 +77,7 @@ size_t brokerless_broadcast_recv( fromlen = sizeof(from); // TODO: what if received packages are not full? - ssize_t readed_bytes = recvfrom(fd_recv, (void*)buf, len, 0, (struct sockaddr * restrict)&from, (socklen_t * restrict)&fromlen); + ssize_t readed_bytes = recvfrom(fd_recv, (void*)buf, len, 0, (struct sockaddr *)(&from), (socklen_t *)(&fromlen)); return (readed_bytes > 0) ? (size_t)readed_bytes : 0; } diff --git a/test/unitary/session/Session.cpp b/test/unitary/session/Session.cpp index 0706a8a8b..cc05cea0f 100644 --- a/test/unitary/session/Session.cpp +++ b/test/unitary/session/Session.cpp @@ -23,6 +23,9 @@ extern "C" #include +#include +#include + #undef UXR_MESSAGE_LOG #undef UXR_SERIALIZATION_LOG #include diff --git a/test/unitary/session/WriteReadAccess.cpp b/test/unitary/session/WriteReadAccess.cpp index 8f543c668..49ff1dd22 100644 --- a/test/unitary/session/WriteReadAccess.cpp +++ b/test/unitary/session/WriteReadAccess.cpp @@ -20,6 +20,9 @@ extern "C" #include #include + +#include +#include } #include From 10da007727f15d76183ce28ec311b915d24f36ac Mon Sep 17 00:00:00 2001 From: Jose Antonio Moral Date: Wed, 9 Sep 2020 16:12:44 +0200 Subject: [PATCH 22/25] Disable brokerless P2P when on Windows platform --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d3bbf8d1e..aa096ef64 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,6 +216,10 @@ if(UCLIENT_PROFILE_DISCOVERY) endif() endif() +if(UCLIENT_PROFILE_BROKERLESS AND UCLIENT_PLATFORM_WINDOWS) + set(UCLIENT_PROFILE_BROKERLESS OFF) +endif() + # Other sources set(SRCS src/c/core/session/stream/input_best_effort_stream.c From a9db07a104436cfe515e0d05cb2e9bbbbb7dc916 Mon Sep 17 00:00:00 2001 From: Jose Antonio Moral Date: Thu, 10 Sep 2020 07:40:44 +0200 Subject: [PATCH 23/25] Add guard conditions to tests includes --- test/unitary/session/Session.cpp | 2 ++ test/unitary/session/WriteReadAccess.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/test/unitary/session/Session.cpp b/test/unitary/session/Session.cpp index cc05cea0f..f2dc77bb1 100644 --- a/test/unitary/session/Session.cpp +++ b/test/unitary/session/Session.cpp @@ -23,8 +23,10 @@ extern "C" #include +#ifdef UCLIENT_PROFILE_BROKERLESS #include #include +#endif // UCLIENT_PROFILE_BROKERLESS #undef UXR_MESSAGE_LOG #undef UXR_SERIALIZATION_LOG diff --git a/test/unitary/session/WriteReadAccess.cpp b/test/unitary/session/WriteReadAccess.cpp index 49ff1dd22..d2f08c48a 100644 --- a/test/unitary/session/WriteReadAccess.cpp +++ b/test/unitary/session/WriteReadAccess.cpp @@ -21,8 +21,10 @@ extern "C" #include +#ifdef UCLIENT_PROFILE_BROKERLESS #include #include +#endif // UCLIENT_PROFILE_BROKERLESS } #include From ff9b7a80b6525544f884a0869e94c004f9ac26e3 Mon Sep 17 00:00:00 2001 From: Jose Antonio Moral Date: Thu, 10 Sep 2020 10:35:07 +0200 Subject: [PATCH 24/25] Temporal fix for some warnings for windows tests --- examples/ReplyAdder/main.c | 2 +- examples/RequestAdder/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ReplyAdder/main.c b/examples/ReplyAdder/main.c index 67d251d6a..192407e58 100644 --- a/examples/ReplyAdder/main.c +++ b/examples/ReplyAdder/main.c @@ -139,7 +139,7 @@ int main(int args, char** argv) bool connected = true; while (1) { - uint8_t read_data_status; + // uint8_t read_data_status; // connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); connected = uxr_run_session_time(&session, 100); } diff --git a/examples/RequestAdder/main.c b/examples/RequestAdder/main.c index 1165c7f69..4614dc57a 100644 --- a/examples/RequestAdder/main.c +++ b/examples/RequestAdder/main.c @@ -60,7 +60,7 @@ int main(int args, char** argv) char* ip = argv[1]; char* port = argv[2]; - srand(time(NULL)); // Initialization, should only be called once. + srand((unsigned int)time(NULL)); // Initialization, should only be called once. uint32_t key = rand(); // Transport From 223d69b29cb08194ce30153fc516736dfb1b7e0d Mon Sep 17 00:00:00 2001 From: Jose Antonio Moral Date: Thu, 10 Sep 2020 10:58:13 +0200 Subject: [PATCH 25/25] Use proper sleep method for Window --- examples/PublishHelloWorld/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/PublishHelloWorld/main.c b/examples/PublishHelloWorld/main.c index 6aa33038c..e53b03771 100644 --- a/examples/PublishHelloWorld/main.c +++ b/examples/PublishHelloWorld/main.c @@ -20,7 +20,12 @@ #include //printf #include //strcmp #include //atoi + +#ifndef _WIN32 #include //sleep +#else +#include +#endif #define STREAM_HISTORY 8 #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY @@ -123,7 +128,12 @@ int main(int args, char** argv) printf("Send topic: %s, id: %i\n", topic.message, topic.index); connected = uxr_run_session_time(&session, 1000); + +#ifndef _WIN32 sleep(1); +#else + Sleep(1000); +#endif } // Delete resources