add support for running over ethernet without a configured IP stack
Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
1d8379b6c6
commit
3d16f5f2ce
36 changed files with 2612 additions and 1125 deletions
|
@ -15,6 +15,9 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src"
|
|||
ddsi_tcp.c
|
||||
ddsi_tran.c
|
||||
ddsi_udp.c
|
||||
ddsi_raweth.c
|
||||
ddsi_ipaddr.c
|
||||
ddsi_mcgroup.c
|
||||
q_addrset.c
|
||||
q_bitset_inlines.c
|
||||
q_bswap.c
|
||||
|
@ -45,6 +48,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src"
|
|||
q_thread_inlines.c
|
||||
q_time.c
|
||||
q_transmit.c
|
||||
q_inverse_uint32_set.c
|
||||
q_whc.c
|
||||
q_xevent.c
|
||||
q_xmsg.c
|
||||
|
@ -60,6 +64,9 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/ddsi"
|
|||
ddsi_tcp.h
|
||||
ddsi_tran.h
|
||||
ddsi_udp.h
|
||||
ddsi_raweth.h
|
||||
ddsi_ipaddr.h
|
||||
ddsi_mcgroup.h
|
||||
probes-constants.h
|
||||
q_addrset.h
|
||||
q_align.h
|
||||
|
@ -101,6 +108,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/ddsi"
|
|||
q_thread_template.h
|
||||
q_time.h
|
||||
q_transmit.h
|
||||
q_inverse_uint32_set.h
|
||||
q_unused.h
|
||||
q_whc.h
|
||||
q_xevent.h
|
||||
|
|
23
src/core/ddsi/include/ddsi/ddsi_ipaddr.h
Normal file
23
src/core/ddsi/include/ddsi/ddsi_ipaddr.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSI_IPADDR_H
|
||||
#define DDSI_IPADDR_H
|
||||
|
||||
#include "ddsi/ddsi_tran.h"
|
||||
|
||||
enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, const size_t ninterf, const struct nn_interface interf[]);
|
||||
enum ddsi_locator_from_string_result ddsi_ipaddr_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str, int32_t kind);
|
||||
char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port);
|
||||
void ddsi_ipaddr_to_loc (nn_locator_t *dst, const os_sockaddr_storage *src, int32_t kind);
|
||||
void ddsi_ipaddr_from_loc (os_sockaddr_storage *dst, const nn_locator_t *src);
|
||||
|
||||
#endif
|
26
src/core/ddsi/include/ddsi/ddsi_mcgroup.h
Normal file
26
src/core/ddsi/include/ddsi/ddsi_mcgroup.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSI_MCGROUP_H
|
||||
#define DDSI_MCGROUP_H
|
||||
|
||||
#include "ddsi/ddsi_tran.h"
|
||||
|
||||
struct nn_group_membership;
|
||||
|
||||
struct nn_group_membership *new_group_membership (void);
|
||||
void free_group_membership (struct nn_group_membership *mship);
|
||||
int ddsi_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip);
|
||||
int ddsi_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip);
|
||||
void ddsi_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t newconn);
|
||||
int ddsi_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn);
|
||||
|
||||
#endif
|
17
src/core/ddsi/include/ddsi/ddsi_raweth.h
Normal file
17
src/core/ddsi/include/ddsi/ddsi_raweth.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSI_RAWETH_H
|
||||
#define DDSI_RAWETH_H
|
||||
|
||||
int ddsi_raweth_init (void);
|
||||
|
||||
#endif
|
|
@ -36,8 +36,8 @@ typedef struct ddsi_tran_qos * ddsi_tran_qos_t;
|
|||
|
||||
/* Function pointer types */
|
||||
|
||||
typedef ssize_t (*ddsi_tran_read_fn_t) (ddsi_tran_conn_t , unsigned char *, size_t);
|
||||
typedef ssize_t (*ddsi_tran_write_fn_t) (ddsi_tran_conn_t, const struct msghdr *, size_t, uint32_t);
|
||||
typedef ssize_t (*ddsi_tran_read_fn_t) (ddsi_tran_conn_t, unsigned char *, size_t, nn_locator_t *);
|
||||
typedef ssize_t (*ddsi_tran_write_fn_t) (ddsi_tran_conn_t, const nn_locator_t *, size_t, const ddsi_iovec_t *, uint32_t);
|
||||
typedef int (*ddsi_tran_locator_fn_t) (ddsi_tran_base_t, nn_locator_t *);
|
||||
typedef bool (*ddsi_tran_supports_fn_t) (int32_t);
|
||||
typedef os_handle (*ddsi_tran_handle_fn_t) (ddsi_tran_base_t);
|
||||
|
@ -51,8 +51,31 @@ typedef void (*ddsi_tran_release_conn_fn_t) (ddsi_tran_conn_t);
|
|||
typedef void (*ddsi_tran_close_conn_fn_t) (ddsi_tran_conn_t);
|
||||
typedef void (*ddsi_tran_unblock_listener_fn_t) (ddsi_tran_listener_t);
|
||||
typedef void (*ddsi_tran_release_listener_fn_t) (ddsi_tran_listener_t);
|
||||
typedef int (*ddsi_tran_join_mc_fn_t) (ddsi_tran_conn_t, const nn_locator_t *srcip, const nn_locator_t *mcip);
|
||||
typedef int (*ddsi_tran_leave_mc_fn_t) (ddsi_tran_conn_t, const nn_locator_t *srcip, const nn_locator_t *mcip);
|
||||
typedef int (*ddsi_tran_join_mc_fn_t) (ddsi_tran_conn_t, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf);
|
||||
typedef int (*ddsi_tran_leave_mc_fn_t) (ddsi_tran_conn_t, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf);
|
||||
typedef int (*ddsi_is_mcaddr_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc);
|
||||
typedef int (*ddsi_is_ssm_mcaddr_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc);
|
||||
|
||||
enum ddsi_nearby_address_result {
|
||||
DNAR_DISTANT,
|
||||
DNAR_LOCAL,
|
||||
DNAR_SAME
|
||||
};
|
||||
|
||||
typedef enum ddsi_nearby_address_result (*ddsi_is_nearby_address_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]);
|
||||
|
||||
enum ddsi_locator_from_string_result {
|
||||
AFSR_OK, /* conversion succeeded */
|
||||
AFSR_INVALID, /* bogus input */
|
||||
AFSR_UNKNOWN, /* transport or hostname lookup failure */
|
||||
AFSR_MISMATCH /* recognised format, but mismatch with expected (e.g., IPv4/IPv6) */
|
||||
};
|
||||
|
||||
typedef enum ddsi_locator_from_string_result (*ddsi_locator_from_string_fn_t) (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str);
|
||||
|
||||
typedef char * (*ddsi_locator_to_string_fn_t) (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port);
|
||||
|
||||
typedef int (*ddsi_enumerate_interfaces_fn_t) (ddsi_tran_factory_t tran, int max, struct os_ifAttributes_s *interfs);
|
||||
|
||||
/* Data types */
|
||||
|
||||
|
@ -125,11 +148,18 @@ struct ddsi_tran_factory
|
|||
ddsi_tran_free_fn_t m_free_fn;
|
||||
ddsi_tran_join_mc_fn_t m_join_mc_fn;
|
||||
ddsi_tran_leave_mc_fn_t m_leave_mc_fn;
|
||||
ddsi_is_mcaddr_fn_t m_is_mcaddr_fn;
|
||||
ddsi_is_ssm_mcaddr_fn_t m_is_ssm_mcaddr_fn;
|
||||
ddsi_is_nearby_address_fn_t m_is_nearby_address_fn;
|
||||
ddsi_locator_from_string_fn_t m_locator_from_string_fn;
|
||||
ddsi_locator_to_string_fn_t m_locator_to_string_fn;
|
||||
ddsi_enumerate_interfaces_fn_t m_enumerate_interfaces_fn;
|
||||
|
||||
/* Data */
|
||||
|
||||
int32_t m_kind;
|
||||
const char * m_typename;
|
||||
const char * m_default_spdp_address;
|
||||
bool m_connless;
|
||||
bool m_stream;
|
||||
|
||||
|
@ -148,6 +178,8 @@ struct ddsi_tran_qos
|
|||
|
||||
/* Functions and pseudo functions (macro wrappers) */
|
||||
|
||||
void ddsi_factory_conn_init (ddsi_tran_factory_t, ddsi_tran_conn_t);
|
||||
|
||||
#define ddsi_tran_type(b) (((ddsi_tran_base_t) (b))->m_trantype)
|
||||
#define ddsi_tran_port(b) (((ddsi_tran_base_t) (b))->m_port)
|
||||
int ddsi_tran_locator (ddsi_tran_base_t base, nn_locator_t * loc);
|
||||
|
@ -169,18 +201,43 @@ void ddsi_tran_factories_fini (void);
|
|||
void ddsi_factory_add (ddsi_tran_factory_t factory);
|
||||
void ddsi_factory_free (ddsi_tran_factory_t factory);
|
||||
ddsi_tran_factory_t ddsi_factory_find (const char * type);
|
||||
ddsi_tran_factory_t ddsi_factory_find_supported_kind (int32_t kind);
|
||||
void ddsi_factory_conn_init (ddsi_tran_factory_t factory, ddsi_tran_conn_t conn);
|
||||
|
||||
#define ddsi_conn_handle(c) (ddsi_tran_handle (&(c)->m_base))
|
||||
#define ddsi_conn_locator(c,l) (ddsi_tran_locator (&(c)->m_base,(l)))
|
||||
OSAPI_EXPORT ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const struct msghdr * msg, size_t len, uint32_t flags);
|
||||
ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len);
|
||||
OSAPI_EXPORT ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const ddsi_iovec_t *iov, uint32_t flags);
|
||||
ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc);
|
||||
bool ddsi_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * loc);
|
||||
void ddsi_conn_add_ref (ddsi_tran_conn_t conn);
|
||||
void ddsi_conn_free (ddsi_tran_conn_t conn);
|
||||
|
||||
int ddsi_conn_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip);
|
||||
int ddsi_conn_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip);
|
||||
int ddsi_conn_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf);
|
||||
int ddsi_conn_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf);
|
||||
|
||||
void ddsi_conn_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t newconn);
|
||||
int ddsi_conn_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn);
|
||||
|
||||
int ddsi_is_mcaddr (const nn_locator_t *loc);
|
||||
int ddsi_is_ssm_mcaddr (const nn_locator_t *loc);
|
||||
enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, const size_t ninterf, const struct nn_interface interf[]);
|
||||
enum ddsi_locator_from_string_result ddsi_locator_from_string (nn_locator_t *loc, const char *str);
|
||||
|
||||
/* 8 for transport/
|
||||
1 for [
|
||||
48 for IPv6 hex digits (3*16) + separators
|
||||
2 for ]:
|
||||
10 for port (DDSI loc has signed 32-bit)
|
||||
1 for terminator
|
||||
--
|
||||
70
|
||||
*/
|
||||
#define DDSI_LOCSTRLEN 70
|
||||
|
||||
char *ddsi_locator_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc);
|
||||
char *ddsi_locator_to_string_no_port (char *dst, size_t sizeof_dst, const nn_locator_t *loc);
|
||||
|
||||
int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, int max, struct os_ifAttributes_s *interfs);
|
||||
|
||||
#define ddsi_listener_locator(s,l) (ddsi_tran_locator (&(s)->m_base,(l)))
|
||||
ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener);
|
||||
|
|
|
@ -70,14 +70,12 @@ void nn_log_addrset (logcat_t tf, const char *prefix, const struct addrset *as);
|
|||
trylock B fails */
|
||||
int addrset_eq_onesidederr (const struct addrset *a, const struct addrset *b);
|
||||
|
||||
int is_mcaddr (const nn_locator_t *loc);
|
||||
int is_unspec_locator (const nn_locator_t *loc);
|
||||
void set_unspec_locator (nn_locator_t *loc);
|
||||
|
||||
int add_addresses_to_addrset (struct addrset *as, const char *addrs, int port_mode, const char *msgtag, int req_mc);
|
||||
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
int is_ssm_mcaddr (const nn_locator_t *loc);
|
||||
int addrset_contains_ssm (const struct addrset *as);
|
||||
int addrset_any_ssm (const struct addrset *as, nn_locator_t *dst);
|
||||
int addrset_any_non_ssm_mc (const struct addrset *as, nn_locator_t *dst);
|
||||
|
|
|
@ -85,7 +85,7 @@ struct q_security_plugins
|
|||
q_securityDecoderSet (*new_decoder) (void);
|
||||
c_bool (*free_encoder) (q_securityEncoderSet);
|
||||
c_bool (*free_decoder) (q_securityDecoderSet);
|
||||
ssize_t (*send_encoded) (ddsi_tran_conn_t, struct msghdr *, q_securityEncoderSet *, uint32_t, uint32_t);
|
||||
ssize_t (*send_encoded) (ddsi_tran_conn_t, const nn_locator_t *dst, size_t niov, ddsi_iovec_t *iov, q_securityEncoderSet *, uint32_t, uint32_t);
|
||||
char * (*cipher_type) (q_cipherType);
|
||||
c_bool (*cipher_type_from_string) (const char *, q_cipherType *);
|
||||
uint32_t (*header_size) (q_securityEncoderSet, uint32_t);
|
||||
|
@ -196,6 +196,22 @@ struct prune_deleted_ppant {
|
|||
#define AMC_TRUE (AMC_SPDP | AMC_ASM)
|
||||
#endif
|
||||
|
||||
/* FIXME: this should be fully dynamic ... but this is easier for a quick hack */
|
||||
enum transport_selector {
|
||||
TRANS_DEFAULT, /* actually UDP, but this is so we can tell what has been set */
|
||||
TRANS_UDP,
|
||||
TRANS_UDP6,
|
||||
TRANS_TCP,
|
||||
TRANS_TCP6,
|
||||
TRANS_RAWETH
|
||||
};
|
||||
|
||||
enum many_sockets_mode {
|
||||
MSM_NO_UNICAST,
|
||||
MSM_SINGLE_UNICAST,
|
||||
MSM_MANY_UNICAST
|
||||
};
|
||||
|
||||
struct config
|
||||
{
|
||||
int valid;
|
||||
|
@ -213,7 +229,9 @@ struct config
|
|||
int tracingRelativeTimestamps;
|
||||
int tracingAppendToFile;
|
||||
unsigned allowMulticast;
|
||||
int useIpv6;
|
||||
enum transport_selector transport_selector;
|
||||
enum boolean_default compat_use_ipv6;
|
||||
enum boolean_default compat_tcp_enable;
|
||||
int dontRoute;
|
||||
int enableMulticastLoopback;
|
||||
int domainId;
|
||||
|
@ -259,14 +277,14 @@ struct config
|
|||
uint32_t fragment_size;
|
||||
|
||||
int publish_uc_locators; /* Publish discovery unicast locators */
|
||||
int enable_uc_locators; /* If false, don't even try to create a unicast socket */
|
||||
|
||||
/* TCP transport configuration */
|
||||
|
||||
int tcp_enable;
|
||||
int tcp_nodelay;
|
||||
int tcp_port;
|
||||
int64_t tcp_read_timeout;
|
||||
int64_t tcp_write_timeout;
|
||||
int tcp_use_peeraddr_for_unicast;
|
||||
|
||||
#ifdef DDSI_INCLUDE_SSL
|
||||
|
||||
|
@ -357,7 +375,7 @@ struct config
|
|||
/* compability options */
|
||||
enum nn_standards_conformance standards_conformance;
|
||||
int explicitly_publish_qos_set_to_default;
|
||||
int many_sockets_mode;
|
||||
enum many_sockets_mode many_sockets_mode;
|
||||
int arrival_of_data_asserts_pp_and_ep_liveliness;
|
||||
int acknack_numbits_emptyset;
|
||||
int respond_to_rti_init_zero_ack_with_invalid_heartbeat;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "ddsi/q_ephash.h"
|
||||
#include "ddsi/q_hbcontrol.h"
|
||||
#include "ddsi/q_feature_check.h"
|
||||
#include "ddsi/q_inverse_uint32_set.h"
|
||||
|
||||
#include "ddsi/ddsi_tran.h"
|
||||
|
||||
|
@ -145,6 +146,10 @@ struct local_reader_ary {
|
|||
struct reader **rdary; /* for efficient delivery, null-pointer terminated */
|
||||
};
|
||||
|
||||
struct avail_entityid_set {
|
||||
struct inverse_uint32_set x;
|
||||
};
|
||||
|
||||
struct participant
|
||||
{
|
||||
struct entity_common e;
|
||||
|
@ -157,7 +162,7 @@ struct participant
|
|||
struct xevent *pmd_update_xevent; /* timed event for periodically publishing ParticipantMessageData */
|
||||
nn_locator_t m_locator;
|
||||
ddsi_tran_conn_t m_conn;
|
||||
unsigned next_entityid; /* next available entity id [e.lock] */
|
||||
struct avail_entityid_set avail_entityids; /* available entity ids [e.lock] */
|
||||
os_mutex refc_lock;
|
||||
int32_t user_refc; /* number of non-built-in endpoints in this participant [refc_lock] */
|
||||
int32_t builtin_refc; /* number of built-in endpoints in this participant [refc_lock] */
|
||||
|
@ -390,6 +395,7 @@ int is_writer_entityid (nn_entityid_t id);
|
|||
int is_reader_entityid (nn_entityid_t id);
|
||||
|
||||
int pp_allocate_entityid (nn_entityid_t *id, unsigned kind, struct participant *pp);
|
||||
void pp_release_entityid(struct participant *pp, nn_entityid_t id);
|
||||
|
||||
/* Interface for glue code between the OpenSplice kernel and the DDSI
|
||||
entities. These all return 0 iff successful. All GIDs supplied
|
||||
|
@ -571,6 +577,9 @@ void delete_proxy_group (const struct nn_guid *guid, nn_wctime_t timestamp, int
|
|||
void writer_exit_startup_mode (struct writer *wr);
|
||||
uint64_t writer_instance_id (const struct nn_guid *guid);
|
||||
|
||||
/* Call this to empty all address sets of all writers to stop all outgoing traffic, or to
|
||||
rebuild them all (which only makes sense after previously having emptied them all). */
|
||||
void rebuild_or_clear_writer_addrsets(int rebuild);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ struct debug_monitor;
|
|||
struct tkmap;
|
||||
|
||||
typedef struct ospl_in_addr_node {
|
||||
os_sockaddr_storage addr;
|
||||
nn_locator_t loc;
|
||||
struct ospl_in_addr_node *next;
|
||||
} ospl_in_addr_node;
|
||||
|
||||
|
@ -160,10 +160,10 @@ struct q_globals {
|
|||
a NAT may be advertised), and the DDSI multi-cast address. */
|
||||
enum recvips_mode recvips_mode;
|
||||
struct ospl_in_addr_node *recvips;
|
||||
struct in_addr extmask;
|
||||
nn_locator_t extmask;
|
||||
|
||||
os_sockaddr_storage ownip;
|
||||
os_sockaddr_storage extip;
|
||||
nn_locator_t ownloc;
|
||||
nn_locator_t extloc;
|
||||
|
||||
/* InterfaceNo that the OwnIP is tied to */
|
||||
unsigned interfaceNo;
|
||||
|
@ -293,6 +293,8 @@ struct q_globals {
|
|||
/* Data structure to capture power events */
|
||||
os_timePowerEvents powerEvents;
|
||||
|
||||
struct nn_group_membership *mship;
|
||||
|
||||
/* Static log buffer, for those rare cases a thread calls nn_vlogb
|
||||
without having its own log buffer (happens during config file
|
||||
processing and for listeners, &c. */
|
||||
|
|
18
src/core/ddsi/include/ddsi/q_init.h
Normal file
18
src/core/ddsi/include/ddsi/q_init.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef Q_INIT_H
|
||||
#define Q_INIT_H
|
||||
|
||||
int create_multicast_sockets(void);
|
||||
int joinleave_spdp_defmcip (int dojoin);
|
||||
|
||||
#endif
|
32
src/core/ddsi/include/ddsi/q_inverse_uint32_set.h
Normal file
32
src/core/ddsi/include/ddsi/q_inverse_uint32_set.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef NN_INVERSE_UINT32_SET_H
|
||||
#define NN_INVERSE_UINT32_SET_H
|
||||
|
||||
#include "util/ut_avl.h"
|
||||
|
||||
struct inverse_uint32_set_node {
|
||||
ut_avlNode_t avlnode;
|
||||
uint32_t min, max;
|
||||
};
|
||||
struct inverse_uint32_set {
|
||||
ut_avlTree_t ids;
|
||||
uint32_t cursor;
|
||||
uint32_t min, max;
|
||||
};
|
||||
|
||||
void inverse_uint32_set_init(struct inverse_uint32_set *set, uint32_t min, uint32_t max);
|
||||
void inverse_uint32_set_fini(struct inverse_uint32_set *set);
|
||||
int inverse_uint32_set_alloc(uint32_t * const id, struct inverse_uint32_set *set);
|
||||
void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id);
|
||||
|
||||
#endif
|
|
@ -19,44 +19,22 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define INET6_ADDRSTRLEN_EXTENDED (INET6_ADDRSTRLEN + 8) /* 13: '[' + ']' + ':' + PORT */
|
||||
#define MAX_INTERFACES 128
|
||||
struct nn_interface {
|
||||
os_sockaddr_storage addr;
|
||||
os_sockaddr_storage netmask;
|
||||
nn_locator_t loc;
|
||||
nn_locator_t netmask;
|
||||
unsigned if_index;
|
||||
unsigned mc_capable: 1;
|
||||
unsigned point_to_point: 1;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct nn_group_membership;
|
||||
|
||||
void nn_loc_to_address (os_sockaddr_storage *dst, const nn_locator_t *src);
|
||||
void nn_address_to_loc (nn_locator_t *dst, const os_sockaddr_storage *src, int32_t kind);
|
||||
|
||||
char *sockaddr_to_string_no_port (char addrbuf[INET6_ADDRSTRLEN_EXTENDED], const os_sockaddr_storage *src);
|
||||
char *sockaddr_to_string_with_port (char addrbuf[INET6_ADDRSTRLEN_EXTENDED], const os_sockaddr_storage *src);
|
||||
char *locator_to_string_no_port (char addrbuf[INET6_ADDRSTRLEN_EXTENDED], const nn_locator_t *loc);
|
||||
char *locator_to_string_with_port (char addrbuf[INET6_ADDRSTRLEN_EXTENDED], const nn_locator_t *loc);
|
||||
void print_sockerror (const char *msg);
|
||||
int make_socket (os_socket *socket, unsigned short port, bool stream, bool reuse);
|
||||
int find_own_ip (const char *requested_address);
|
||||
unsigned short get_socket_port (os_socket socket);
|
||||
struct nn_group_membership *new_group_membership (void);
|
||||
void free_group_membership (struct nn_group_membership *mship);
|
||||
int join_mcgroups (struct nn_group_membership *mship, os_socket socket, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip);
|
||||
int leave_mcgroups (struct nn_group_membership *mship, os_socket socket, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip);
|
||||
void sockaddr_set_port (os_sockaddr_storage *addr, unsigned short port);
|
||||
unsigned short sockaddr_get_port (const os_sockaddr_storage *addr);
|
||||
unsigned sockaddr_to_hopefully_unique_uint32 (const os_sockaddr_storage *src);
|
||||
unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
|
||||
void set_socket_diffserv (os_socket sock, int diffserv);
|
||||
#endif
|
||||
|
||||
#endif /* Q_NWIF_H */
|
||||
|
|
|
@ -119,6 +119,7 @@ struct cdrstring {
|
|||
#define NN_LOCATOR_KIND_UDPv6 2
|
||||
#define NN_LOCATOR_KIND_TCPv4 4
|
||||
#define NN_LOCATOR_KIND_TCPv6 8
|
||||
#define NN_LOCATOR_KIND_RAWETH 0x8000 /* proposed vendor-specific */
|
||||
#define NN_LOCATOR_KIND_UDPv4MCGEN 0x4fff0000
|
||||
#define NN_LOCATOR_PORT_INVALID 0
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ struct receiver_state {
|
|||
nn_vendorid_t vendor; /* 2 */
|
||||
nn_protocol_version_t protocol_version; /* 2 => 44/48 */
|
||||
ddsi_tran_conn_t conn; /* Connection for request */
|
||||
nn_locator_t srcloc;
|
||||
};
|
||||
|
||||
struct proxy_writer_info
|
||||
|
|
|
@ -132,11 +132,26 @@ extern "C" {
|
|||
#define ASSERT_WRLOCK_HELD(x) ((void) 0)
|
||||
#define ASSERT_MUTEX_HELD(x) ((void) 0)
|
||||
|
||||
#if ! SYSDEPS_HAVE_IOVEC
|
||||
struct iovec {
|
||||
#if SYSDEPS_HAVE_IOVEC
|
||||
typedef struct iovec ddsi_iovec_t;
|
||||
#elif defined _WIN32 && !defined WINCE
|
||||
typedef struct ddsi_iovec {
|
||||
unsigned iov_len;
|
||||
void *iov_base;
|
||||
} ddsi_iovec_t;
|
||||
#define DDSI_IOVEC_MATCHES_WSABUF do { \
|
||||
struct ddsi_iovec_matches_WSABUF { \
|
||||
char sizeof_matches[sizeof(struct ddsi_iovec) == sizeof(WSABUF) ? 1 : -1]; \
|
||||
char base_off_matches[offsetof(struct ddsi_iovec, iov_base) == offsetof(WSABUF, buf) ? 1 : -1]; \
|
||||
char base_size_matches[sizeof(((struct ddsi_iovec *)8)->iov_base) == sizeof(((WSABUF *)8)->buf) ? 1 : -1]; \
|
||||
char len_off_matches[offsetof(struct ddsi_iovec, iov_len) == offsetof(WSABUF, len) ? 1 : -1]; \
|
||||
char len_size_matches[sizeof(((struct ddsi_iovec *)8)->iov_len) == sizeof(((WSABUF *)8)->len) ? 1 : -1]; \
|
||||
}; } while (0)
|
||||
#else
|
||||
typedef struct ddsi_iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
} ddsi_iovec_t;
|
||||
#endif
|
||||
|
||||
#if ! SYSDEPS_HAVE_MSGHDR
|
||||
|
@ -144,7 +159,7 @@ struct msghdr
|
|||
{
|
||||
void *msg_name;
|
||||
socklen_t msg_namelen;
|
||||
struct iovec *msg_iov;
|
||||
ddsi_iovec_t *msg_iov;
|
||||
size_t msg_iovlen;
|
||||
void *msg_control;
|
||||
size_t msg_controllen;
|
||||
|
|
183
src/core/ddsi/src/ddsi_ipaddr.c
Normal file
183
src/core/ddsi/src/ddsi_ipaddr.c
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "os/os.h"
|
||||
#include "ddsi/ddsi_ipaddr.h"
|
||||
#include "ddsi/q_nwif.h"
|
||||
#include "ddsi/q_config.h"
|
||||
|
||||
enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[])
|
||||
{
|
||||
os_sockaddr_storage tmp, iftmp, nmtmp, ownip;
|
||||
size_t i;
|
||||
(void)tran;
|
||||
ddsi_ipaddr_from_loc(&tmp, loc);
|
||||
for (i = 0; i < ninterf; i++)
|
||||
{
|
||||
ddsi_ipaddr_from_loc(&iftmp, &interf[i].loc);
|
||||
ddsi_ipaddr_from_loc(&nmtmp, &interf[i].netmask);
|
||||
ddsi_ipaddr_from_loc(&ownip, &gv.ownloc);
|
||||
if (os_sockaddrSameSubnet ((os_sockaddr *) &tmp, (os_sockaddr *) &iftmp, (os_sockaddr *) &nmtmp))
|
||||
{
|
||||
if (os_sockaddrIPAddressEqual ((os_sockaddr*) &iftmp, (os_sockaddr*) &ownip))
|
||||
return DNAR_SAME;
|
||||
else
|
||||
return DNAR_LOCAL;
|
||||
}
|
||||
}
|
||||
return DNAR_DISTANT;
|
||||
}
|
||||
|
||||
enum ddsi_locator_from_string_result ddsi_ipaddr_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str, int32_t kind)
|
||||
{
|
||||
os_sockaddr_storage tmpaddr;
|
||||
int ipv4 = (kind == NN_LOCATOR_KIND_UDPv4 || kind == NN_LOCATOR_KIND_TCPv4);
|
||||
assert (kind == NN_LOCATOR_KIND_UDPv4 || kind == NN_LOCATOR_KIND_TCPv4 ||
|
||||
kind == NN_LOCATOR_KIND_TCPv6 || kind == NN_LOCATOR_KIND_UDPv6);
|
||||
(void)tran;
|
||||
if (!os_sockaddrStringToAddress (str, (os_sockaddr *) &tmpaddr, ipv4))
|
||||
return AFSR_INVALID;
|
||||
if ((ipv4 && tmpaddr.ss_family != AF_INET) || (!ipv4 && tmpaddr.ss_family != AF_INET6))
|
||||
return AFSR_MISMATCH;
|
||||
ddsi_ipaddr_to_loc (loc, &tmpaddr, kind);
|
||||
/* This is just an address, so there is no valid value for port, other than INVALID.
|
||||
Without a guarantee that tmpaddr has port 0, best is to set it explicitly here */
|
||||
loc->port = NN_LOCATOR_PORT_INVALID;
|
||||
return AFSR_OK;
|
||||
}
|
||||
|
||||
char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port)
|
||||
{
|
||||
os_sockaddr_storage src;
|
||||
size_t pos;
|
||||
(void)tran;
|
||||
assert (sizeof_dst > 1);
|
||||
ddsi_ipaddr_from_loc(&src, loc);
|
||||
switch (src.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
os_sockaddrAddressToString ((const os_sockaddr *) &src, dst, sizeof_dst);
|
||||
if (with_port) {
|
||||
pos = strlen (dst);
|
||||
assert(pos <= sizeof_dst);
|
||||
snprintf (dst + pos, sizeof_dst - pos, ":%d", loc->port);
|
||||
}
|
||||
break;
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case AF_INET6:
|
||||
dst[0] = '[';
|
||||
os_sockaddrAddressToString ((const os_sockaddr *) &src, dst + 1, sizeof_dst);
|
||||
pos = strlen (dst);
|
||||
if (with_port) {
|
||||
assert(pos <= sizeof_dst);
|
||||
snprintf (dst + pos, sizeof_dst - pos, "]:%u", loc->port);
|
||||
} else {
|
||||
snprintf (dst + pos, sizeof_dst - pos, "]");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
dst[0] = 0;
|
||||
break;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
void ddsi_ipaddr_to_loc (nn_locator_t *dst, const os_sockaddr_storage *src, int32_t kind)
|
||||
{
|
||||
dst->kind = kind;
|
||||
switch (src->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
const os_sockaddr_in *x = (const os_sockaddr_in *) src;
|
||||
assert (kind == NN_LOCATOR_KIND_UDPv4 || kind == NN_LOCATOR_KIND_TCPv4);
|
||||
if (x->sin_addr.s_addr == htonl (INADDR_ANY))
|
||||
{
|
||||
dst->kind = NN_LOCATOR_KIND_INVALID;
|
||||
dst->port = NN_LOCATOR_PORT_INVALID;
|
||||
memset (dst->address, 0, sizeof (dst->address));
|
||||
}
|
||||
else
|
||||
{
|
||||
dst->port = (x->sin_port == 0) ? NN_LOCATOR_PORT_INVALID : ntohs (x->sin_port);
|
||||
memset (dst->address, 0, 12);
|
||||
memcpy (dst->address + 12, &x->sin_addr.s_addr, 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case AF_INET6:
|
||||
{
|
||||
const os_sockaddr_in6 *x = (const os_sockaddr_in6 *) src;
|
||||
assert (kind == NN_LOCATOR_KIND_UDPv6 || kind == NN_LOCATOR_KIND_TCPv6);
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&x->sin6_addr))
|
||||
{
|
||||
dst->kind = NN_LOCATOR_KIND_INVALID;
|
||||
dst->port = NN_LOCATOR_PORT_INVALID;
|
||||
memset (dst->address, 0, sizeof (dst->address));
|
||||
}
|
||||
else
|
||||
{
|
||||
dst->port = (x->sin6_port == 0) ? NN_LOCATOR_PORT_INVALID : ntohs (x->sin6_port);
|
||||
memcpy (dst->address, &x->sin6_addr.s6_addr, 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
NN_FATAL ("nn_address_to_loc: family %d unsupported\n", (int) src->ss_family);
|
||||
}
|
||||
}
|
||||
|
||||
void ddsi_ipaddr_from_loc (os_sockaddr_storage *dst, const nn_locator_t *src)
|
||||
{
|
||||
memset (dst, 0, sizeof (*dst));
|
||||
switch (src->kind)
|
||||
{
|
||||
case NN_LOCATOR_KIND_INVALID:
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
dst->ss_family = (config.transport_selector == TRANS_UDP6 || config.transport_selector == TRANS_TCP6) ? AF_INET6 : AF_INET;
|
||||
#else
|
||||
dst->ss_family = AF_INET;
|
||||
#endif
|
||||
break;
|
||||
case NN_LOCATOR_KIND_UDPv4:
|
||||
case NN_LOCATOR_KIND_TCPv4:
|
||||
{
|
||||
os_sockaddr_in *x = (os_sockaddr_in *) dst;
|
||||
x->sin_family = AF_INET;
|
||||
x->sin_port = (src->port == NN_LOCATOR_PORT_INVALID) ? 0 : htons ((unsigned short) src->port);
|
||||
memcpy (&x->sin_addr.s_addr, src->address + 12, 4);
|
||||
break;
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case NN_LOCATOR_KIND_UDPv6:
|
||||
case NN_LOCATOR_KIND_TCPv6:
|
||||
{
|
||||
os_sockaddr_in6 *x = (os_sockaddr_in6 *) dst;
|
||||
x->sin6_family = AF_INET6;
|
||||
x->sin6_port = (src->port == NN_LOCATOR_PORT_INVALID) ? 0 : htons ((unsigned short) src->port);
|
||||
memcpy (&x->sin6_addr.s6_addr, src->address, 16);
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&x->sin6_addr))
|
||||
{
|
||||
x->sin6_scope_id = gv.interfaceNo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
299
src/core/ddsi/src/ddsi_mcgroup.c
Normal file
299
src/core/ddsi/src/ddsi_mcgroup.c
Normal file
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "os/os.h"
|
||||
#include "os/os_atomics.h"
|
||||
#include "ddsi/ddsi_tran.h"
|
||||
#include "ddsi/ddsi_mcgroup.h"
|
||||
#include "ddsi/q_config.h"
|
||||
#include "ddsi/q_log.h"
|
||||
#include "util/ut_avl.h"
|
||||
|
||||
struct nn_group_membership_node {
|
||||
ut_avlNode_t avlnode;
|
||||
ddsi_tran_conn_t conn;
|
||||
nn_locator_t srcloc;
|
||||
nn_locator_t mcloc;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
struct nn_group_membership {
|
||||
os_mutex lock;
|
||||
ut_avlTree_t mships;
|
||||
};
|
||||
|
||||
static int locator_compare_no_port (const nn_locator_t *as, const nn_locator_t *bs)
|
||||
{
|
||||
if (as->kind != bs->kind)
|
||||
return (as->kind < bs->kind) ? -1 : 1;
|
||||
else
|
||||
return memcmp (as->address, bs->address, 16);
|
||||
}
|
||||
|
||||
static int cmp_group_membership (const void *va, const void *vb)
|
||||
{
|
||||
const struct nn_group_membership_node *a = va;
|
||||
const struct nn_group_membership_node *b = vb;
|
||||
int c;
|
||||
if (a->conn < b->conn)
|
||||
return -1;
|
||||
else if (a->conn > b->conn)
|
||||
return 1;
|
||||
else if ((c = memcmp (&a->srcloc, &b->srcloc, sizeof(a->srcloc))) != 0)
|
||||
return c;
|
||||
else if ((c = memcmp (&a->mcloc, &b->mcloc, sizeof(a->mcloc))) != 0)
|
||||
return c;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ut_avlTreedef_t mship_td = UT_AVL_TREEDEF_INITIALIZER(offsetof (struct nn_group_membership_node, avlnode), 0, cmp_group_membership, 0);
|
||||
|
||||
struct nn_group_membership *new_group_membership (void)
|
||||
{
|
||||
struct nn_group_membership *mship = os_malloc (sizeof (*mship));
|
||||
os_mutexInit (&mship->lock);
|
||||
ut_avlInit (&mship_td, &mship->mships);
|
||||
return mship;
|
||||
}
|
||||
|
||||
void free_group_membership (struct nn_group_membership *mship)
|
||||
{
|
||||
ut_avlFree (&mship_td, &mship->mships, os_free);
|
||||
os_mutexDestroy (&mship->lock);
|
||||
os_free (mship);
|
||||
}
|
||||
|
||||
static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
{
|
||||
struct nn_group_membership_node key, *n;
|
||||
ut_avlIPath_t ip;
|
||||
int isnew;
|
||||
key.conn = conn;
|
||||
if (srcloc)
|
||||
key.srcloc = *srcloc;
|
||||
else
|
||||
memset (&key.srcloc, 0, sizeof (key.srcloc));
|
||||
key.mcloc = *mcloc;
|
||||
if ((n = ut_avlLookupIPath (&mship_td, &mship->mships, &key, &ip)) != NULL) {
|
||||
isnew = 0;
|
||||
n->count++;
|
||||
} else {
|
||||
isnew = 1;
|
||||
n = os_malloc (sizeof (*n));
|
||||
n->conn = conn;
|
||||
n->srcloc = key.srcloc;
|
||||
n->mcloc = key.mcloc;
|
||||
n->count = 1;
|
||||
ut_avlInsertIPath (&mship_td, &mship->mships, n, &ip);
|
||||
}
|
||||
return isnew;
|
||||
}
|
||||
|
||||
static int unreg_group_membership (struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
{
|
||||
struct nn_group_membership_node key, *n;
|
||||
ut_avlDPath_t dp;
|
||||
int mustdel;
|
||||
key.conn = conn;
|
||||
if (srcloc)
|
||||
key.srcloc = *srcloc;
|
||||
else
|
||||
memset (&key.srcloc, 0, sizeof (key.srcloc));
|
||||
key.mcloc = *mcloc;
|
||||
n = ut_avlLookupDPath (&mship_td, &mship->mships, &key, &dp);
|
||||
assert (n != NULL);
|
||||
assert (n->count > 0);
|
||||
if (--n->count > 0)
|
||||
mustdel = 0;
|
||||
else
|
||||
{
|
||||
mustdel = 1;
|
||||
ut_avlDeleteDPath (&mship_td, &mship->mships, n, &dp);
|
||||
os_free (n);
|
||||
}
|
||||
return mustdel;
|
||||
}
|
||||
|
||||
static char *make_joinleave_msg (char *buf, size_t bufsz, ddsi_tran_conn_t conn, int join, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf, int err)
|
||||
{
|
||||
char mcstr[DDSI_LOCSTRLEN], srcstr[DDSI_LOCSTRLEN], interfstr[DDSI_LOCSTRLEN];
|
||||
int n;
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
if (srcloc)
|
||||
ddsi_locator_to_string_no_port(srcstr, sizeof(srcstr), srcloc);
|
||||
else
|
||||
strcpy (srcstr, "*");
|
||||
#else
|
||||
OS_UNUSED_ARG (srcloc);
|
||||
strcpy (srcstr, "*");
|
||||
#endif
|
||||
ddsi_locator_to_string_no_port (mcstr, sizeof(mcstr), mcloc);
|
||||
if (interf)
|
||||
ddsi_locator_to_string_no_port(interfstr, sizeof(interfstr), &interf->loc);
|
||||
else
|
||||
(void) snprintf (interfstr, sizeof (interfstr), "(default)");
|
||||
n = err ? snprintf (buf, bufsz, "error %d in ", err) : 0;
|
||||
if ((size_t) n < bufsz)
|
||||
snprintf (buf + n, bufsz - (size_t) n, "%s conn %p for (%s, %s) interface %s", join ? "join" : "leave", (void *) conn, mcstr, srcstr, interfstr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int joinleave_mcgroup (ddsi_tran_conn_t conn, int join, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
char buf[256];
|
||||
int err;
|
||||
TRACE (("%s\n", make_joinleave_msg (buf, sizeof(buf), conn, join, srcloc, mcloc, interf, 0)));
|
||||
if (join)
|
||||
err = ddsi_conn_join_mc(conn, srcloc, mcloc, interf);
|
||||
else
|
||||
err = ddsi_conn_leave_mc(conn, srcloc, mcloc, interf);
|
||||
if (err)
|
||||
NN_WARNING ("%s\n", make_joinleave_msg (buf, sizeof(buf), conn, join, srcloc, mcloc, interf, err));
|
||||
return err ? -1 : 0;
|
||||
}
|
||||
|
||||
static int interface_in_recvips_p (const struct nn_interface *interf)
|
||||
{
|
||||
struct ospl_in_addr_node *nodeaddr;
|
||||
for (nodeaddr = gv.recvips; nodeaddr; nodeaddr = nodeaddr->next)
|
||||
{
|
||||
if (locator_compare_no_port(&nodeaddr->loc, &interf->loc) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int joinleave_mcgroups (ddsi_tran_conn_t conn, int join, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
{
|
||||
int rc;
|
||||
switch (gv.recvips_mode)
|
||||
{
|
||||
case RECVIPS_MODE_NONE:
|
||||
break;
|
||||
case RECVIPS_MODE_ANY:
|
||||
/* User has specified to use the OS default interface */
|
||||
if ((rc = joinleave_mcgroup (conn, join, srcloc, mcloc, NULL)) < 0)
|
||||
return rc;
|
||||
break;
|
||||
case RECVIPS_MODE_PREFERRED:
|
||||
if (gv.interfaces[gv.selected_interface].mc_capable)
|
||||
return joinleave_mcgroup (conn, join, srcloc, mcloc, &gv.interfaces[gv.selected_interface]);
|
||||
return 0;
|
||||
case RECVIPS_MODE_ALL:
|
||||
case RECVIPS_MODE_SOME:
|
||||
{
|
||||
int i, fails = 0, oks = 0;
|
||||
for (i = 0; i < gv.n_interfaces; i++)
|
||||
{
|
||||
if (gv.interfaces[i].mc_capable)
|
||||
{
|
||||
if (gv.recvips_mode == RECVIPS_MODE_ALL || interface_in_recvips_p (&gv.interfaces[i]))
|
||||
{
|
||||
if ((rc = joinleave_mcgroup (conn, join, srcloc, mcloc, &gv.interfaces[i])) < 0)
|
||||
fails++;
|
||||
else
|
||||
oks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fails > 0)
|
||||
{
|
||||
if (oks > 0)
|
||||
TRACE (("multicast join failed for some but not all interfaces, proceeding\n"));
|
||||
else
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ddsi_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
{
|
||||
int ret;
|
||||
os_mutexLock (&gv.mship->lock);
|
||||
if (!reg_group_membership (gv.mship, conn, srcloc, mcloc))
|
||||
{
|
||||
char buf[256];
|
||||
TRACE (("%s: already joined\n", make_joinleave_msg (buf, sizeof(buf), conn, 1, srcloc, mcloc, NULL, 0)));
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = joinleave_mcgroups (conn, 1, srcloc, mcloc);
|
||||
}
|
||||
os_mutexUnlock (&gv.mship->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ddsi_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
{
|
||||
int ret;
|
||||
os_mutexLock (&gv.mship->lock);
|
||||
if (!unreg_group_membership (gv.mship, conn, srcloc, mcloc))
|
||||
{
|
||||
char buf[256];
|
||||
TRACE (("%s: not leaving yet\n", make_joinleave_msg (buf, sizeof(buf), conn, 0, srcloc, mcloc, NULL, 0)));
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = joinleave_mcgroups (conn, 0, srcloc, mcloc);
|
||||
}
|
||||
os_mutexUnlock (&gv.mship->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ddsi_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t newconn)
|
||||
{
|
||||
struct nn_group_membership_node *n, min, max;
|
||||
memset(&min, 0, sizeof(min));
|
||||
memset(&max, 0xff, sizeof(max));
|
||||
min.conn = max.conn = conn;
|
||||
/* ordering is on socket, then src IP, then mc IP; IP compare checks family first and AF_INET, AF_INET6
|
||||
are neither 0 nor maximum representable, min and max define the range of key values that relate to
|
||||
oldsock */
|
||||
os_mutexLock (&gv.mship->lock);
|
||||
n = ut_avlLookupSuccEq (&mship_td, &gv.mship->mships, &min);
|
||||
while (n != NULL && cmp_group_membership (n, &max) <= 0)
|
||||
{
|
||||
struct nn_group_membership_node * const nn = ut_avlFindSucc (&mship_td, &gv.mship->mships, n);
|
||||
ut_avlDelete (&mship_td, &gv.mship->mships, n);
|
||||
n->conn = newconn;
|
||||
ut_avlInsert (&mship_td, &gv.mship->mships, n);
|
||||
n = nn;
|
||||
}
|
||||
os_mutexUnlock (&gv.mship->lock);
|
||||
}
|
||||
|
||||
int ddsi_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn)
|
||||
{
|
||||
struct nn_group_membership_node *n, min, max;
|
||||
ut_avlIter_t it;
|
||||
int ret = 0;
|
||||
memset(&min, 0, sizeof(min));
|
||||
memset(&max, 0xff, sizeof(max));
|
||||
min.conn = max.conn = conn;
|
||||
os_mutexLock (&gv.mship->lock);
|
||||
for (n = ut_avlIterSuccEq (&mship_td, &gv.mship->mships, &it, &min); n != NULL && ret >= 0 && cmp_group_membership(n, &max) <= 0; n = ut_avlIterNext (&it))
|
||||
{
|
||||
int have_srcloc = (memcmp(&n->srcloc, &min.srcloc, sizeof(n->srcloc)) != 0);
|
||||
assert (n->conn == conn);
|
||||
ret = joinleave_mcgroups (conn, 1, have_srcloc ? &n->srcloc : NULL, &n->mcloc);
|
||||
}
|
||||
os_mutexUnlock (&gv.mship->lock);
|
||||
return ret;
|
||||
}
|
418
src/core/ddsi/src/ddsi_raweth.c
Normal file
418
src/core/ddsi/src/ddsi_raweth.c
Normal file
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "os/os.h"
|
||||
#include "ddsi/ddsi_tran.h"
|
||||
#include "ddsi/ddsi_raweth.h"
|
||||
#include "ddsi/ddsi_ipaddr.h"
|
||||
#include "ddsi/ddsi_mcgroup.h"
|
||||
#include "ddsi/q_nwif.h"
|
||||
#include "ddsi/q_config.h"
|
||||
#include "ddsi/q_log.h"
|
||||
#include "ddsi/q_error.h"
|
||||
#include "ddsi/q_pcap.h"
|
||||
#include "os/os_atomics.h"
|
||||
|
||||
#ifdef __linux
|
||||
#include <linux/if_packet.h>
|
||||
#include <sys/types.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
typedef struct ddsi_tran_factory * ddsi_raweth_factory_t;
|
||||
|
||||
typedef struct ddsi_raweth_config
|
||||
{
|
||||
struct nn_group_membership *mship;
|
||||
}
|
||||
* ddsi_raweth_config_t;
|
||||
|
||||
typedef struct ddsi_raweth_conn
|
||||
{
|
||||
struct ddsi_tran_conn m_base;
|
||||
os_socket m_sock;
|
||||
int m_ifindex;
|
||||
}
|
||||
* ddsi_raweth_conn_t;
|
||||
|
||||
static struct ddsi_raweth_config ddsi_raweth_config_g;
|
||||
static struct ddsi_tran_factory ddsi_raweth_factory_g;
|
||||
static pa_uint32_t init_g = PA_UINT32_INIT(0);
|
||||
|
||||
static char *ddsi_raweth_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port)
|
||||
{
|
||||
(void)tran;
|
||||
if (with_port)
|
||||
snprintf(dst, sizeof_dst, "[%02x:%02x:%02x:%02x:%02x:%02x]:%u",
|
||||
loc->address[10], loc->address[11], loc->address[12],
|
||||
loc->address[13], loc->address[14], loc->address[15], loc->port);
|
||||
else
|
||||
snprintf(dst, sizeof_dst, "[%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
loc->address[10], loc->address[11], loc->address[12],
|
||||
loc->address[13], loc->address[14], loc->address[15]);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static ssize_t ddsi_raweth_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc)
|
||||
{
|
||||
int err;
|
||||
ssize_t ret;
|
||||
struct msghdr msghdr;
|
||||
struct sockaddr_ll src;
|
||||
struct iovec msg_iov;
|
||||
socklen_t srclen = (socklen_t) sizeof (src);
|
||||
|
||||
msg_iov.iov_base = (void*) buf;
|
||||
msg_iov.iov_len = len;
|
||||
|
||||
memset (&msghdr, 0, sizeof (msghdr));
|
||||
|
||||
msghdr.msg_name = &src;
|
||||
msghdr.msg_namelen = srclen;
|
||||
msghdr.msg_iov = &msg_iov;
|
||||
msghdr.msg_iovlen = 1;
|
||||
|
||||
do {
|
||||
ret = recvmsg(((ddsi_raweth_conn_t) conn)->m_sock, &msghdr, 0);
|
||||
err = (ret == -1) ? os_getErrno() : 0;
|
||||
} while (err == os_sockEINTR);
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
if (srcloc)
|
||||
{
|
||||
srcloc->kind = NN_LOCATOR_KIND_RAWETH;
|
||||
srcloc->port = ntohs (src.sll_protocol);
|
||||
memset(srcloc->address, 0, 10);
|
||||
memcpy(srcloc->address + 10, src.sll_addr, 6);
|
||||
}
|
||||
|
||||
/* Check for udp packet truncation */
|
||||
if ((((size_t) ret) > len)
|
||||
#if SYSDEPS_MSGHDR_FLAGS
|
||||
|| (msghdr.msg_flags & MSG_TRUNC)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
char addrbuf[DDSI_LOCSTRLEN];
|
||||
snprintf(addrbuf, sizeof(addrbuf), "[%02x:%02x:%02x:%02x:%02x:%02x]:%u",
|
||||
src.sll_addr[0], src.sll_addr[1], src.sll_addr[2],
|
||||
src.sll_addr[3], src.sll_addr[4], src.sll_addr[5], ntohs(src.sll_protocol));
|
||||
NN_WARNING ("%s => %d truncated to %d\n", addrbuf, (int)ret, (int)len);
|
||||
}
|
||||
}
|
||||
else if (err != os_sockENOTSOCK && err != os_sockECONNRESET)
|
||||
{
|
||||
NN_ERROR ("UDP recvmsg sock %d: ret %d errno %d\n", (int) ((ddsi_raweth_conn_t) conn)->m_sock, (int) ret, err);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ddsi_raweth_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const ddsi_iovec_t *iov, uint32_t flags)
|
||||
{
|
||||
ddsi_raweth_conn_t uc = (ddsi_raweth_conn_t) conn;
|
||||
int err;
|
||||
ssize_t ret;
|
||||
unsigned retry = 2;
|
||||
int sendflags = 0;
|
||||
struct msghdr msg;
|
||||
struct sockaddr_ll dstaddr;
|
||||
assert(niov <= INT_MAX);
|
||||
memset (&dstaddr, 0, sizeof (dstaddr));
|
||||
dstaddr.sll_family = AF_PACKET;
|
||||
dstaddr.sll_protocol = htons ((uint16_t) dst->port);
|
||||
dstaddr.sll_ifindex = uc->m_ifindex;
|
||||
dstaddr.sll_halen = 6;
|
||||
memcpy(dstaddr.sll_addr, dst->address + 10, 6);
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_name = &dstaddr;
|
||||
msg.msg_namelen = sizeof(dstaddr);
|
||||
msg.msg_flags = (int) flags;
|
||||
msg.msg_iov = (ddsi_iovec_t *) iov;
|
||||
msg.msg_iovlen = niov;
|
||||
#ifdef MSG_NOSIGNAL
|
||||
sendflags |= MSG_NOSIGNAL;
|
||||
#endif
|
||||
do {
|
||||
ret = sendmsg (uc->m_sock, &msg, sendflags);
|
||||
err = (ret == -1) ? os_getErrno() : 0;
|
||||
} while (err == os_sockEINTR || err == os_sockEWOULDBLOCK || (err == os_sockEPERM && retry-- > 0));
|
||||
if (ret == -1)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case os_sockEINTR:
|
||||
case os_sockEPERM:
|
||||
case os_sockECONNRESET:
|
||||
#ifdef os_sockENETUNREACH
|
||||
case os_sockENETUNREACH:
|
||||
#endif
|
||||
#ifdef os_sockEHOSTUNREACH
|
||||
case os_sockEHOSTUNREACH:
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
NN_ERROR("ddsi_raweth_conn_write failed with error code %d", err);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static os_handle ddsi_raweth_conn_handle (ddsi_tran_base_t base)
|
||||
{
|
||||
return ((ddsi_raweth_conn_t) base)->m_sock;
|
||||
}
|
||||
|
||||
static bool ddsi_raweth_supports (int32_t kind)
|
||||
{
|
||||
return (kind == NN_LOCATOR_KIND_RAWETH);
|
||||
}
|
||||
|
||||
static int ddsi_raweth_conn_locator (ddsi_tran_base_t base, nn_locator_t *loc)
|
||||
{
|
||||
ddsi_raweth_conn_t uc = (ddsi_raweth_conn_t) base;
|
||||
int ret = -1;
|
||||
if (uc->m_sock != Q_INVALID_SOCKET)
|
||||
{
|
||||
loc->kind = NN_LOCATOR_KIND_RAWETH;
|
||||
loc->port = uc->m_base.m_base.m_port;
|
||||
memcpy(loc->address, gv.extloc.address, sizeof (loc->address));
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ddsi_tran_conn_t ddsi_raweth_create_conn (uint32_t port, ddsi_tran_qos_t qos)
|
||||
{
|
||||
os_socket sock;
|
||||
int rc;
|
||||
ddsi_raweth_conn_t uc = NULL;
|
||||
struct sockaddr_ll addr;
|
||||
bool mcast = (bool) (qos ? qos->m_multicast : FALSE);
|
||||
|
||||
/* If port is zero, need to create dynamic port */
|
||||
|
||||
if (port == 0 || port > 65535)
|
||||
{
|
||||
NN_ERROR("ddsi_raweth_create_conn %s port %u - using port number as ethernet type, %u won't do\n", mcast ? "multicast" : "unicast", port, port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((sock = socket(PF_PACKET, SOCK_DGRAM, htons((uint16_t)port))) == -1)
|
||||
{
|
||||
rc = os_getErrno();
|
||||
NN_ERROR("ddsi_raweth_create_conn %s port %u failed ... errno = %d\n", mcast ? "multicast" : "unicast", port, rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sll_family = AF_PACKET;
|
||||
addr.sll_protocol = htons((uint16_t)port);
|
||||
addr.sll_ifindex = (int)gv.interfaceNo;
|
||||
addr.sll_pkttype = PACKET_HOST | PACKET_BROADCAST | PACKET_MULTICAST;
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
rc = os_getErrno();
|
||||
close(sock);
|
||||
NN_ERROR("ddsi_raweth_create_conn %s bind port %u failed ... errno = %d\n", mcast ? "multicast" : "unicast", port, rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uc = (ddsi_raweth_conn_t) os_malloc (sizeof (*uc));
|
||||
memset (uc, 0, sizeof (*uc));
|
||||
uc->m_sock = sock;
|
||||
uc->m_ifindex = addr.sll_ifindex;
|
||||
ddsi_factory_conn_init (&ddsi_raweth_factory_g, &uc->m_base);
|
||||
uc->m_base.m_base.m_port = port;
|
||||
uc->m_base.m_base.m_trantype = DDSI_TRAN_CONN;
|
||||
uc->m_base.m_base.m_multicast = mcast;
|
||||
uc->m_base.m_base.m_handle_fn = ddsi_raweth_conn_handle;
|
||||
uc->m_base.m_base.m_locator_fn = ddsi_raweth_conn_locator;
|
||||
uc->m_base.m_read_fn = ddsi_raweth_conn_read;
|
||||
uc->m_base.m_write_fn = ddsi_raweth_conn_write;
|
||||
|
||||
nn_log(LC_INFO, "ddsi_raweth_create_conn %s socket %d port %u\n", mcast ? "multicast" : "unicast", uc->m_sock, uc->m_base.m_base.m_port);
|
||||
return uc ? &uc->m_base : NULL;
|
||||
}
|
||||
|
||||
static int isbroadcast(const nn_locator_t *loc)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 6; i++)
|
||||
if (loc->address[10 + i] != 0xff)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int joinleave_asm_mcgroup (os_socket socket, int join, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
int rc;
|
||||
struct packet_mreq mreq;
|
||||
mreq.mr_ifindex = (int)interf->if_index;
|
||||
mreq.mr_type = PACKET_MR_MULTICAST;
|
||||
mreq.mr_alen = 6;
|
||||
memcpy(mreq.mr_address, mcloc + 10, 6);
|
||||
rc = setsockopt(socket, SOL_PACKET, join ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
|
||||
return (rc == -1) ? os_getErrno() : 0;
|
||||
}
|
||||
|
||||
static int ddsi_raweth_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
if (isbroadcast(mcloc))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
ddsi_raweth_conn_t uc = (ddsi_raweth_conn_t) conn;
|
||||
(void)srcloc;
|
||||
return joinleave_asm_mcgroup(uc->m_sock, 1, mcloc, interf);
|
||||
}
|
||||
}
|
||||
|
||||
static int ddsi_raweth_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
if (isbroadcast(mcloc))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
ddsi_raweth_conn_t uc = (ddsi_raweth_conn_t) conn;
|
||||
(void)srcloc;
|
||||
return joinleave_asm_mcgroup(uc->m_sock, 0, mcloc, interf);
|
||||
}
|
||||
}
|
||||
|
||||
static void ddsi_raweth_release_conn (ddsi_tran_conn_t conn)
|
||||
{
|
||||
ddsi_raweth_conn_t uc = (ddsi_raweth_conn_t) conn;
|
||||
nn_log
|
||||
(
|
||||
LC_INFO,
|
||||
"ddsi_raweth_release_conn %s socket %d port %d\n",
|
||||
conn->m_base.m_multicast ? "multicast" : "unicast",
|
||||
uc->m_sock,
|
||||
uc->m_base.m_base.m_port
|
||||
);
|
||||
os_sockFree (uc->m_sock);
|
||||
os_free (conn);
|
||||
}
|
||||
|
||||
static int ddsi_raweth_is_mcaddr (const ddsi_tran_factory_t tran, const nn_locator_t *loc)
|
||||
{
|
||||
(void) tran;
|
||||
assert (loc->kind == NN_LOCATOR_KIND_RAWETH);
|
||||
return (loc->address[10] & 1);
|
||||
}
|
||||
|
||||
static enum ddsi_locator_from_string_result ddsi_raweth_address_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str)
|
||||
{
|
||||
int i = 0;
|
||||
(void)tran;
|
||||
loc->kind = NN_LOCATOR_KIND_RAWETH;
|
||||
loc->port = NN_LOCATOR_PORT_INVALID;
|
||||
memset (loc->address, 0, sizeof (loc->address));
|
||||
while (i < 6 && *str != 0)
|
||||
{
|
||||
int o, p;
|
||||
if (sscanf (str, "%x%n", &o, &p) != 1 || o < 0 || o > 255)
|
||||
return AFSR_INVALID;
|
||||
loc->address[10 + i++] = (unsigned char) o;
|
||||
str += p;
|
||||
if (i < 6)
|
||||
{
|
||||
if (*str != ':')
|
||||
return AFSR_INVALID;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
if (*str)
|
||||
return AFSR_INVALID;
|
||||
return AFSR_OK;
|
||||
}
|
||||
|
||||
static void ddsi_raweth_deinit(void)
|
||||
{
|
||||
if (pa_dec32_nv(&init_g) == 0) {
|
||||
if (ddsi_raweth_config_g.mship)
|
||||
free_group_membership(ddsi_raweth_config_g.mship);
|
||||
nn_log (LC_INFO | LC_CONFIG, "raweth de-initialized\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int ddsi_raweth_enumerate_interfaces (ddsi_tran_factory_t factory, int max, struct os_ifAttributes_s *interfs)
|
||||
{
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
int cnt = 0;
|
||||
(void)factory;
|
||||
if (getifaddrs (&ifaddr) == -1)
|
||||
return -errno;
|
||||
for (ifa = ifaddr; ifa && cnt < max; ifa = ifa->ifa_next)
|
||||
{
|
||||
struct os_ifAttributes_s *f = &interfs[cnt];
|
||||
struct sockaddr_ll *x;
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue;
|
||||
if (ifa->ifa_addr->sa_family != AF_PACKET)
|
||||
continue;
|
||||
if ((ifa->ifa_flags & (IFF_UP | IFF_BROADCAST)) != (IFF_UP | IFF_BROADCAST))
|
||||
continue;
|
||||
strncpy(f->name, ifa->ifa_name, sizeof(f->name));
|
||||
f->name[sizeof(f->name)-1] = 0;
|
||||
f->flags = ifa->ifa_flags;
|
||||
f->interfaceIndexNo = if_nametoindex(f->name);
|
||||
x = (struct sockaddr_ll *)&f->address;
|
||||
memcpy(x, ifa->ifa_addr, sizeof (*x));
|
||||
x = (struct sockaddr_ll *)&f->network_mask;
|
||||
if (ifa->ifa_netmask)
|
||||
memcpy(x, ifa->ifa_netmask, sizeof (*x));
|
||||
else
|
||||
memset(x, 0, sizeof(*x));
|
||||
x = (struct sockaddr_ll *)&f->broadcast_address;
|
||||
if (ifa->ifa_broadaddr)
|
||||
memcpy(x, ifa->ifa_broadaddr, sizeof (*x));
|
||||
else
|
||||
memset(x, 0, sizeof(*x));
|
||||
cnt++;
|
||||
}
|
||||
freeifaddrs (ifaddr);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int ddsi_raweth_init (void)
|
||||
{
|
||||
if (pa_inc32_nv(&init_g) == 1) {
|
||||
memset (&ddsi_raweth_factory_g, 0, sizeof (ddsi_raweth_factory_g));
|
||||
ddsi_raweth_factory_g.m_free_fn = ddsi_raweth_deinit;
|
||||
ddsi_raweth_factory_g.m_kind = NN_LOCATOR_KIND_RAWETH;
|
||||
ddsi_raweth_factory_g.m_typename = "raweth";
|
||||
ddsi_raweth_factory_g.m_default_spdp_address = "raweth/ff:ff:ff:ff:ff:ff";
|
||||
ddsi_raweth_factory_g.m_connless = TRUE;
|
||||
ddsi_raweth_factory_g.m_supports_fn = ddsi_raweth_supports;
|
||||
ddsi_raweth_factory_g.m_create_conn_fn = ddsi_raweth_create_conn;
|
||||
ddsi_raweth_factory_g.m_release_conn_fn = ddsi_raweth_release_conn;
|
||||
ddsi_raweth_factory_g.m_join_mc_fn = ddsi_raweth_join_mc;
|
||||
ddsi_raweth_factory_g.m_leave_mc_fn = ddsi_raweth_leave_mc;
|
||||
ddsi_raweth_factory_g.m_is_mcaddr_fn = ddsi_raweth_is_mcaddr;
|
||||
ddsi_raweth_factory_g.m_is_nearby_address_fn = ddsi_ipaddr_is_nearby_address;
|
||||
ddsi_raweth_factory_g.m_locator_from_string_fn = ddsi_raweth_address_from_string;
|
||||
ddsi_raweth_factory_g.m_locator_to_string_fn = ddsi_raweth_to_string;
|
||||
ddsi_raweth_factory_g.m_enumerate_interfaces_fn = ddsi_raweth_enumerate_interfaces;
|
||||
ddsi_factory_add (&ddsi_raweth_factory_g);
|
||||
|
||||
ddsi_raweth_config_g.mship = new_group_membership();
|
||||
|
||||
nn_log (LC_INFO | LC_CONFIG, "raweth initialized\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int ddsi_raweth_init (void) { return 0; }
|
||||
|
||||
#endif /* defined __linux */
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "ddsi/ddsi_tran.h"
|
||||
#include "ddsi/ddsi_tcp.h"
|
||||
#include "ddsi/ddsi_ipaddr.h"
|
||||
#include "util/ut_avl.h"
|
||||
#include "ddsi/q_nwif.h"
|
||||
#include "ddsi/q_config.h"
|
||||
|
@ -81,6 +82,16 @@ static void nn_trace_tcp (const char *fmt, ...)
|
|||
|
||||
#define TRACE_TCP(args) ((config.enabled_logcats & LC_TCP) ? (nn_trace_tcp args) : (void) 0)
|
||||
|
||||
static unsigned short sockaddr_get_port (const os_sockaddr_storage *addr)
|
||||
{
|
||||
if (addr->ss_family == AF_INET)
|
||||
return ntohs (((os_sockaddr_in *) addr)->sin_port);
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
else
|
||||
return ntohs (((os_sockaddr_in6 *) addr)->sin6_port);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ddsi_tcp_cmp_conn (const ddsi_tcp_conn_t c1, const ddsi_tcp_conn_t c2)
|
||||
{
|
||||
const os_sockaddr_storage *a1s = &c1->m_peer_addr;
|
||||
|
@ -130,7 +141,14 @@ static ut_avlTree_t ddsi_tcp_cache_g;
|
|||
static struct ddsi_tran_factory ddsi_tcp_factory_g;
|
||||
|
||||
static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket, bool, os_sockaddr_storage *);
|
||||
extern void ddsi_factory_conn_init (ddsi_tran_factory_t, ddsi_tran_conn_t);
|
||||
|
||||
static char *sockaddr_to_string_with_port (char *dst, size_t sizeof_dst, const os_sockaddr_storage *src)
|
||||
{
|
||||
nn_locator_t loc;
|
||||
ddsi_ipaddr_to_loc(&loc, src, src->ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6);
|
||||
ddsi_locator_to_string(dst, sizeof_dst, &loc);
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* Connection cache dump routine for debugging
|
||||
|
||||
|
@ -157,6 +175,19 @@ static void ddsi_tcp_cache_dump (void)
|
|||
}
|
||||
*/
|
||||
|
||||
static unsigned short get_socket_port (os_socket socket)
|
||||
{
|
||||
os_sockaddr_storage addr;
|
||||
socklen_t addrlen = sizeof (addr);
|
||||
if (getsockname (socket, (os_sockaddr *) &addr, &addrlen) < 0)
|
||||
{
|
||||
int err = os_getErrno();
|
||||
NN_ERROR ("ddsi_tcp_get_socket_port: getsockname errno %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
return sockaddr_get_port(&addr);
|
||||
}
|
||||
|
||||
static void ddsi_tcp_conn_set_socket (ddsi_tcp_conn_t conn, os_socket sock)
|
||||
{
|
||||
conn->m_sock = sock;
|
||||
|
@ -193,7 +224,7 @@ static void ddsi_tcp_node_free (void * ptr)
|
|||
static void ddsi_tcp_conn_connect (ddsi_tcp_conn_t conn, const struct msghdr * msg)
|
||||
{
|
||||
int ret;
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
os_socket sock;
|
||||
|
||||
ddsi_tcp_sock_new (&sock, 0);
|
||||
|
@ -226,7 +257,7 @@ static void ddsi_tcp_conn_connect (ddsi_tcp_conn_t conn, const struct msghdr * m
|
|||
}
|
||||
#endif
|
||||
|
||||
sockaddr_to_string_with_port(buff, (const os_sockaddr_storage *) msg->msg_name);
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), (const os_sockaddr_storage *) msg->msg_name);
|
||||
nn_log (LC_INFO, "%s connect socket %"PRIsock" port %u to %s\n", ddsi_name, sock, get_socket_port (sock), buff);
|
||||
|
||||
/* Also may need to receive on connection so add to waitset */
|
||||
|
@ -241,7 +272,7 @@ static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path)
|
|||
{
|
||||
const char * action = "added";
|
||||
ddsi_tcp_node_t node;
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
|
||||
os_atomic_inc32 (&conn->m_base.m_count);
|
||||
|
||||
|
@ -271,13 +302,13 @@ static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path)
|
|||
}
|
||||
}
|
||||
|
||||
sockaddr_to_string_with_port(buff, &conn->m_peer_addr);
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr);
|
||||
nn_log (LC_INFO, "%s cache %s %s socket %"PRIsock" to %s\n", ddsi_name, action, conn->m_base.m_server ? "server" : "client", conn->m_sock, buff);
|
||||
}
|
||||
|
||||
static void ddsi_tcp_cache_remove (ddsi_tcp_conn_t conn)
|
||||
{
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
ddsi_tcp_node_t node;
|
||||
ut_avlDPath_t path;
|
||||
|
||||
|
@ -285,7 +316,7 @@ static void ddsi_tcp_cache_remove (ddsi_tcp_conn_t conn)
|
|||
node = ut_avlLookupDPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn, &path);
|
||||
if (node)
|
||||
{
|
||||
sockaddr_to_string_with_port(buff, &conn->m_peer_addr);
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr);
|
||||
nn_log (LC_INFO, "%s cache removed socket %"PRIsock" to %s\n", ddsi_name, conn->m_sock, buff);
|
||||
ut_avlDeleteDPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, &path);
|
||||
ddsi_tcp_node_free (node);
|
||||
|
@ -393,7 +424,7 @@ static int err_is_AGAIN_or_WOULDBLOCK (int err)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len)
|
||||
static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc)
|
||||
{
|
||||
ddsi_tcp_conn_t tcp = (ddsi_tcp_conn_t) conn;
|
||||
ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, int * err) = ddsi_tcp_conn_read_plain;
|
||||
|
@ -416,6 +447,10 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s
|
|||
pos += (size_t) n;
|
||||
if (pos == len)
|
||||
{
|
||||
if (srcloc)
|
||||
{
|
||||
ddsi_ipaddr_to_loc(srcloc, &tcp->m_peer_addr, tcp->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6);
|
||||
}
|
||||
return (ssize_t) pos;
|
||||
}
|
||||
}
|
||||
|
@ -515,21 +550,49 @@ static ssize_t ddsi_tcp_block_write
|
|||
return (pos == sz) ? (ssize_t) pos : -1;
|
||||
}
|
||||
|
||||
static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const struct msghdr * msg, size_t len, uint32_t flags)
|
||||
static size_t iovlen_sum (size_t niov, const ddsi_iovec_t *iov)
|
||||
{
|
||||
size_t tot = 0;
|
||||
while (niov--) {
|
||||
tot += iov++->iov_len;
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
/* Turns out Darwin uses "int" for msg_iovlen, but glibc uses "size_t". The simplest
|
||||
way out is to do the assignment with the conversion warnings disabled */
|
||||
//OSPL_DIAG_OFF(conversion)
|
||||
static void set_msghdr_iov (struct msghdr *mhdr, ddsi_iovec_t *iov, size_t iovlen)
|
||||
{
|
||||
mhdr->msg_iov = iov;
|
||||
mhdr->msg_iovlen = iovlen;
|
||||
}
|
||||
//OSPL_DIAG_ON(conversion)
|
||||
|
||||
static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *dst, size_t niov, const ddsi_iovec_t *iov, uint32_t flags)
|
||||
{
|
||||
#ifdef DDSI_INCLUDE_SSL
|
||||
char msgbuf[4096]; /* stack buffer for merging smallish writes without requiring allocations */
|
||||
struct iovec iovec; /* iovec used for msgbuf */
|
||||
#endif
|
||||
struct msghdr msgcopy = *msg;
|
||||
ssize_t ret;
|
||||
size_t len;
|
||||
ddsi_tcp_conn_t conn;
|
||||
int piecewise;
|
||||
bool connect = false;
|
||||
|
||||
struct msghdr msg;
|
||||
os_sockaddr_storage dstaddr;
|
||||
assert(niov <= INT_MAX);
|
||||
ddsi_ipaddr_from_loc(&dstaddr, dst);
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
set_msghdr_iov (&msg, (ddsi_iovec_t *) iov, niov);
|
||||
msg.msg_name = &dstaddr;
|
||||
msg.msg_namelen = (socklen_t) os_sockaddrSizeof((os_sockaddr *) &dstaddr);
|
||||
msg.msg_flags = (int) flags;
|
||||
len = iovlen_sum (niov, iov);
|
||||
(void) base;
|
||||
|
||||
conn = ddsi_tcp_cache_find (msg);
|
||||
conn = ddsi_tcp_cache_find (&msg);
|
||||
if (conn == NULL)
|
||||
{
|
||||
return -1;
|
||||
|
@ -541,7 +604,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const struct msghdr *
|
|||
|
||||
if ((conn->m_sock == Q_INVALID_SOCKET) && ! conn->m_base.m_server)
|
||||
{
|
||||
ddsi_tcp_conn_connect (conn, msg);
|
||||
ddsi_tcp_conn_connect (conn, &msg);
|
||||
if (conn->m_sock == Q_INVALID_SOCKET)
|
||||
{
|
||||
os_mutexUnlock (&conn->m_mutex);
|
||||
|
@ -566,20 +629,20 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const struct msghdr *
|
|||
Rumor is that it is much better to merge small writes, which do here
|
||||
rather in than in SSL-specific code for simplicity - perhaps ought
|
||||
to move this copying into xpack_send */
|
||||
if (msg->msg_iovlen > 1)
|
||||
if (msg.msg_iovlen > 1)
|
||||
{
|
||||
int i;
|
||||
char * ptr;
|
||||
iovec.iov_len = len;
|
||||
iovec.iov_base = (len <= sizeof (msgbuf)) ? msgbuf : os_malloc (len);
|
||||
ptr = iovec.iov_base;
|
||||
for (i = 0; i < (int) msg->msg_iovlen; i++)
|
||||
for (i = 0; i < (int) msg.msg_iovlen; i++)
|
||||
{
|
||||
memcpy (ptr, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
|
||||
ptr += msg->msg_iov[i].iov_len;
|
||||
memcpy (ptr, msg.msg_iov[i].iov_base, msg.msg_iov[i].iov_len);
|
||||
ptr += msg.msg_iov[i].iov_len;
|
||||
}
|
||||
msgcopy.msg_iov = &iovec;
|
||||
msgcopy.msg_iovlen = 1;
|
||||
msg.msg_iov = &iovec;
|
||||
msg.msg_iovlen = 1;
|
||||
}
|
||||
piecewise = 1;
|
||||
ret = 0;
|
||||
|
@ -592,11 +655,11 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const struct msghdr *
|
|||
#ifdef MSG_NOSIGNAL
|
||||
sendflags |= MSG_NOSIGNAL;
|
||||
#endif
|
||||
msgcopy.msg_name = NULL;
|
||||
msgcopy.msg_namelen = 0;
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
do
|
||||
{
|
||||
ret = sendmsg (conn->m_sock, &msgcopy, sendflags);
|
||||
ret = sendmsg (conn->m_sock, &msg, sendflags);
|
||||
err = (ret == -1) ? os_getErrno () : 0;
|
||||
}
|
||||
while ((ret == -1) && (err == os_sockEINTR));
|
||||
|
@ -648,22 +711,22 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const struct msghdr *
|
|||
}
|
||||
#endif
|
||||
|
||||
assert (msgcopy.msg_iov[i].iov_len > 0);
|
||||
while (ret >= (ssize_t) msgcopy.msg_iov[i].iov_len)
|
||||
assert (msg.msg_iov[i].iov_len > 0);
|
||||
while (ret >= (ssize_t) msg.msg_iov[i].iov_len)
|
||||
{
|
||||
ret -= (ssize_t) msgcopy.msg_iov[i++].iov_len;
|
||||
ret -= (ssize_t) msg.msg_iov[i++].iov_len;
|
||||
}
|
||||
assert (i < (int) msgcopy.msg_iovlen);
|
||||
ret = ddsi_tcp_block_write (wr, conn, (const char *) msgcopy.msg_iov[i].iov_base + ret, msgcopy.msg_iov[i].iov_len - (size_t) ret);
|
||||
while (ret > 0 && ++i < (int) msgcopy.msg_iovlen)
|
||||
assert (i < (int) msg.msg_iovlen);
|
||||
ret = ddsi_tcp_block_write (wr, conn, (const char *) msg.msg_iov[i].iov_base + ret, msg.msg_iov[i].iov_len - (size_t) ret);
|
||||
while (ret > 0 && ++i < (int) msg.msg_iovlen)
|
||||
{
|
||||
ret = ddsi_tcp_block_write (wr, conn, msgcopy.msg_iov[i].iov_base, msgcopy.msg_iov[i].iov_len);
|
||||
ret = ddsi_tcp_block_write (wr, conn, msg.msg_iov[i].iov_base, msg.msg_iov[i].iov_len);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DDSI_INCLUDE_SSL
|
||||
/* If allocated memory for merging original fragments into a single buffer, free it */
|
||||
if (msgcopy.msg_iov == &iovec && iovec.iov_base != msgbuf)
|
||||
if (msg.msg_iov == &iovec && iovec.iov_base != msgbuf)
|
||||
{
|
||||
os_free (iovec.iov_base);
|
||||
}
|
||||
|
@ -688,16 +751,16 @@ static bool ddsi_tcp_supports (int32_t kind)
|
|||
{
|
||||
return
|
||||
(
|
||||
(!config.useIpv6 && (kind == NN_LOCATOR_KIND_TCPv4))
|
||||
(config.transport_selector == TRANS_TCP && kind == NN_LOCATOR_KIND_TCPv4)
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
|| (config.useIpv6 && (kind == NN_LOCATOR_KIND_TCPv6))
|
||||
|| (config.transport_selector == TRANS_TCP6 && kind == NN_LOCATOR_KIND_TCPv6)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
static int ddsi_tcp_locator (ddsi_tran_base_t base, nn_locator_t *loc)
|
||||
{
|
||||
nn_address_to_loc (loc, &gv.extip, ddsi_tcp_factory_g.m_kind);
|
||||
*loc = gv.extloc;
|
||||
loc->port = base->m_port;
|
||||
return 0;
|
||||
}
|
||||
|
@ -732,7 +795,7 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener)
|
|||
os_socket sock = Q_INVALID_SOCKET;
|
||||
os_sockaddr_storage addr;
|
||||
socklen_t addrlen = sizeof (addr);
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
int err = 0;
|
||||
#ifdef DDSI_INCLUDE_SSL
|
||||
SSL * ssl = NULL;
|
||||
|
@ -763,7 +826,7 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener)
|
|||
if (sock == Q_INVALID_SOCKET)
|
||||
{
|
||||
getsockname (tl->m_sock, (struct sockaddr *) &addr, &addrlen);
|
||||
sockaddr_to_string_with_port(buff, &addr);
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), &addr);
|
||||
nn_log ((err == 0) ? LC_ERROR : LC_FATAL, "%s accept failed on socket %"PRIsock" at %s errno %d\n", ddsi_name, tl->m_sock, buff, err);
|
||||
}
|
||||
else if (getpeername (sock, (struct sockaddr *) &addr, &addrlen) == -1)
|
||||
|
@ -773,7 +836,7 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener)
|
|||
}
|
||||
else
|
||||
{
|
||||
sockaddr_to_string_with_port(buff, &addr);
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), &addr);
|
||||
nn_log (LC_INFO, "%s accept new socket %"PRIsock" on socket %"PRIsock" from %s\n", ddsi_name, sock, tl->m_sock, buff);
|
||||
|
||||
os_sockSetNonBlocking (sock, true);
|
||||
|
@ -807,15 +870,12 @@ static os_handle ddsi_tcp_listener_handle (ddsi_tran_base_t base)
|
|||
|
||||
static void ddsi_tcp_conn_peer_locator (ddsi_tran_conn_t conn, nn_locator_t * loc)
|
||||
{
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
ddsi_tcp_conn_t tc = (ddsi_tcp_conn_t) conn;
|
||||
|
||||
assert (tc->m_base.m_server);
|
||||
assert (tc->m_sock != Q_INVALID_SOCKET);
|
||||
|
||||
sockaddr_to_string_with_port(buff, &tc->m_peer_addr);
|
||||
ddsi_ipaddr_to_loc (loc, &tc->m_peer_addr, tc->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6);
|
||||
ddsi_locator_to_string(buff, sizeof(buff), loc);
|
||||
TRACE (("(%s EP:%s)", ddsi_name, buff));
|
||||
nn_address_to_loc (loc, &tc->m_peer_addr, tc->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6);
|
||||
}
|
||||
|
||||
static void ddsi_tcp_base_init (struct ddsi_tran_conn * base)
|
||||
|
@ -848,7 +908,7 @@ static ddsi_tcp_conn_t ddsi_tcp_new_conn (os_socket sock, bool server, os_sockad
|
|||
|
||||
static ddsi_tran_listener_t ddsi_tcp_create_listener (int port, ddsi_tran_qos_t qos)
|
||||
{
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
os_socket sock;
|
||||
os_sockaddr_storage addr;
|
||||
socklen_t addrlen = sizeof (addr);
|
||||
|
@ -876,13 +936,14 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (int port, ddsi_tran_qos_t
|
|||
|
||||
if (getsockname (sock, (os_sockaddr *) &addr, &addrlen) == -1)
|
||||
{
|
||||
print_sockerror ("ddsi_tcp_create_listener: getsockname");
|
||||
int err = os_getErrno ();
|
||||
NN_ERROR ("ddsi_tcp_create_listener: getsockname errno %d\n", err);
|
||||
ddsi_tcp_sock_free (sock, NULL);
|
||||
os_free (tl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sockaddr_to_string_with_port(buff, &addr);
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), &addr);
|
||||
nn_log (LC_INFO, "%s create listener socket %"PRIsock" on %s\n", ddsi_name, sock, buff);
|
||||
}
|
||||
|
||||
|
@ -891,8 +952,8 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (int port, ddsi_tran_qos_t
|
|||
|
||||
static void ddsi_tcp_conn_delete (ddsi_tcp_conn_t conn)
|
||||
{
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
sockaddr_to_string_with_port(buff, &conn->m_peer_addr);
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr);
|
||||
nn_log (LC_INFO, "%s free %s connnection on socket %"PRIsock" to %s\n", ddsi_name, conn->m_base.m_server ? "server" : "client", conn->m_sock, buff);
|
||||
|
||||
#ifdef DDSI_INCLUDE_SSL
|
||||
|
@ -913,13 +974,13 @@ static void ddsi_tcp_close_conn (ddsi_tran_conn_t tc)
|
|||
{
|
||||
if (tc != (ddsi_tran_conn_t) &ddsi_tcp_conn_client)
|
||||
{
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
nn_locator_t loc;
|
||||
ddsi_tcp_conn_t conn = (ddsi_tcp_conn_t) tc;
|
||||
sockaddr_to_string_with_port(buff, &conn->m_peer_addr);
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), &conn->m_peer_addr);
|
||||
nn_log (LC_INFO, "%s close %s connnection on socket %"PRIsock" to %s\n", ddsi_name, conn->m_base.m_server ? "server" : "client", conn->m_sock, buff);
|
||||
(void) shutdown (conn->m_sock, 2);
|
||||
nn_address_to_loc(&loc, &conn->m_peer_addr, conn->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6);
|
||||
ddsi_ipaddr_to_loc(&loc, &conn->m_peer_addr, conn->m_peer_addr.ss_family == AF_INET ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_TCPv6);
|
||||
loc.port = conn->m_peer_port;
|
||||
purge_proxy_participants (&loc, conn->m_base.m_server);
|
||||
}
|
||||
|
@ -983,8 +1044,8 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener)
|
|||
while ((ret == -1) && (os_getErrno() == os_sockEINTR));
|
||||
if (ret == -1)
|
||||
{
|
||||
char buff[INET6_ADDRSTRLEN_EXTENDED];
|
||||
sockaddr_to_string_with_port(buff, &addr);
|
||||
char buff[DDSI_LOCSTRLEN];
|
||||
sockaddr_to_string_with_port(buff, sizeof(buff), &addr);
|
||||
nn_log (LC_WARNING, "%s failed to connect to own listener (%s) error %d\n", ddsi_name, buff, os_getErrno());
|
||||
}
|
||||
}
|
||||
|
@ -1011,6 +1072,11 @@ static void ddsi_tcp_release_factory (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static enum ddsi_locator_from_string_result ddsi_tcp_address_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str)
|
||||
{
|
||||
return ddsi_ipaddr_from_string(tran, loc, str, ddsi_tcp_factory_g.m_kind);
|
||||
}
|
||||
|
||||
int ddsi_tcp_init (void)
|
||||
{
|
||||
static bool init = false;
|
||||
|
@ -1029,14 +1095,15 @@ int ddsi_tcp_init (void)
|
|||
ddsi_tcp_factory_g.m_unblock_listener_fn = ddsi_tcp_unblock_listener;
|
||||
ddsi_tcp_factory_g.m_release_listener_fn = ddsi_tcp_release_listener;
|
||||
ddsi_tcp_factory_g.m_free_fn = ddsi_tcp_release_factory;
|
||||
ddsi_tcp_factory_g.m_join_mc_fn = 0;
|
||||
ddsi_tcp_factory_g.m_leave_mc_fn = 0;
|
||||
ddsi_tcp_factory_g.m_locator_from_string_fn = ddsi_tcp_address_from_string;
|
||||
ddsi_tcp_factory_g.m_locator_to_string_fn = ddsi_ipaddr_to_string;
|
||||
ddsi_factory_add (&ddsi_tcp_factory_g);
|
||||
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
if (config.transport_selector == TRANS_TCP6)
|
||||
{
|
||||
ddsi_tcp_factory_g.m_kind = NN_LOCATOR_KIND_TCPv6;
|
||||
ddsi_tcp_factory_g.m_typename = "tcp6";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "os/os.h"
|
||||
#include "ddsi/ddsi_tran.h"
|
||||
#include "ddsi/q_config.h"
|
||||
|
@ -26,6 +27,7 @@ void ddsi_factory_add (ddsi_tran_factory_t factory)
|
|||
|
||||
ddsi_tran_factory_t ddsi_factory_find (const char * type)
|
||||
{
|
||||
/* FIXME: should speed up */
|
||||
ddsi_tran_factory_t factory = ddsi_tran_factories;
|
||||
|
||||
while (factory)
|
||||
|
@ -51,6 +53,35 @@ void ddsi_tran_factories_fini (void)
|
|||
}
|
||||
}
|
||||
|
||||
static ddsi_tran_factory_t ddsi_factory_find_with_len (const char * type, size_t len)
|
||||
{
|
||||
/* FIXME: should speed up */
|
||||
ddsi_tran_factory_t factory = ddsi_tran_factories;
|
||||
|
||||
while (factory)
|
||||
{
|
||||
if (strncmp (factory->m_typename, type, len) == 0 && factory->m_typename[len] == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
factory = factory->m_factory;
|
||||
}
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
ddsi_tran_factory_t ddsi_factory_find_supported_kind (int32_t kind)
|
||||
{
|
||||
/* FIXME: MUST speed up */
|
||||
ddsi_tran_factory_t factory;
|
||||
for (factory = ddsi_tran_factories; factory; factory = factory->m_factory) {
|
||||
if (factory->m_supports_fn(kind)) {
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ddsi_factory_free (ddsi_tran_factory_t factory)
|
||||
{
|
||||
if (factory && factory->m_free_fn)
|
||||
|
@ -83,7 +114,7 @@ void ddsi_conn_add_ref (ddsi_tran_conn_t conn)
|
|||
os_atomic_inc32 (&conn->m_count);
|
||||
}
|
||||
|
||||
extern void ddsi_factory_conn_init (ddsi_tran_factory_t factory, ddsi_tran_conn_t conn)
|
||||
void ddsi_factory_conn_init (ddsi_tran_factory_t factory, ddsi_tran_conn_t conn)
|
||||
{
|
||||
os_atomic_st32 (&conn->m_count, 1);
|
||||
conn->m_connless = factory->m_connless;
|
||||
|
@ -91,22 +122,29 @@ extern void ddsi_factory_conn_init (ddsi_tran_factory_t factory, ddsi_tran_conn_
|
|||
conn->m_factory = factory;
|
||||
}
|
||||
|
||||
ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len)
|
||||
ssize_t ddsi_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc)
|
||||
{
|
||||
return (conn->m_closed) ? -1 : (conn->m_read_fn) (conn, buf, len);
|
||||
return (conn->m_closed) ? -1 : (conn->m_read_fn) (conn, buf, len, srcloc);
|
||||
}
|
||||
|
||||
ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const struct msghdr * msg, size_t len, uint32_t flags)
|
||||
ssize_t ddsi_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const ddsi_iovec_t *iov, uint32_t flags)
|
||||
{
|
||||
ssize_t ret = -1;
|
||||
if (! conn->m_closed)
|
||||
{
|
||||
ret = (conn->m_write_fn) (conn, msg, len, flags);
|
||||
ret = (conn->m_write_fn) (conn, dst, niov, iov, flags);
|
||||
}
|
||||
|
||||
/* Check that write function is atomic (all or nothing) */
|
||||
|
||||
assert (ret == -1 || (size_t) ret == len);
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
size_t i, len;
|
||||
for (i = 0, len = 0; i < niov; i++) {
|
||||
len += iov[i].iov_len;
|
||||
}
|
||||
assert (ret == -1 || (size_t) ret == len);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -125,14 +163,14 @@ void ddsi_tran_free_qos (ddsi_tran_qos_t qos)
|
|||
os_free (qos);
|
||||
}
|
||||
|
||||
int ddsi_conn_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
int ddsi_conn_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
return conn->m_factory->m_join_mc_fn (conn, srcloc, mcloc);
|
||||
return conn->m_factory->m_join_mc_fn (conn, srcloc, mcloc, interf);
|
||||
}
|
||||
|
||||
int ddsi_conn_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
int ddsi_conn_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
return conn->m_factory->m_leave_mc_fn (conn, srcloc, mcloc);
|
||||
return conn->m_factory->m_leave_mc_fn (conn, srcloc, mcloc, interf);
|
||||
}
|
||||
|
||||
os_handle ddsi_tran_handle (ddsi_tran_base_t base)
|
||||
|
@ -204,3 +242,78 @@ void ddsi_listener_free (ddsi_tran_listener_t listener)
|
|||
(listener->m_factory->m_release_listener_fn) (listener);
|
||||
}
|
||||
}
|
||||
|
||||
int ddsi_is_mcaddr (const nn_locator_t *loc)
|
||||
{
|
||||
/* FIXME: should set m_is_mcaddr_fn to a function returning false if transport doesn't provide an implementation, and get rid of the test */
|
||||
ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(loc->kind);
|
||||
return tran->m_is_mcaddr_fn ? tran->m_is_mcaddr_fn (tran, loc) : 0;
|
||||
}
|
||||
|
||||
int ddsi_is_ssm_mcaddr (const nn_locator_t *loc)
|
||||
{
|
||||
ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(loc->kind);
|
||||
return tran->m_is_ssm_mcaddr_fn ? tran->m_is_ssm_mcaddr_fn (tran, loc) : 0;
|
||||
}
|
||||
|
||||
enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[])
|
||||
{
|
||||
ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(loc->kind);
|
||||
return tran->m_is_nearby_address_fn ? tran->m_is_nearby_address_fn (tran, loc, ninterf, interf) : DNAR_DISTANT;
|
||||
}
|
||||
|
||||
enum ddsi_locator_from_string_result ddsi_locator_from_string (nn_locator_t *loc, const char *str)
|
||||
{
|
||||
const char *sep = strchr(str, '/');
|
||||
ddsi_tran_factory_t tran;
|
||||
if (sep == str) {
|
||||
return AFSR_INVALID;
|
||||
} else if (sep > str) {
|
||||
const char *cur = sep;
|
||||
while (cur-- > str)
|
||||
if (!isalnum((unsigned char)*cur) && *cur != '_')
|
||||
return AFSR_INVALID;
|
||||
tran = ddsi_factory_find_with_len(str, (size_t)(sep - str));
|
||||
if (tran == NULL)
|
||||
return AFSR_UNKNOWN;
|
||||
} else {
|
||||
/* FIXME: am I happy with defaulting it like this? */
|
||||
tran = gv.m_factory;
|
||||
}
|
||||
return tran->m_locator_from_string_fn (tran, loc, sep ? sep + 1 : str);
|
||||
}
|
||||
|
||||
char *ddsi_locator_to_string (char *dst, size_t sizeof_dst, const nn_locator_t *loc)
|
||||
{
|
||||
/* FIXME: should add a "factory" for INVALID locators */
|
||||
if (loc->kind != NN_LOCATOR_KIND_INVALID) {
|
||||
ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(loc->kind);
|
||||
int pos = snprintf (dst, sizeof_dst, "%s/", tran->m_typename);
|
||||
if (0 < pos && (size_t)pos < sizeof_dst)
|
||||
(void) tran->m_locator_to_string_fn (tran, dst + (size_t)pos, sizeof_dst - (size_t)pos, loc, 1);
|
||||
} else {
|
||||
snprintf (dst, sizeof_dst, "invalid/0:0");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *ddsi_locator_to_string_no_port (char *dst, size_t sizeof_dst, const nn_locator_t *loc)
|
||||
{
|
||||
if (loc->kind != NN_LOCATOR_KIND_INVALID) {
|
||||
ddsi_tran_factory_t tran = ddsi_factory_find_supported_kind(loc->kind);
|
||||
int pos = snprintf (dst, sizeof_dst, "%s/", tran->m_typename);
|
||||
if (0 < pos && (size_t)pos < sizeof_dst)
|
||||
(void) tran->m_locator_to_string_fn (tran, dst + (size_t)pos, sizeof_dst - (size_t)pos, loc, 0);
|
||||
} else {
|
||||
snprintf (dst, sizeof_dst, "invalid/0");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
int ddsi_enumerate_interfaces (ddsi_tran_factory_t factory, int max, struct os_ifAttributes_s *interfs)
|
||||
{
|
||||
/* FIXME: HACK */
|
||||
if (factory->m_enumerate_interfaces_fn == 0)
|
||||
return 0;
|
||||
return factory->m_enumerate_interfaces_fn (factory, max, interfs);
|
||||
}
|
||||
|
|
|
@ -12,8 +12,11 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "os/os.h"
|
||||
#include "os/os_atomics.h"
|
||||
#include "ddsi/ddsi_tran.h"
|
||||
#include "ddsi/ddsi_udp.h"
|
||||
#include "ddsi/ddsi_ipaddr.h"
|
||||
#include "ddsi/ddsi_mcgroup.h"
|
||||
#include "ddsi/q_nwif.h"
|
||||
#include "ddsi/q_config.h"
|
||||
#include "ddsi/q_log.h"
|
||||
|
@ -44,7 +47,7 @@ static struct ddsi_udp_config ddsi_udp_config_g;
|
|||
static struct ddsi_tran_factory ddsi_udp_factory_g;
|
||||
static os_atomic_uint32_t ddsi_udp_init_g = OS_ATOMIC_UINT32_INIT(0);
|
||||
|
||||
static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len)
|
||||
static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, size_t len, nn_locator_t *srcloc)
|
||||
{
|
||||
int err;
|
||||
ssize_t ret;
|
||||
|
@ -70,6 +73,9 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s
|
|||
|
||||
if (ret > 0)
|
||||
{
|
||||
if (srcloc)
|
||||
ddsi_ipaddr_to_loc(srcloc, &src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6);
|
||||
|
||||
/* Check for udp packet truncation */
|
||||
if ((((size_t) ret) > len)
|
||||
#if SYSDEPS_MSGHDR_FLAGS
|
||||
|
@ -77,8 +83,10 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s
|
|||
#endif
|
||||
)
|
||||
{
|
||||
char addrbuf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
sockaddr_to_string_with_port (addrbuf, &src);
|
||||
char addrbuf[DDSI_LOCSTRLEN];
|
||||
nn_locator_t tmp;
|
||||
ddsi_ipaddr_to_loc(&tmp, &src, src.ss_family == AF_INET ? NN_LOCATOR_KIND_UDPv4 : NN_LOCATOR_KIND_UDPv6);
|
||||
ddsi_locator_to_string(addrbuf, sizeof(addrbuf), &tmp);
|
||||
NN_WARNING ("%s => %d truncated to %d\n", addrbuf, (int)ret, (int)len);
|
||||
}
|
||||
}
|
||||
|
@ -89,20 +97,37 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const struct msghdr * msg, size_t len, uint32_t flags)
|
||||
/* Turns out Darwin uses "int" for msg_iovlen, but glibc uses "size_t". The simplest
|
||||
way out is to do the assignment with the conversion warnings disabled */
|
||||
//OSPL_DIAG_OFF(conversion)
|
||||
static void set_msghdr_iov (struct msghdr *mhdr, ddsi_iovec_t *iov, size_t iovlen)
|
||||
{
|
||||
mhdr->msg_iov = iov;
|
||||
mhdr->msg_iovlen = iovlen;
|
||||
}
|
||||
//OSPL_DIAG_ON(conversion)
|
||||
|
||||
static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, const ddsi_iovec_t *iov, uint32_t flags)
|
||||
{
|
||||
int err;
|
||||
ssize_t ret;
|
||||
unsigned retry = 2;
|
||||
int sendflags = 0;
|
||||
(void) flags;
|
||||
(void) len;
|
||||
struct msghdr msg;
|
||||
os_sockaddr_storage dstaddr;
|
||||
assert(niov <= INT_MAX);
|
||||
ddsi_ipaddr_from_loc(&dstaddr, dst);
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
set_msghdr_iov (&msg, (ddsi_iovec_t *) iov, niov);
|
||||
msg.msg_name = &dstaddr;
|
||||
msg.msg_namelen = (socklen_t) os_sockaddrSizeof((os_sockaddr *) &dstaddr);
|
||||
msg.msg_flags = (int) flags;
|
||||
#ifdef MSG_NOSIGNAL
|
||||
sendflags |= MSG_NOSIGNAL;
|
||||
#endif
|
||||
do {
|
||||
ddsi_udp_conn_t uc = (ddsi_udp_conn_t) conn;
|
||||
ret = sendmsg (uc->m_sock, msg, sendflags);
|
||||
ret = sendmsg (uc->m_sock, &msg, sendflags);
|
||||
err = (ret == -1) ? os_getErrno() : 0;
|
||||
#if defined _WIN32 && !defined WINCE
|
||||
if (err == os_sockEWOULDBLOCK) {
|
||||
|
@ -118,7 +143,7 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const struct msghdr *
|
|||
socklen_t alen = sizeof (sa);
|
||||
if (getsockname (((ddsi_udp_conn_t) conn)->m_sock, (struct sockaddr *) &sa, &alen) == -1)
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
write_pcap_sent (gv.pcap_fp, now (), &sa, msg, (size_t) ret);
|
||||
write_pcap_sent (gv.pcap_fp, now (), &sa, &msg, (size_t) ret);
|
||||
}
|
||||
else if (ret == -1)
|
||||
{
|
||||
|
@ -149,9 +174,9 @@ static bool ddsi_udp_supports (int32_t kind)
|
|||
{
|
||||
return
|
||||
(
|
||||
(!config.useIpv6 && (kind == NN_LOCATOR_KIND_UDPv4))
|
||||
(config.transport_selector == TRANS_UDP && (kind == NN_LOCATOR_KIND_UDPv4 || kind == NN_LOCATOR_KIND_UDPv4MCGEN))
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
|| (config.useIpv6 && (kind == NN_LOCATOR_KIND_UDPv6))
|
||||
|| (config.transport_selector == TRANS_UDP6 && kind == NN_LOCATOR_KIND_UDPv6)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
@ -160,27 +185,39 @@ static int ddsi_udp_conn_locator (ddsi_tran_base_t base, nn_locator_t *loc)
|
|||
{
|
||||
int ret = -1;
|
||||
ddsi_udp_conn_t uc = (ddsi_udp_conn_t) base;
|
||||
os_sockaddr_storage * addr = &gv.extip;
|
||||
|
||||
memset (loc, 0, sizeof (*loc));
|
||||
if (uc->m_sock != Q_INVALID_SOCKET)
|
||||
{
|
||||
loc->kind = ddsi_udp_factory_g.m_kind;
|
||||
loc->port = uc->m_base.m_base.m_port;
|
||||
|
||||
if (loc->kind == NN_LOCATOR_KIND_UDPv4)
|
||||
{
|
||||
memcpy (loc->address + 12, &((os_sockaddr_in*) addr)->sin_addr, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (loc->address, &((os_sockaddr_in6*) addr)->sin6_addr, 16);
|
||||
}
|
||||
memcpy(loc->address, gv.extloc.address, sizeof (loc->address));
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned short sockaddr_get_port (const os_sockaddr_storage *addr)
|
||||
{
|
||||
if (addr->ss_family == AF_INET)
|
||||
return ntohs (((os_sockaddr_in *) addr)->sin_port);
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
else
|
||||
return ntohs (((os_sockaddr_in6 *) addr)->sin6_port);
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned short get_socket_port (os_socket socket)
|
||||
{
|
||||
os_sockaddr_storage addr;
|
||||
socklen_t addrlen = sizeof (addr);
|
||||
if (getsockname (socket, (os_sockaddr *) &addr, &addrlen) < 0)
|
||||
{
|
||||
int err = os_getErrno();
|
||||
NN_ERROR ("ddsi_udp_get_socket_port: getsockname errno %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
return sockaddr_get_port(&addr);
|
||||
}
|
||||
|
||||
static ddsi_tran_conn_t ddsi_udp_create_conn
|
||||
(
|
||||
uint32_t port,
|
||||
|
@ -235,7 +272,11 @@ static ddsi_tran_conn_t ddsi_udp_create_conn
|
|||
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
|
||||
if ((uc->m_diffserv != 0) && (ddsi_udp_factory_g.m_kind == NN_LOCATOR_KIND_UDPv4))
|
||||
{
|
||||
set_socket_diffserv (uc->m_sock, uc->m_diffserv);
|
||||
if (os_sockSetsockopt (sock, IPPROTO_IP, IP_TOS, (char*) &uc->m_diffserv, sizeof (uc->m_diffserv)) != os_resultSuccess)
|
||||
{
|
||||
int err = os_getErrno();
|
||||
NN_ERROR("ddsi_udp_create_conn: set diffserv error %d\n", err);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -255,24 +296,90 @@ static ddsi_tran_conn_t ddsi_udp_create_conn
|
|||
return uc ? &uc->m_base : NULL;
|
||||
}
|
||||
|
||||
static int ddsi_udp_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
static int joinleave_asm_mcgroup (os_socket socket, int join, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
ddsi_udp_conn_t uc = (ddsi_udp_conn_t) conn;
|
||||
os_sockaddr_storage mcip, srcip;
|
||||
nn_loc_to_address (&mcip, mcloc);
|
||||
if (srcloc)
|
||||
nn_loc_to_address (&srcip, srcloc);
|
||||
return join_mcgroups (ddsi_udp_config_g.mship, uc->m_sock, srcloc ? &srcip : NULL, &mcip);
|
||||
int rc;
|
||||
os_sockaddr_storage mcip;
|
||||
ddsi_ipaddr_from_loc(&mcip, mcloc);
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.transport_selector == TRANS_UDP6)
|
||||
{
|
||||
os_ipv6_mreq ipv6mreq;
|
||||
memset (&ipv6mreq, 0, sizeof (ipv6mreq));
|
||||
memcpy (&ipv6mreq.ipv6mr_multiaddr, &((os_sockaddr_in6 *) &mcloc)->sin6_addr, sizeof (ipv6mreq.ipv6mr_multiaddr));
|
||||
ipv6mreq.ipv6mr_interface = interf ? interf->if_index : 0;
|
||||
rc = os_sockSetsockopt (socket, IPPROTO_IPV6, join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, &ipv6mreq, sizeof (ipv6mreq));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr = ((os_sockaddr_in *) &mcip)->sin_addr;
|
||||
if (interf)
|
||||
memcpy (&mreq.imr_interface, interf->loc.address + 12, sizeof (mreq.imr_interface));
|
||||
else
|
||||
mreq.imr_interface.s_addr = htonl (INADDR_ANY);
|
||||
rc = os_sockSetsockopt (socket, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof (mreq));
|
||||
}
|
||||
return (rc == -1) ? os_getErrno() : 0;
|
||||
}
|
||||
|
||||
static int ddsi_udp_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc)
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
static int joinleave_ssm_mcgroup (os_socket socket, int join, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
int rc;
|
||||
os_sockaddr_storage mcip, srcip;
|
||||
ddsi_ipaddr_from_loc(&mcip, mcloc);
|
||||
ddsi_ipaddr_from_loc(&srcip, srcloc);
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.transport_selector == TRANS_UDP6)
|
||||
{
|
||||
struct group_source_req gsr;
|
||||
memset (&gsr, 0, sizeof (gsr));
|
||||
gsr.gsr_interface = interf ? interf->if_index : 0;
|
||||
memcpy (&gsr.gsr_group, &mcip, sizeof (gsr.gsr_group));
|
||||
memcpy (&gsr.gsr_source, &srcip, sizeof (gsr.gsr_source));
|
||||
rc = os_sockSetsockopt (socket, IPPROTO_IPV6, join ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP, &gsr, sizeof (gsr));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct ip_mreq_source mreq;
|
||||
memset (&mreq, 0, sizeof (mreq));
|
||||
mreq.imr_sourceaddr = ((os_sockaddr_in *) &srcip)->sin_addr;
|
||||
mreq.imr_multiaddr = ((os_sockaddr_in *) &mcip)->sin_addr;
|
||||
if (interf)
|
||||
memcpy (&mreq.imr_interface, interf->loc.address + 12, sizeof (mreq.imr_interface));
|
||||
else
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
rc = os_sockSetsockopt (socket, IPPROTO_IP, join ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP, &mreq, sizeof (mreq));
|
||||
}
|
||||
return (rc == -1) ? os_getErrno() : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ddsi_udp_join_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
ddsi_udp_conn_t uc = (ddsi_udp_conn_t) conn;
|
||||
os_sockaddr_storage mcip, srcip;
|
||||
nn_loc_to_address (&mcip, mcloc);
|
||||
(void)srcloc;
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
if (srcloc)
|
||||
nn_loc_to_address (&srcip, srcloc);
|
||||
return leave_mcgroups (ddsi_udp_config_g.mship, uc->m_sock, srcloc ? &srcip : NULL, &mcip);
|
||||
return joinleave_ssm_mcgroup(uc->m_sock, 1, srcloc, mcloc, interf);
|
||||
else
|
||||
#endif
|
||||
return joinleave_asm_mcgroup(uc->m_sock, 1, mcloc, interf);
|
||||
}
|
||||
|
||||
static int ddsi_udp_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc, const struct nn_interface *interf)
|
||||
{
|
||||
ddsi_udp_conn_t uc = (ddsi_udp_conn_t) conn;
|
||||
(void)srcloc;
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
if (srcloc)
|
||||
return joinleave_ssm_mcgroup(uc->m_sock, 0, srcloc, mcloc, interf);
|
||||
else
|
||||
#endif
|
||||
return joinleave_asm_mcgroup(uc->m_sock, 0, mcloc, interf);
|
||||
}
|
||||
|
||||
static void ddsi_udp_release_conn (ddsi_tran_conn_t conn)
|
||||
|
@ -302,6 +409,96 @@ void ddsi_udp_fini (void)
|
|||
}
|
||||
}
|
||||
|
||||
static int ddsi_udp_is_mcaddr (const ddsi_tran_factory_t tran, const nn_locator_t *loc)
|
||||
{
|
||||
(void) tran;
|
||||
switch (loc->kind)
|
||||
{
|
||||
case NN_LOCATOR_KIND_UDPv4: {
|
||||
const struct in_addr *ipv4 = (const struct in_addr *) (loc->address + 12);
|
||||
return IN_MULTICAST (ntohl (ipv4->s_addr));
|
||||
}
|
||||
case NN_LOCATOR_KIND_UDPv4MCGEN: {
|
||||
const nn_udpv4mcgen_address_t *mcgen = (const nn_udpv4mcgen_address_t *) loc->address;
|
||||
return IN_MULTICAST (ntohl (mcgen->ipv4.s_addr));
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case NN_LOCATOR_KIND_UDPv6: {
|
||||
const struct in6_addr *ipv6 = (const struct in6_addr *) loc->address;
|
||||
return IN6_IS_ADDR_MULTICAST (ipv6);
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
static int ddsi_udp_is_ssm_mcaddr (const ddsi_tran_factory_t tran, const nn_locator_t *loc)
|
||||
{
|
||||
(void) tran;
|
||||
switch (loc->kind)
|
||||
{
|
||||
case NN_LOCATOR_KIND_UDPv4: {
|
||||
const struct in_addr *x = (const struct in_addr *) (loc->address + 12);
|
||||
return (((uint32_t) ntohl (x->s_addr)) >> 24) == 232;
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case NN_LOCATOR_KIND_UDPv6: {
|
||||
const struct in6_addr *x = (const struct in6_addr *) loc->address;
|
||||
return x->s6_addr[0] == 0xff && (x->s6_addr[1] & 0xf0) == 0x30;
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum ddsi_locator_from_string_result ddsi_udp_address_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str)
|
||||
{
|
||||
return ddsi_ipaddr_from_string(tran, loc, str, ddsi_udp_factory_g.m_kind);
|
||||
}
|
||||
|
||||
static char *ddsi_udp_locator_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port)
|
||||
{
|
||||
if (loc->kind != NN_LOCATOR_KIND_UDPv4MCGEN) {
|
||||
return ddsi_ipaddr_to_string(tran, dst, sizeof_dst, loc, with_port);
|
||||
} else {
|
||||
os_sockaddr_in src;
|
||||
nn_udpv4mcgen_address_t mcgen;
|
||||
size_t pos;
|
||||
int cnt;
|
||||
assert(sizeof_dst > 1);
|
||||
memcpy (&mcgen, loc->address, sizeof (mcgen));
|
||||
memset (&src, 0, sizeof (src));
|
||||
src.sin_family = AF_INET;
|
||||
memcpy (&src.sin_addr.s_addr, &mcgen.ipv4, 4);
|
||||
os_sockaddrAddressToString ((const os_sockaddr *) &src, dst, sizeof_dst);
|
||||
pos = strlen (dst);
|
||||
assert (pos <= sizeof_dst);
|
||||
cnt = snprintf (dst + pos, sizeof_dst - pos, ";%u;%u;%u", mcgen.base, mcgen.count, mcgen.idx);
|
||||
if (cnt > 0) {
|
||||
pos += (size_t)cnt;
|
||||
}
|
||||
if (with_port && pos < sizeof_dst) {
|
||||
snprintf (dst + pos, sizeof_dst - pos, ":%d", loc->port);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
}
|
||||
|
||||
static void ddsi_udp_deinit(void)
|
||||
{
|
||||
if (os_atomic_dec32_nv(&ddsi_udp_init_g) == 0) {
|
||||
if (ddsi_udp_config_g.mship)
|
||||
free_group_membership(ddsi_udp_config_g.mship);
|
||||
nn_log (LC_INFO | LC_CONFIG, "udp de-initialized\n");
|
||||
}
|
||||
}
|
||||
|
||||
int ddsi_udp_init (void)
|
||||
{
|
||||
/* TODO: proper init_once. Either the call doesn't need it, in which case
|
||||
|
@ -311,8 +508,10 @@ int ddsi_udp_init (void)
|
|||
if (os_atomic_inc32_nv (&ddsi_udp_init_g) == 1)
|
||||
{
|
||||
memset (&ddsi_udp_factory_g, 0, sizeof (ddsi_udp_factory_g));
|
||||
ddsi_udp_factory_g.m_free_fn = ddsi_udp_deinit;
|
||||
ddsi_udp_factory_g.m_kind = NN_LOCATOR_KIND_UDPv4;
|
||||
ddsi_udp_factory_g.m_typename = "udp";
|
||||
ddsi_udp_factory_g.m_default_spdp_address = "udp/239.255.0.1";
|
||||
ddsi_udp_factory_g.m_connless = true;
|
||||
ddsi_udp_factory_g.m_supports_fn = ddsi_udp_supports;
|
||||
ddsi_udp_factory_g.m_create_conn_fn = ddsi_udp_create_conn;
|
||||
|
@ -320,10 +519,19 @@ int ddsi_udp_init (void)
|
|||
ddsi_udp_factory_g.m_free_fn = ddsi_udp_fini;
|
||||
ddsi_udp_factory_g.m_join_mc_fn = ddsi_udp_join_mc;
|
||||
ddsi_udp_factory_g.m_leave_mc_fn = ddsi_udp_leave_mc;
|
||||
ddsi_udp_factory_g.m_is_mcaddr_fn = ddsi_udp_is_mcaddr;
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
ddsi_udp_factory_g.m_is_ssm_mcaddr_fn = ddsi_udp_is_ssm_mcaddr;
|
||||
#endif
|
||||
ddsi_udp_factory_g.m_is_nearby_address_fn = ddsi_ipaddr_is_nearby_address;
|
||||
ddsi_udp_factory_g.m_locator_from_string_fn = ddsi_udp_address_from_string;
|
||||
ddsi_udp_factory_g.m_locator_to_string_fn = ddsi_udp_locator_to_string;
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
if (config.transport_selector == TRANS_UDP6)
|
||||
{
|
||||
ddsi_udp_factory_g.m_kind = NN_LOCATOR_KIND_UDPv6;
|
||||
ddsi_udp_factory_g.m_typename = "udp6";
|
||||
ddsi_udp_factory_g.m_default_spdp_address = "udp6/ff02::ffff:239.255.0.1";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -42,28 +42,25 @@ static const ut_avlCTreedef_t addrset_treedef =
|
|||
|
||||
static int add_addresses_to_addrset_1 (struct addrset *as, const char *ip, int port_mode, const char *msgtag, int req_mc, int mcgen_base, int mcgen_count, int mcgen_idx)
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
os_sockaddr_storage tmpaddr;
|
||||
char buf[DDSI_LOCSTRLEN];
|
||||
nn_locator_t loc;
|
||||
int32_t kind;
|
||||
|
||||
if (config.useIpv6)
|
||||
kind = config.tcp_enable ? NN_LOCATOR_KIND_TCPv6 : NN_LOCATOR_KIND_UDPv6;
|
||||
else
|
||||
kind = config.tcp_enable ? NN_LOCATOR_KIND_TCPv4 : NN_LOCATOR_KIND_UDPv4;
|
||||
switch (ddsi_locator_from_string(&loc, ip))
|
||||
{
|
||||
case AFSR_OK:
|
||||
break;
|
||||
case AFSR_INVALID:
|
||||
NN_ERROR ("%s: %s: not a valid address\n", msgtag, ip);
|
||||
return -1;
|
||||
case AFSR_UNKNOWN:
|
||||
NN_ERROR ("%s: %s: unknown address\n", msgtag, ip);
|
||||
return -1;
|
||||
case AFSR_MISMATCH:
|
||||
NN_ERROR ("%s: %s: address family mismatch\n", msgtag, ip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!os_sockaddrStringToAddress (ip, (os_sockaddr *) &tmpaddr, !config.useIpv6))
|
||||
{
|
||||
NN_ERROR ("%s: %s: not a valid address\n", msgtag, ip);
|
||||
return -1;
|
||||
}
|
||||
if ((config.useIpv6 && tmpaddr.ss_family != AF_INET6) || (!config.useIpv6 && tmpaddr.ss_family != AF_INET))
|
||||
{
|
||||
NN_ERROR ("%s: %s: not a valid IPv%d address\n", msgtag, ip, config.useIpv6 ? 6 : 4);
|
||||
return -1;
|
||||
}
|
||||
nn_address_to_loc (&loc, &tmpaddr, kind);
|
||||
if (req_mc && !is_mcaddr (&loc))
|
||||
if (req_mc && !ddsi_is_mcaddr (&loc))
|
||||
{
|
||||
NN_ERROR ("%s: %s: not a multicast address\n", msgtag, ip);
|
||||
return -1;
|
||||
|
@ -71,7 +68,7 @@ static int add_addresses_to_addrset_1 (struct addrset *as, const char *ip, int p
|
|||
|
||||
if (mcgen_base == -1 && mcgen_count == -1 && mcgen_idx == -1)
|
||||
;
|
||||
else if (kind == NN_LOCATOR_KIND_UDPv4 && is_mcaddr(&loc) && mcgen_base >= 0 && mcgen_count > 0 && mcgen_base + mcgen_count < 28 && mcgen_idx >= 0 && mcgen_idx < mcgen_count)
|
||||
else if (loc.kind == NN_LOCATOR_KIND_UDPv4 && ddsi_is_mcaddr(&loc) && mcgen_base >= 0 && mcgen_count > 0 && mcgen_base + mcgen_count < 28 && mcgen_idx >= 0 && mcgen_idx < mcgen_count)
|
||||
{
|
||||
nn_udpv4mcgen_address_t x;
|
||||
memset(&x, 0, sizeof(x));
|
||||
|
@ -93,13 +90,13 @@ static int add_addresses_to_addrset_1 (struct addrset *as, const char *ip, int p
|
|||
if (port_mode >= 0)
|
||||
{
|
||||
loc.port = (unsigned) port_mode;
|
||||
nn_log (LC_CONFIG, "%s: add %s", msgtag, locator_to_string_with_port (buf, &loc));
|
||||
nn_log (LC_CONFIG, "%s: add %s", msgtag, ddsi_locator_to_string(buf, sizeof(buf), &loc));
|
||||
add_to_addrset (as, &loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
nn_log (LC_CONFIG, "%s: add ", msgtag);
|
||||
if (!is_mcaddr (&loc))
|
||||
if (!ddsi_is_mcaddr (&loc))
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= config.maxAutoParticipantIndex; i++)
|
||||
|
@ -107,7 +104,7 @@ static int add_addresses_to_addrset_1 (struct addrset *as, const char *ip, int p
|
|||
int port = config.port_base + config.port_dg * config.domainId + i * config.port_pg + config.port_d1;
|
||||
loc.port = (unsigned) port;
|
||||
if (i == 0)
|
||||
nn_log (LC_CONFIG, "%s", locator_to_string_with_port (buf, &loc));
|
||||
nn_log (LC_CONFIG, "%s", ddsi_locator_to_string(buf, sizeof(buf), &loc));
|
||||
else
|
||||
nn_log (LC_CONFIG, ", :%d", port);
|
||||
add_to_addrset (as, &loc);
|
||||
|
@ -119,7 +116,7 @@ static int add_addresses_to_addrset_1 (struct addrset *as, const char *ip, int p
|
|||
if (port == -1)
|
||||
port = config.port_base + config.port_dg * config.domainId + config.port_d0;
|
||||
loc.port = (unsigned) port;
|
||||
nn_log (LC_CONFIG, "%s", locator_to_string_with_port (buf, &loc));
|
||||
nn_log (LC_CONFIG, "%s", ddsi_locator_to_string(buf, sizeof(buf), &loc));
|
||||
add_to_addrset (as, &loc);
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +139,7 @@ int add_addresses_to_addrset (struct addrset *as, const char *addrs, int port_mo
|
|||
{
|
||||
int port = 0, pos;
|
||||
int mcgen_base = -1, mcgen_count = -1, mcgen_idx = -1;
|
||||
if (!config.useIpv6)
|
||||
if (config.transport_selector == TRANS_UDP || config.transport_selector == TRANS_TCP)
|
||||
{
|
||||
if (port_mode == -1 && sscanf (a, "%[^:]:%d%n", ip, &port, &pos) == 2 && a[pos] == 0)
|
||||
; /* XYZ:PORT */
|
||||
|
@ -227,33 +224,6 @@ void unref_addrset (struct addrset *as)
|
|||
}
|
||||
}
|
||||
|
||||
int is_mcaddr (const nn_locator_t *loc)
|
||||
{
|
||||
os_sockaddr_storage tmp;
|
||||
switch (loc->kind)
|
||||
{
|
||||
case NN_LOCATOR_KIND_UDPv4: {
|
||||
const os_sockaddr_in *x;
|
||||
nn_loc_to_address (&tmp, loc);
|
||||
x = (const os_sockaddr_in *) &tmp;
|
||||
return IN_MULTICAST (ntohl (x->sin_addr.s_addr));
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case NN_LOCATOR_KIND_UDPv6: {
|
||||
const os_sockaddr_in6 *x;
|
||||
nn_loc_to_address (&tmp, loc);
|
||||
x = (const os_sockaddr_in6 *) &tmp;
|
||||
return IN6_IS_ADDR_MULTICAST (&x->sin6_addr);
|
||||
}
|
||||
#endif
|
||||
case NN_LOCATOR_KIND_UDPv4MCGEN:
|
||||
return 1;
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_unspec_locator (nn_locator_t *loc)
|
||||
{
|
||||
loc->kind = NN_LOCATOR_KIND_INVALID;
|
||||
|
@ -270,31 +240,6 @@ int is_unspec_locator (const nn_locator_t *loc)
|
|||
}
|
||||
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
int is_ssm_mcaddr (const nn_locator_t *loc)
|
||||
{
|
||||
os_sockaddr_storage tmp;
|
||||
switch (loc->kind)
|
||||
{
|
||||
case NN_LOCATOR_KIND_UDPv4: {
|
||||
const os_sockaddr_in *x;
|
||||
nn_loc_to_address (&tmp, loc);
|
||||
x = (const os_sockaddr_in *) &tmp;
|
||||
return (((uint32_t) ntohl (x->sin_addr.s_addr)) >> 24) == 232;
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case NN_LOCATOR_KIND_UDPv6: {
|
||||
const os_sockaddr_in6 *x;
|
||||
nn_loc_to_address (&tmp, loc);
|
||||
x = (const os_sockaddr_in6 *) &tmp;
|
||||
return x->sin6_addr.s6_addr[0] == 0xff && (x->sin6_addr.s6_addr[1] & 0xf0) == 0x30;
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int addrset_contains_ssm (const struct addrset *as)
|
||||
{
|
||||
struct addrset_node *n;
|
||||
|
@ -302,7 +247,7 @@ int addrset_contains_ssm (const struct addrset *as)
|
|||
LOCK (as);
|
||||
for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it))
|
||||
{
|
||||
if (is_ssm_mcaddr (&n->loc))
|
||||
if (ddsi_is_ssm_mcaddr (&n->loc))
|
||||
{
|
||||
UNLOCK (as);
|
||||
return 1;
|
||||
|
@ -319,7 +264,7 @@ int addrset_any_ssm (const struct addrset *as, nn_locator_t *dst)
|
|||
LOCK (as);
|
||||
for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it))
|
||||
{
|
||||
if (is_ssm_mcaddr (&n->loc))
|
||||
if (ddsi_is_ssm_mcaddr (&n->loc))
|
||||
{
|
||||
*dst = n->loc;
|
||||
UNLOCK (as);
|
||||
|
@ -337,7 +282,7 @@ int addrset_any_non_ssm_mc (const struct addrset *as, nn_locator_t *dst)
|
|||
LOCK (as);
|
||||
for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it))
|
||||
{
|
||||
if (!is_ssm_mcaddr (&n->loc))
|
||||
if (!ddsi_is_ssm_mcaddr (&n->loc))
|
||||
{
|
||||
*dst = n->loc;
|
||||
UNLOCK (as);
|
||||
|
@ -363,7 +308,7 @@ void add_to_addrset (struct addrset *as, const nn_locator_t *loc)
|
|||
if (!is_unspec_locator (loc))
|
||||
{
|
||||
ut_avlIPath_t path;
|
||||
ut_avlCTree_t *tree = is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs;
|
||||
ut_avlCTree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs;
|
||||
LOCK (as);
|
||||
if (ut_avlCLookupIPath (&addrset_treedef, tree, loc, &path) == NULL)
|
||||
{
|
||||
|
@ -378,7 +323,7 @@ void add_to_addrset (struct addrset *as, const nn_locator_t *loc)
|
|||
void remove_from_addrset (struct addrset *as, const nn_locator_t *loc)
|
||||
{
|
||||
ut_avlDPath_t path;
|
||||
ut_avlCTree_t *tree = is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs;
|
||||
ut_avlCTree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs;
|
||||
struct addrset_node *n;
|
||||
LOCK (as);
|
||||
if ((n = ut_avlCLookupDPath (&addrset_treedef, tree, loc, &path)) != NULL)
|
||||
|
@ -423,7 +368,7 @@ void copy_addrset_into_addrset_no_ssm_mc (struct addrset *as, const struct addrs
|
|||
LOCK (asadd);
|
||||
for (n = ut_avlCIterFirst (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ut_avlCIterNext (&it))
|
||||
{
|
||||
if (!is_ssm_mcaddr (&n->loc))
|
||||
if (!ddsi_is_ssm_mcaddr (&n->loc))
|
||||
add_to_addrset (as, &n->loc);
|
||||
}
|
||||
UNLOCK (asadd);
|
||||
|
@ -445,7 +390,7 @@ void addrset_purge_ssm (struct addrset *as)
|
|||
{
|
||||
struct addrset_node *n1 = n;
|
||||
n = ut_avlCFindSucc (&addrset_treedef, &as->mcaddrs, n);
|
||||
if (is_ssm_mcaddr (&n1->loc))
|
||||
if (ddsi_is_ssm_mcaddr (&n1->loc))
|
||||
{
|
||||
ut_avlCDelete (&addrset_treedef, &as->mcaddrs, n1);
|
||||
os_free (n1);
|
||||
|
@ -623,9 +568,9 @@ struct log_addrset_helper_arg
|
|||
static void log_addrset_helper (const nn_locator_t *n, void *varg)
|
||||
{
|
||||
const struct log_addrset_helper_arg *arg = varg;
|
||||
char buf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buf[DDSI_LOCSTRLEN];
|
||||
if (config.enabled_logcats & arg->tf)
|
||||
nn_log (arg->tf, " %s", locator_to_string_with_port (buf, n));
|
||||
nn_log (arg->tf, " %s", ddsi_locator_to_string(buf, sizeof(buf), n));
|
||||
}
|
||||
|
||||
void nn_log_addrset (logcat_t tf, const char *prefix, const struct addrset *as)
|
||||
|
|
|
@ -120,6 +120,7 @@ DUPF(networkAddresses);
|
|||
DU(ipv4);
|
||||
DUPF(allow_multicast);
|
||||
DUPF(boolean);
|
||||
DUPF(boolean_default);
|
||||
DUPF(negated_boolean);
|
||||
DUPF(string);
|
||||
DU(tracingOutputFileName);
|
||||
|
@ -158,6 +159,9 @@ DUPF(bandwidth);
|
|||
#endif
|
||||
DU(domainId);
|
||||
DUPF(durability_cdr);
|
||||
DUPF(transport_selector);
|
||||
DUPF(many_sockets_mode);
|
||||
DU(deaf_mute);
|
||||
#undef DUPF
|
||||
#undef DU
|
||||
#undef PF
|
||||
|
@ -192,6 +196,7 @@ DI(if_thread_properties);
|
|||
#define LEAF(name) name, NULL, NULL
|
||||
#define LEAF_W_ATTRS(name, attrs) name, NULL, attrs
|
||||
#define GROUP(name, children) name, children, NULL, 1, NULL, 0, 0, 0, 0, 0, 0
|
||||
#define GROUP_W_ATTRS(name, children, attrs) name, children, attrs, 1, NULL, 0, 0, 0, 0, 0, 0
|
||||
#define MGROUP(name, children, attrs) name, children, attrs
|
||||
#define ATTR(name) name, NULL, NULL
|
||||
/* MOVED: whereto must be a path relative to DDSI2Service, may not be used in/for lists and only for elements, may not be chained */
|
||||
|
@ -232,8 +237,10 @@ static const struct cfgelem general_cfgelems[] = {
|
|||
"<p>This element specifies the time-to-live setting for outgoing multicast packets.</p>" },
|
||||
{ LEAF("DontRoute"), 1, "false", ABSOFF(dontRoute), 0, uf_boolean, 0, pf_boolean,
|
||||
"<p>This element allows setting the SO_DONTROUTE option for outgoing packets, to bypass the local routing tables. This is generally useful only when the routing tables cannot be trusted, which is highly unusual.</p>" },
|
||||
{ LEAF("UseIPv6"), 1, "false", ABSOFF(useIpv6), 0, uf_boolean, 0, pf_boolean ,
|
||||
"<p>This element can be used to DDSI2E use IPv6 instead of IPv4. This is currently an either/or switch.</p>" },
|
||||
{ LEAF ("UseIPv6"), 1, "default", ABSOFF (compat_use_ipv6), 0, uf_boolean_default, 0, pf_nop,
|
||||
"<p>Deprecated (use Transport instead)</p>" },
|
||||
{ LEAF ("Transport"), 1, "default", ABSOFF (transport_selector), 0, uf_transport_selector, 0, pf_transport_selector,
|
||||
"<p>This element allows selecting the transport to be used (udp, udp6, tcp, tcp6, raweth)</p>" },
|
||||
{ LEAF("EnableMulticastLoopback"), 1, "true", ABSOFF(enableMulticastLoopback), 0, uf_boolean, 0, pf_boolean,
|
||||
"<p>This element specifies whether DDSI2E allows IP multicast packets to be visible to all DDSI participants in the same node, including itself. It must be \"true\" for intra-node multicast communications, but if a node runs only a single DDSI2E service and does not host any other DDSI-capable programs, it should be set to \"false\" for improved performance.</p>" },
|
||||
{ LEAF("EnableLoopback"), 1, "false", ABSOFF(enableLoopback), 0, uf_boolean, 0, pf_boolean,
|
||||
|
@ -418,7 +425,7 @@ static const struct cfgelem compatibility_cfgelems[] = {
|
|||
{ LEAF("ExplicitlyPublishQosSetToDefault"), 1, "false", ABSOFF(explicitly_publish_qos_set_to_default), 0, uf_boolean, 0, pf_boolean,
|
||||
"<p>This element specifies whether QoS settings set to default values are explicitly published in the discovery protocol. Implementations are to use the default value for QoS settings not published, which allows a significant reduction of the amount of data that needs to be exchanged for the discovery protocol, but this requires all implementations to adhere to the default values specified by the specifications.</p>\n\
|
||||
<p>When interoperability is required with an implementation that does not follow the specifications in this regard, setting this option to true will help.</p>" },
|
||||
{ LEAF("ManySocketsMode"), 1, "false", ABSOFF(many_sockets_mode), 0, uf_boolean, 0, pf_boolean,
|
||||
{ LEAF ("ManySocketsMode"), 1, "single", ABSOFF (many_sockets_mode), 0, uf_many_sockets_mode, 0, pf_many_sockets_mode,
|
||||
"<p>This option specifies whether a network socket will be created for each domain participant on a host. The specification seems to assume that each participant has a unique address, and setting this option will ensure this to be the case. This is not the defeault.</p>\n\
|
||||
<p>Disabling it slightly improves performance and reduces network traffic somewhat. It also causes the set of port numbers needed by DDSI2E to become predictable, which may be useful for firewall and NAT configuration.</p>" },
|
||||
{ LEAF("ArrivalOfDataAssertsPpAndEpLiveliness"), 1, "true", ABSOFF(arrival_of_data_asserts_pp_and_ep_liveliness), 0, uf_boolean, 0, pf_boolean,
|
||||
|
@ -459,8 +466,10 @@ static const struct cfgelem control_topic_cfgattrs[] = {
|
|||
};
|
||||
|
||||
static const struct cfgelem control_topic_cfgelems[] = {
|
||||
{ LEAF("Deaf"), 1, "false", ABSOFF(initial_deaf), 0, uf_boolean, 0, pf_boolean },
|
||||
{ LEAF("Mute"), 1, "false", ABSOFF(initial_mute), 0, uf_boolean, 0, pf_boolean },
|
||||
{ LEAF ("Deaf"), 1, "false", ABSOFF (initial_deaf), 0, uf_deaf_mute, 0, pf_boolean,
|
||||
"<p>This element controls whether DDSI2E defaults to deaf mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.</p>" },
|
||||
{ LEAF ("Mute"), 1, "false", ABSOFF (initial_mute), 0, uf_deaf_mute, 0, pf_boolean,
|
||||
"<p>This element controls whether DDSI2E defaults to mute mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.</p>" },
|
||||
END_MARKER
|
||||
};
|
||||
|
||||
|
@ -471,9 +480,12 @@ static const struct cfgelem rediscovery_blacklist_duration_attrs[] = {
|
|||
};
|
||||
|
||||
static const struct cfgelem heartbeat_interval_attrs[] = {
|
||||
{ ATTR("min"), 1, "5 ms", ABSOFF(const_hb_intv_min), 0, uf_duration_inf, 0, pf_duration },
|
||||
{ ATTR("minsched"), 1, "20 ms", ABSOFF(const_hb_intv_sched_min), 0, uf_duration_inf, 0, pf_duration },
|
||||
{ ATTR("max"), 1, "8 s", ABSOFF(const_hb_intv_sched_max), 0, uf_duration_inf, 0, pf_duration },
|
||||
{ ATTR ("min"), 1, "5 ms", ABSOFF (const_hb_intv_min), 0, uf_duration_inf, 0, pf_duration,
|
||||
"<p>This attribute sets the minimum interval that must have passed since the most recent heartbeat from a writer, before another asynchronous (not directly related to writing) will be sent.</p>" },
|
||||
{ ATTR ("minsched"), 1, "20 ms", ABSOFF (const_hb_intv_sched_min), 0, uf_duration_inf, 0, pf_duration,
|
||||
"<p>This attribute sets the minimum interval for periodic heartbeats. Other events may still cause heartbeats to go out.</p>" },
|
||||
{ ATTR ("max"), 1, "8 s", ABSOFF (const_hb_intv_sched_max), 0, uf_duration_inf, 0, pf_duration,
|
||||
"<p>This attribute sets the maximum interval for periodic heartbeats.</p>" },
|
||||
END_MARKER
|
||||
};
|
||||
|
||||
|
@ -622,8 +634,8 @@ static const struct cfgelem discovery_ports_cfgelems[] = {
|
|||
};
|
||||
|
||||
static const struct cfgelem tcp_cfgelems[] = {
|
||||
{ LEAF("Enable"), 1, "false", ABSOFF(tcp_enable), 0, uf_boolean, 0, pf_boolean,
|
||||
"<p>This element enables the optional TCP transport.</p>" },
|
||||
{ LEAF ("Enable"), 1, "default", ABSOFF (compat_tcp_enable), 0, uf_boolean_default, 0, pf_nop,
|
||||
"<p>This element enables the optional TCP transport - deprecated, use General/Transport instead.</p>" },
|
||||
{ LEAF("NoDelay"), 1, "true", ABSOFF(tcp_nodelay), 0, uf_boolean, 0, pf_boolean,
|
||||
"<p>This element enables the TCP_NODELAY socket option, preventing multiple DDSI messages being sent in the same TCP request. Setting this option typically optimises latency over throughput.</p>" },
|
||||
{ LEAF("Port"), 1, "-1", ABSOFF(tcp_port), 0, uf_dyn_port, 0, pf_int,
|
||||
|
@ -632,6 +644,8 @@ static const struct cfgelem tcp_cfgelems[] = {
|
|||
"<p>This element specifies the timeout for blocking TCP read operations. If this timeout expires then the connection is closed.</p>" },
|
||||
{ LEAF("WriteTimeout"), 1, "2 s", ABSOFF(tcp_write_timeout), 0, uf_duration_ms_1hr, 0, pf_duration,
|
||||
"<p>This element specifies the timeout for blocking TCP write operations. If this timeout expires then the connection is closed.</p>" },
|
||||
{ LEAF ("AlwaysUsePeeraddrForUnicast"), 1, "false", ABSOFF (tcp_use_peeraddr_for_unicast), 0, uf_boolean, 0, pf_boolean,
|
||||
"<p>Setting this to true means the unicast addresses in SPDP packets will be ignored and the peer address from the TCP connection will be used instead. This may help work around incorrectly advertised addresses when using TCP.</p>" },
|
||||
END_MARKER
|
||||
};
|
||||
|
||||
|
@ -1271,6 +1285,33 @@ static int uf_negated_boolean(struct cfgst *cfgst, void *parent, struct cfgelem
|
|||
}
|
||||
}
|
||||
|
||||
static int uf_boolean_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
|
||||
{
|
||||
static const char *vs[] = { "default", "false", "true", NULL };
|
||||
static const enum boolean_default ms[] = {
|
||||
BOOLDEF_DEFAULT, BOOLDEF_FALSE, BOOLDEF_TRUE, 0,
|
||||
};
|
||||
int *elem = cfg_address (cfgst, parent, cfgelem);
|
||||
int idx = list_index (vs, value);
|
||||
assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms));
|
||||
if (idx < 0)
|
||||
return cfg_error (cfgst, "'%s': undefined value", value);
|
||||
*elem = ms[idx];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pf_boolean_default (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
|
||||
{
|
||||
enum besmode *p = cfg_address (cfgst, parent, cfgelem);
|
||||
const char *str = "INVALID";
|
||||
switch (*p)
|
||||
{
|
||||
case BOOLDEF_DEFAULT: str = "default"; break;
|
||||
case BOOLDEF_FALSE: str = "false"; break;
|
||||
case BOOLDEF_TRUE: str = "true"; break;
|
||||
}
|
||||
cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : "");
|
||||
}
|
||||
|
||||
static int uf_logcat(struct cfgst *cfgst, UNUSED_ARG(void *parent), UNUSED_ARG(struct cfgelem const * const cfgelem), UNUSED_ARG(int first), const char *value)
|
||||
{
|
||||
|
@ -1871,6 +1912,70 @@ static int uf_natint_255(struct cfgst *cfgst, void *parent, struct cfgelem const
|
|||
return uf_int_min_max(cfgst, parent, cfgelem, first, value, 0, 255);
|
||||
}
|
||||
|
||||
static int uf_transport_selector (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
|
||||
{
|
||||
static const char *vs[] = { "default", "udp", "udp6", "tcp", "tcp6", "raweth", NULL };
|
||||
static const enum transport_selector ms[] = {
|
||||
TRANS_DEFAULT, TRANS_UDP, TRANS_UDP6, TRANS_TCP, TRANS_TCP6, TRANS_RAWETH, 0,
|
||||
};
|
||||
enum transport_selector *elem = cfg_address (cfgst, parent, cfgelem);
|
||||
int idx = list_index (vs, value);
|
||||
assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms));
|
||||
if (idx < 0)
|
||||
return cfg_error (cfgst, "'%s': undefined value", value);
|
||||
*elem = ms[idx];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pf_transport_selector (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
|
||||
{
|
||||
enum transport_selector *p = cfg_address (cfgst, parent, cfgelem);
|
||||
const char *str = "INVALID";
|
||||
switch (*p)
|
||||
{
|
||||
case TRANS_DEFAULT: str = "default"; break;
|
||||
case TRANS_UDP: str = "udp"; break;
|
||||
case TRANS_UDP6: str = "udp6"; break;
|
||||
case TRANS_TCP: str = "tcp"; break;
|
||||
case TRANS_TCP6: str = "tcp6"; break;
|
||||
case TRANS_RAWETH: str = "raweth"; break;
|
||||
}
|
||||
cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : "");
|
||||
}
|
||||
|
||||
static int uf_many_sockets_mode (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
|
||||
{
|
||||
static const char *vs[] = { "false", "true", "single", "none", "many", NULL };
|
||||
static const enum many_sockets_mode ms[] = {
|
||||
MSM_SINGLE_UNICAST, MSM_MANY_UNICAST, MSM_SINGLE_UNICAST, MSM_NO_UNICAST, MSM_MANY_UNICAST, 0,
|
||||
};
|
||||
enum many_sockets_mode *elem = cfg_address (cfgst, parent, cfgelem);
|
||||
int idx = list_index (vs, value);
|
||||
assert (sizeof (vs) / sizeof (*vs) == sizeof (ms) / sizeof (*ms));
|
||||
if (idx < 0)
|
||||
return cfg_error (cfgst, "'%s': undefined value", value);
|
||||
*elem = ms[idx];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pf_many_sockets_mode (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default)
|
||||
{
|
||||
enum many_sockets_mode *p = cfg_address (cfgst, parent, cfgelem);
|
||||
const char *str = "INVALID";
|
||||
switch (*p)
|
||||
{
|
||||
case MSM_SINGLE_UNICAST: str = "single"; break;
|
||||
case MSM_MANY_UNICAST: str = "many"; break;
|
||||
case MSM_NO_UNICAST: str = "none"; break;
|
||||
}
|
||||
cfg_log (cfgst, "%s%s", str, is_default ? " [def]" : "");
|
||||
}
|
||||
|
||||
static int uf_deaf_mute (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
|
||||
{
|
||||
return uf_boolean (cfgst, parent, cfgelem, first, value);
|
||||
}
|
||||
|
||||
static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct cfgelem const * const cfgelem, const char *value, int is_default)
|
||||
{
|
||||
struct cfgst_node *n;
|
||||
|
@ -2620,6 +2725,42 @@ struct cfgst * config_init
|
|||
ok = ok && ok1;
|
||||
}
|
||||
|
||||
|
||||
/* Compatibility settings of IPv6, TCP -- a bit too complicated for
|
||||
the poor framework */
|
||||
{
|
||||
int ok1 = 1;
|
||||
switch (cfgst->cfg->transport_selector)
|
||||
{
|
||||
case TRANS_DEFAULT:
|
||||
if (cfgst->cfg->compat_tcp_enable == BOOLDEF_TRUE)
|
||||
cfgst->cfg->transport_selector = (config.compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_TCP6 : TRANS_TCP;
|
||||
else
|
||||
cfgst->cfg->transport_selector = (config.compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_UDP6 : TRANS_UDP;
|
||||
break;
|
||||
case TRANS_TCP:
|
||||
ok1 = !(cfgst->cfg->compat_tcp_enable == BOOLDEF_FALSE || cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE);
|
||||
break;
|
||||
case TRANS_TCP6:
|
||||
ok1 = !(cfgst->cfg->compat_tcp_enable == BOOLDEF_FALSE || cfgst->cfg->compat_use_ipv6 == BOOLDEF_FALSE);
|
||||
break;
|
||||
case TRANS_UDP:
|
||||
ok1 = !(cfgst->cfg->compat_tcp_enable == BOOLDEF_TRUE || cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE);
|
||||
break;
|
||||
case TRANS_UDP6:
|
||||
ok1 = !(cfgst->cfg->compat_tcp_enable == BOOLDEF_TRUE || cfgst->cfg->compat_use_ipv6 == BOOLDEF_FALSE);
|
||||
break;
|
||||
case TRANS_RAWETH:
|
||||
ok1 = !(cfgst->cfg->compat_tcp_enable == BOOLDEF_TRUE || cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE);
|
||||
break;
|
||||
}
|
||||
if (!ok1)
|
||||
NN_ERROR ("config: invalid combination of Transport, IPv6, TCP\n");
|
||||
ok = ok && ok1;
|
||||
cfgst->cfg->compat_use_ipv6 = (cfgst->cfg->transport_selector == TRANS_UDP6 || cfgst->cfg->transport_selector == TRANS_TCP6) ? BOOLDEF_TRUE : BOOLDEF_FALSE;
|
||||
cfgst->cfg->compat_tcp_enable = (cfgst->cfg->transport_selector == TRANS_TCP || cfgst->cfg->transport_selector == TRANS_TCP6) ? BOOLDEF_TRUE : BOOLDEF_FALSE;
|
||||
}
|
||||
|
||||
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
|
||||
/* Default channel gets set outside set_defaults -- a bit too
|
||||
complicated for the poor framework */
|
||||
|
@ -2761,8 +2902,9 @@ void config_fini(_In_ struct cfgst *cfgst)
|
|||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
static char *get_partition_search_pattern(const char *partition, const char *topic)
|
||||
{
|
||||
char *pt = os_malloc(strlen(partition) + strlen(topic) + 2);
|
||||
os_sprintf(pt, "%s.%s", partition, topic);
|
||||
size_t sz = strlen(partition) + strlen(topic) + 2;
|
||||
char *pt = os_malloc(sz);
|
||||
snprintf(pt, sz, "%s.%s", partition, topic);
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
|
|||
memset (&samenet, 0, sizeof (samenet));
|
||||
|
||||
/* Special case UDPv4 MC address generators - there is a bit of an type mismatch between an address generator (i.e., a set of addresses) and an address ... Whoever uses them is supposed to know that that is what he wants, so we simply given them priority. */
|
||||
if (!config.tcp_enable && !config.useIpv6)
|
||||
if (ddsi_factory_supports (gv.m_factory, NN_LOCATOR_KIND_UDPv4))
|
||||
{
|
||||
for (l = locs->first; l != NULL; l = l->next)
|
||||
{
|
||||
|
@ -73,9 +73,6 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
|
|||
match, so the first one will be used. */
|
||||
for (l = locs->first; l != NULL; l = l->next)
|
||||
{
|
||||
os_sockaddr_storage tmp;
|
||||
int i;
|
||||
|
||||
/* Skip locators of the wrong kind */
|
||||
|
||||
if (! ddsi_factory_supports (gv.m_factory, l->loc.kind))
|
||||
|
@ -83,24 +80,23 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
|
|||
continue;
|
||||
}
|
||||
|
||||
nn_loc_to_address (&tmp, &l->loc);
|
||||
|
||||
if (l->loc.kind == NN_LOCATOR_KIND_UDPv4 && gv.extmask.s_addr != 0)
|
||||
if (l->loc.kind == NN_LOCATOR_KIND_UDPv4 && gv.extmask.kind != NN_LOCATOR_KIND_INVALID)
|
||||
{
|
||||
/* If the examined locator is in the same subnet as our own
|
||||
external IP address, this locator will be translated into one
|
||||
in the same subnet as our own local ip and selected. */
|
||||
os_sockaddr_in *tmp4 = (os_sockaddr_in *) &tmp;
|
||||
const os_sockaddr_in *ownip = (os_sockaddr_in *) &gv.ownip;
|
||||
const os_sockaddr_in *extip = (os_sockaddr_in *) &gv.extip;
|
||||
struct in_addr tmp4 = *((struct in_addr *) (l->loc.address + 12));
|
||||
const struct in_addr ownip = *((struct in_addr *) (gv.ownloc.address + 12));
|
||||
const struct in_addr extip = *((struct in_addr *) (gv.extloc.address + 12));
|
||||
const struct in_addr extmask = *((struct in_addr *) (gv.extmask.address + 12));
|
||||
|
||||
if ((tmp4->sin_addr.s_addr & gv.extmask.s_addr) == (extip->sin_addr.s_addr & gv.extmask.s_addr))
|
||||
if ((tmp4.s_addr & extmask.s_addr) == (extip.s_addr & extmask.s_addr))
|
||||
{
|
||||
/* translate network part of the IP address from the external
|
||||
one to the internal one */
|
||||
tmp4->sin_addr.s_addr =
|
||||
(tmp4->sin_addr.s_addr & ~gv.extmask.s_addr) | (ownip->sin_addr.s_addr & gv.extmask.s_addr);
|
||||
nn_address_to_loc (loc, &tmp, l->loc.kind);
|
||||
tmp4.s_addr = (tmp4.s_addr & ~extmask.s_addr) | (ownip.s_addr & extmask.s_addr);
|
||||
memcpy (loc, &l->loc, sizeof (*loc));
|
||||
memcpy (loc->address + 12, &tmp4, 4);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +107,8 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
|
|||
/* We (cowardly) refuse to accept advertised link-local
|
||||
addresses unles we're in "link-local" mode ourselves. Then
|
||||
we just hope for the best. */
|
||||
if (!gv.ipv6_link_local && IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *) &tmp)->sin6_addr))
|
||||
const struct in6_addr *ip6 = (const struct in6_addr *) l->loc.address;
|
||||
if (!gv.ipv6_link_local && IN6_IS_ADDR_LINKLOCAL (ip6))
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
@ -121,23 +118,23 @@ static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_sam
|
|||
first = l->loc;
|
||||
first_set = 1;
|
||||
}
|
||||
for (i = 0; i < gv.n_interfaces; i++)
|
||||
|
||||
switch (ddsi_is_nearby_address(&l->loc, (size_t)gv.n_interfaces, gv.interfaces))
|
||||
{
|
||||
if (os_sockaddrSameSubnet ((os_sockaddr *) &tmp, (os_sockaddr *) &gv.interfaces[i].addr, (os_sockaddr *) &gv.interfaces[i].netmask))
|
||||
{
|
||||
if (os_sockaddrIPAddressEqual ((os_sockaddr*) &gv.interfaces[i].addr, (os_sockaddr*) &gv.ownip))
|
||||
{
|
||||
/* matches the preferred interface -> the very best situation */
|
||||
*loc = l->loc;
|
||||
return 1;
|
||||
}
|
||||
else if (!samenet_set)
|
||||
case DNAR_DISTANT:
|
||||
break;
|
||||
case DNAR_LOCAL:
|
||||
if (!samenet_set)
|
||||
{
|
||||
/* on a network we're connected to */
|
||||
samenet = l->loc;
|
||||
samenet_set = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DNAR_SAME:
|
||||
/* matches the preferred interface -> the very best situation */
|
||||
*loc = l->loc;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!uc_same_subnet)
|
||||
|
@ -237,7 +234,7 @@ int spdp_write (struct participant *pp)
|
|||
def_uni_loc_one.next = NULL;
|
||||
meta_uni_loc_one.next = NULL;
|
||||
|
||||
if (config.many_sockets_mode)
|
||||
if (config.many_sockets_mode == MSM_MANY_UNICAST)
|
||||
{
|
||||
def_uni_loc_one.loc = pp->m_locator;
|
||||
meta_uni_loc_one.loc = pp->m_locator;
|
||||
|
@ -262,7 +259,7 @@ int spdp_write (struct participant *pp)
|
|||
we will simply advertise it. The recipients better understand
|
||||
it means the writers will publish to address and the readers
|
||||
favour SSM. */
|
||||
if (is_ssm_mcaddr (&gv.loc_default_mc))
|
||||
if (ddsi_is_ssm_mcaddr (&gv.loc_default_mc))
|
||||
include = (config.allowMulticast & AMC_SSM) != 0;
|
||||
else
|
||||
include = (config.allowMulticast & AMC_ASM) != 0;
|
||||
|
@ -457,18 +454,18 @@ static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t times
|
|||
static void allowmulticast_aware_add_to_addrset (struct addrset *as, const nn_locator_t *loc)
|
||||
{
|
||||
#if DDSI_INCLUDE_SSM
|
||||
if (is_ssm_mcaddr (loc))
|
||||
if (ddsi_is_ssm_mcaddr (loc))
|
||||
{
|
||||
if (!(config.allowMulticast & AMC_SSM))
|
||||
return;
|
||||
}
|
||||
else if (is_mcaddr (loc))
|
||||
else if (ddsi_is_mcaddr (loc))
|
||||
{
|
||||
if (!(config.allowMulticast & AMC_ASM))
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (is_mcaddr (loc) && !(config.allowMulticast & AMC_ASM))
|
||||
if (ddsi_is_mcaddr (loc) && !(config.allowMulticast & AMC_ASM))
|
||||
return;
|
||||
#endif
|
||||
add_to_addrset (as, loc);
|
||||
|
@ -720,15 +717,15 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time
|
|||
}
|
||||
|
||||
/* If unicast locators not present, then try to obtain from connection */
|
||||
if ((datap->present & PP_DEFAULT_UNICAST_LOCATOR) && (get_locator (&loc, &datap->default_unicast_locators, uc_same_subnet)))
|
||||
add_to_addrset (as_default, &loc);
|
||||
else if (ddsi_conn_peer_locator (rst->conn, &loc))
|
||||
if (!config.tcp_use_peeraddr_for_unicast && (datap->present & PP_DEFAULT_UNICAST_LOCATOR) && (get_locator (&loc, &datap->default_unicast_locators, uc_same_subnet)))
|
||||
add_to_addrset (as_default, &loc);
|
||||
else
|
||||
nn_log (LC_DISCOVERY, " (srclocD)"), add_to_addrset (as_default, &rst->srcloc);
|
||||
|
||||
if ((datap->present & PP_METATRAFFIC_UNICAST_LOCATOR) && (get_locator (&loc, &datap->metatraffic_unicast_locators, uc_same_subnet)))
|
||||
add_to_addrset (as_meta, &loc);
|
||||
else if (ddsi_conn_peer_locator (rst->conn, &loc))
|
||||
if (!config.tcp_use_peeraddr_for_unicast && (datap->present & PP_METATRAFFIC_UNICAST_LOCATOR) && (get_locator (&loc, &datap->metatraffic_unicast_locators, uc_same_subnet)))
|
||||
add_to_addrset (as_meta, &loc);
|
||||
else
|
||||
nn_log (LC_DISCOVERY, " (srclocM)"), add_to_addrset (as_meta, &rst->srcloc);
|
||||
|
||||
nn_log_addrset (LC_DISCOVERY, " (data", as_default);
|
||||
nn_log_addrset (LC_DISCOVERY, " meta", as_meta);
|
||||
|
@ -844,7 +841,7 @@ static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp
|
|||
}
|
||||
}
|
||||
|
||||
static void add_sockaddr_to_ps (const nn_locator_t *loc, void *arg)
|
||||
static void add_locator_to_ps (const nn_locator_t *loc, void *arg)
|
||||
{
|
||||
nn_plist_t *ps = (nn_plist_t *) arg;
|
||||
struct nn_locators_one *elem = os_malloc (sizeof (struct nn_locators_one));
|
||||
|
@ -854,7 +851,7 @@ static void add_sockaddr_to_ps (const nn_locator_t *loc, void *arg)
|
|||
elem->loc = *loc;
|
||||
elem->next = NULL;
|
||||
|
||||
if (is_mcaddr (loc)) {
|
||||
if (ddsi_is_mcaddr (loc)) {
|
||||
locs = &ps->multicast_locators;
|
||||
present_flag = PP_MULTICAST_LOCATOR;
|
||||
} else {
|
||||
|
@ -956,7 +953,7 @@ static int sedp_write_endpoint
|
|||
|
||||
if (as)
|
||||
{
|
||||
addrset_forall (as, add_sockaddr_to_ps, &ps);
|
||||
addrset_forall (as, add_locator_to_ps, &ps);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1139,7 +1136,7 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg
|
|||
return ephash_lookup_proxy_participant_guid (ppguid);
|
||||
}
|
||||
|
||||
static void handle_SEDP_alive (nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp)
|
||||
static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *datap /* note: potentially modifies datap */, const nn_guid_prefix_t *src_guid_prefix, nn_vendorid_t vendorid, nn_wctime_t timestamp)
|
||||
{
|
||||
#define E(msg, lbl) do { nn_log (LC_DISCOVERY, (msg)); goto lbl; } while (0)
|
||||
struct proxy_participant *pp;
|
||||
|
@ -1260,8 +1257,10 @@ static void handle_SEDP_alive (nn_plist_t *datap /* note: potentially modifies d
|
|||
{
|
||||
nn_locator_t loc;
|
||||
as = new_addrset ();
|
||||
if ((datap->present & PP_UNICAST_LOCATOR) && get_locator (&loc, &datap->unicast_locators, 0))
|
||||
if (!config.tcp_use_peeraddr_for_unicast && (datap->present & PP_UNICAST_LOCATOR) && get_locator (&loc, &datap->unicast_locators, 0))
|
||||
add_to_addrset (as, &loc);
|
||||
else if (config.tcp_use_peeraddr_for_unicast)
|
||||
nn_log (LC_DISCOVERY, " (srcloc)"), add_to_addrset (as, &rst->srcloc);
|
||||
else
|
||||
copy_addrset_into_addrset_uc (as, pp->as_default);
|
||||
if ((datap->present & PP_MULTICAST_LOCATOR) && get_locator (&loc, &datap->multicast_locators, 0))
|
||||
|
@ -1386,7 +1385,7 @@ static void handle_SEDP (const struct receiver_state *rst, nn_wctime_t timestamp
|
|||
switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER))
|
||||
{
|
||||
case 0:
|
||||
handle_SEDP_alive (&decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp);
|
||||
handle_SEDP_alive (rst, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp);
|
||||
break;
|
||||
|
||||
case NN_STATUSINFO_DISPOSE:
|
||||
|
|
|
@ -64,24 +64,16 @@ static int cpf (ddsi_tran_conn_t conn, const char *fmt, ...)
|
|||
return 0;
|
||||
else
|
||||
{
|
||||
os_sockaddr_storage addr;
|
||||
va_list ap;
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
char buf[4096];
|
||||
int n;
|
||||
nn_loc_to_address(&addr, &loc);
|
||||
va_start (ap, fmt);
|
||||
n = os_vsnprintf (buf, sizeof (buf), fmt, ap);
|
||||
va_end (ap);
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = (size_t) n;
|
||||
memset (&msg, 0, sizeof (msg));
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_name = &addr;
|
||||
msg.msg_namelen = (socklen_t) os_sockaddrSizeof ((os_sockaddr*) &addr);
|
||||
return ddsi_conn_write (conn, &msg, iov.iov_len, 0) < 0 ? -1 : 0;
|
||||
return ddsi_conn_write (conn, &loc, 1, &iov, 0) < 0 ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,8 +85,8 @@ struct print_address_arg {
|
|||
static void print_address (const nn_locator_t *n, void *varg)
|
||||
{
|
||||
struct print_address_arg *arg = varg;
|
||||
char buf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
arg->count += cpf (arg->conn, " %s", locator_to_string_with_port (buf, n));
|
||||
char buf[DDSI_LOCSTRLEN];
|
||||
arg->count += cpf (arg->conn, " %s", ddsi_locator_to_string (buf, sizeof(buf), n));
|
||||
}
|
||||
|
||||
static int print_addrset (ddsi_tran_conn_t conn, const char *prefix, struct addrset *as, const char *suffix)
|
||||
|
@ -357,7 +349,8 @@ struct debug_monitor *new_debug_monitor (int port)
|
|||
dm = os_malloc (sizeof (*dm));
|
||||
|
||||
dm->plugins = NULL;
|
||||
dm->tran_factory = ddsi_factory_find ("tcp");
|
||||
if ((dm->tran_factory = ddsi_factory_find ("tcp")) == NULL)
|
||||
dm->tran_factory = ddsi_factory_find ("tcp6");
|
||||
dm->servsock = ddsi_factory_create_listener (dm->tran_factory, port, NULL);
|
||||
if (dm->servsock == NULL)
|
||||
{
|
||||
|
@ -367,11 +360,9 @@ struct debug_monitor *new_debug_monitor (int port)
|
|||
|
||||
{
|
||||
nn_locator_t loc;
|
||||
os_sockaddr_storage addr;
|
||||
char buf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char buf[DDSI_LOCSTRLEN];
|
||||
(void) ddsi_listener_locator(dm->servsock, &loc);
|
||||
nn_loc_to_address (&addr, &loc);
|
||||
nn_log (LC_CONFIG, "debmon at %s\n", sockaddr_to_string_with_port (buf, &addr));
|
||||
nn_log (LC_CONFIG, "debmon at %s\n", ddsi_locator_to_string (buf, sizeof(buf), &loc));
|
||||
}
|
||||
|
||||
os_mutexInit (&dm->lock);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "ddsi/q_error.h"
|
||||
#include "ddsi/q_builtin_topic.h"
|
||||
#include "ddsi/ddsi_ser.h"
|
||||
#include "ddsi/ddsi_mcgroup.h"
|
||||
|
||||
#include "ddsi/sysdeps.h"
|
||||
|
||||
|
@ -345,18 +346,30 @@ static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigne
|
|||
|
||||
/* PARTICIPANT ------------------------------------------------------ */
|
||||
|
||||
int pp_allocate_entityid (nn_entityid_t *id, unsigned kind, struct participant *pp)
|
||||
int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *pp)
|
||||
{
|
||||
uint32_t id1;
|
||||
int ret = 0;
|
||||
os_mutexLock (&pp->e.lock);
|
||||
if (inverse_uint32_set_alloc(&id1, &pp->avail_entityids.x))
|
||||
{
|
||||
*id = to_entityid (id1 * NN_ENTITYID_ALLOCSTEP + kind);
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
NN_ERROR("pp_allocate_entityid(%x:%x:%x:%x): all ids in use\n", PGUID(pp->e.guid));
|
||||
ret = ERR_OUT_OF_IDS;
|
||||
}
|
||||
os_mutexUnlock (&pp->e.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pp_release_entityid(struct participant *pp, nn_entityid_t id)
|
||||
{
|
||||
os_mutexLock (&pp->e.lock);
|
||||
if (pp->next_entityid + NN_ENTITYID_ALLOCSTEP < pp->next_entityid)
|
||||
{
|
||||
os_mutexUnlock (&pp->e.lock);
|
||||
return ERR_OUT_OF_IDS;
|
||||
}
|
||||
*id = to_entityid (pp->next_entityid | kind);
|
||||
pp->next_entityid += NN_ENTITYID_ALLOCSTEP;
|
||||
inverse_uint32_set_free(&pp->avail_entityids.x, id.u / NN_ENTITYID_ALLOCSTEP);
|
||||
os_mutexUnlock (&pp->e.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plist_t *plist)
|
||||
|
@ -411,7 +424,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
|
|||
pp->builtins_deleted = 0;
|
||||
pp->is_ddsi2_pp = (flags & (RTPS_PF_PRIVILEGED_PP | RTPS_PF_IS_DDSI2_PP)) ? 1 : 0;
|
||||
os_mutexInit (&pp->refc_lock);
|
||||
pp->next_entityid = NN_ENTITYID_ALLOCSTEP;
|
||||
inverse_uint32_set_init(&pp->avail_entityids.x, 1, UINT32_MAX / NN_ENTITYID_ALLOCSTEP);
|
||||
pp->lease_duration = config.lease_duration;
|
||||
pp->plist = os_malloc (sizeof (*pp->plist));
|
||||
nn_plist_copy (pp->plist, plist);
|
||||
|
@ -424,11 +437,15 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
|
|||
nn_log (LC_DISCOVERY, "}\n");
|
||||
}
|
||||
|
||||
if (config.many_sockets_mode)
|
||||
if (config.many_sockets_mode == MSM_MANY_UNICAST)
|
||||
{
|
||||
pp->m_conn = ddsi_factory_create_conn (gv.m_factory, 0, NULL);
|
||||
ddsi_conn_locator (pp->m_conn, &pp->m_locator);
|
||||
}
|
||||
else
|
||||
{
|
||||
pp->m_conn = NULL;
|
||||
}
|
||||
|
||||
/* Before we create endpoints -- and may call unref_participant if
|
||||
things go wrong -- we must initialize all that unref_participant
|
||||
|
@ -573,7 +590,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis
|
|||
necessary. Must do in this order, or the receive thread won't
|
||||
find the new participant */
|
||||
|
||||
if (config.many_sockets_mode)
|
||||
if (config.many_sockets_mode == MSM_MANY_UNICAST)
|
||||
{
|
||||
os_atomic_fence ();
|
||||
os_atomic_inc32 (&gv.participant_set_generation);
|
||||
|
@ -778,7 +795,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
|
|||
if (--gv.nparticipants == 0)
|
||||
os_condBroadcast (&gv.participant_set_cond);
|
||||
os_mutexUnlock (&gv.participant_set_lock);
|
||||
if (config.many_sockets_mode)
|
||||
if (config.many_sockets_mode == MSM_MANY_UNICAST)
|
||||
{
|
||||
os_atomic_fence_rel ();
|
||||
os_atomic_inc32 (&gv.participant_set_generation);
|
||||
|
@ -794,6 +811,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui
|
|||
os_mutexDestroy (&pp->refc_lock);
|
||||
entity_common_fini (&pp->e);
|
||||
remove_deleted_participant_guid (&pp->e.guid, DPG_LOCAL);
|
||||
inverse_uint32_set_fini(&pp->avail_entityids.x);
|
||||
os_free (pp);
|
||||
}
|
||||
else
|
||||
|
@ -1069,7 +1087,7 @@ static void rebuild_trace_covered(int nreaders, int nlocs, const nn_locator_t *l
|
|||
for (i = 0; i < nlocs; i++)
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
locator_to_string_with_port(buf, &locs[i]);
|
||||
ddsi_locator_to_string(buf, sizeof(buf), &locs[i]);
|
||||
nn_log(LC_DISCOVERY, " loc %2d = %-20s %2d {", i, buf, locs_nrds[i]);
|
||||
for (j = 0; j < nreaders; j++)
|
||||
if (covered[j * nlocs + i] >= 0)
|
||||
|
@ -1090,10 +1108,10 @@ static int rebuild_select(int nlocs, const nn_locator_t *locs, const int *locs_n
|
|||
j = i; /* better coverage */
|
||||
else if (locs_nrds[i] == locs_nrds[j])
|
||||
{
|
||||
if (locs_nrds[i] == 1 && !is_mcaddr(&locs[i]))
|
||||
if (locs_nrds[i] == 1 && !ddsi_is_mcaddr(&locs[i]))
|
||||
j = i; /* prefer unicast for single nodes */
|
||||
#if DDSI_INCLUDE_SSM
|
||||
else if (is_ssm_mcaddr(&locs[i]))
|
||||
else if (ddsi_is_ssm_mcaddr(&locs[i]))
|
||||
j = i; /* "reader favours SSM": all else being equal, use SSM */
|
||||
#endif
|
||||
}
|
||||
|
@ -1106,7 +1124,7 @@ static void rebuild_add(struct addrset *newas, int locidx, int nreaders, int nlo
|
|||
char str[INET6_ADDRSTRLEN_EXTENDED];
|
||||
if (locs[locidx].kind != NN_LOCATOR_KIND_UDPv4MCGEN)
|
||||
{
|
||||
locator_to_string_with_port(str, &locs[locidx]);
|
||||
ddsi_locator_to_string(str, sizeof(str), &locs[locidx]);
|
||||
nn_log(LC_DISCOVERY, " simple %s\n", str);
|
||||
add_to_addrset(newas, &locs[locidx]);
|
||||
}
|
||||
|
@ -1125,7 +1143,7 @@ static void rebuild_add(struct addrset *newas, int locidx, int nreaders, int nlo
|
|||
iph |= 1u << covered[i * nlocs + locidx];
|
||||
ipn = htonl(iph);
|
||||
memcpy(l.address + 12, &ipn, 4);
|
||||
locator_to_string_with_port(str, &l);
|
||||
ddsi_locator_to_string(str, sizeof(str), &l);
|
||||
nn_log(LC_DISCOVERY, " mcgen %s\n", str);
|
||||
add_to_addrset(newas, &l);
|
||||
}
|
||||
|
@ -1202,6 +1220,41 @@ static void rebuild_writer_addrset (struct writer *wr)
|
|||
nn_log (LC_DISCOVERY, "\n");
|
||||
}
|
||||
|
||||
void rebuild_or_clear_writer_addrsets(int rebuild)
|
||||
{
|
||||
struct ephash_enum_writer est;
|
||||
struct writer *wr;
|
||||
struct addrset *empty = rebuild ? NULL : new_addrset();
|
||||
nn_log (LC_DISCOVERY, "rebuild_or_delete_writer_addrsets(%d)\n", rebuild);
|
||||
ephash_enum_writer_init (&est);
|
||||
os_rwlockRead (&gv.qoslock);
|
||||
while ((wr = ephash_enum_writer_next (&est)) != NULL)
|
||||
{
|
||||
os_mutexLock (&wr->e.lock);
|
||||
if (wr->e.guid.entityid.u != NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)
|
||||
{
|
||||
if (rebuild)
|
||||
rebuild_writer_addrset(wr);
|
||||
else
|
||||
addrset_purge(wr->as);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SPDP writers have no matched readers, instead they all use the same address space,
|
||||
gv.as_disc. Keep as_disc unchanged, and instead make the participants point to the
|
||||
empty one. */
|
||||
unref_addrset(wr->as);
|
||||
if (rebuild)
|
||||
wr->as = ref_addrset(gv.as_disc);
|
||||
else
|
||||
wr->as = ref_addrset(empty);
|
||||
}
|
||||
os_mutexUnlock (&wr->e.lock);
|
||||
}
|
||||
os_rwlockUnlock (&gv.qoslock);
|
||||
ephash_enum_writer_fini (&est);
|
||||
nn_log (LC_DISCOVERY, "rebuild_or_delete_writer_addrsets(%d) done\n", rebuild);
|
||||
}
|
||||
|
||||
static void free_wr_prd_match (struct wr_prd_match *m)
|
||||
{
|
||||
|
@ -1219,9 +1272,9 @@ static void free_rd_pwr_match (struct rd_pwr_match *m)
|
|||
#ifdef DDSI_INCLUDE_SSM
|
||||
if (!is_unspec_locator (&m->ssm_mc_loc))
|
||||
{
|
||||
assert (is_mcaddr (&m->ssm_mc_loc));
|
||||
assert (ddsi_is_mcaddr (&m->ssm_mc_loc));
|
||||
assert (!is_unspec_locator (&m->ssm_src_loc));
|
||||
if (ddsi_conn_leave_mc (gv.data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc) < 0)
|
||||
if (ddsi_leave_mc (gv.data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc) < 0)
|
||||
nn_log (LC_WARNING, "failed to leave network partition ssm group\n");
|
||||
}
|
||||
#endif
|
||||
|
@ -1666,7 +1719,7 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr,
|
|||
/* FIXME: for now, assume that the ports match for datasock_mc --
|
||||
't would be better to dynamically create and destroy sockets on
|
||||
an as needed basis. */
|
||||
ddsi_conn_join_mc (gv.data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc);
|
||||
ddsi_join_mc (gv.data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2335,6 +2388,8 @@ static void endpoint_common_init
|
|||
|
||||
static void endpoint_common_fini (struct entity_common *e, struct endpoint_common *c)
|
||||
{
|
||||
if (!is_builtin_entityid(e->guid.entityid, ownvendorid))
|
||||
pp_release_entityid(c->pp, e->guid.entityid);
|
||||
unref_participant (c->pp, &e->guid);
|
||||
entity_common_fini (e);
|
||||
}
|
||||
|
@ -2691,7 +2746,7 @@ static struct writer * new_writer_guid
|
|||
int have_loc = 0;
|
||||
if (wr->partition_id == 0)
|
||||
{
|
||||
if (is_ssm_mcaddr (&gv.loc_default_mc))
|
||||
if (ddsi_is_ssm_mcaddr (&gv.loc_default_mc))
|
||||
{
|
||||
loc = gv.loc_default_mc;
|
||||
have_loc = 1;
|
||||
|
@ -3070,11 +3125,11 @@ static struct addrset * get_as_from_mapping (const char *partition, const char *
|
|||
static void join_mcast_helper (const nn_locator_t *n, void * varg)
|
||||
{
|
||||
ddsi_tran_conn_t conn = (ddsi_tran_conn_t) varg;
|
||||
if (is_mcaddr (n))
|
||||
if (ddsi_is_mcaddr (n))
|
||||
{
|
||||
if (n->kind != NN_LOCATOR_KIND_UDPv4MCGEN)
|
||||
{
|
||||
if (ddsi_conn_join_mc (conn, NULL, n) < 0)
|
||||
if (ddsi_join_mc (conn, NULL, n) < 0)
|
||||
{
|
||||
nn_log (LC_WARNING, "failed to join network partition multicast group\n");
|
||||
}
|
||||
|
@ -3098,7 +3153,7 @@ static void join_mcast_helper (const nn_locator_t *n, void * varg)
|
|||
iph1 |= (i << l1.base);
|
||||
ipn = htonl(iph1);
|
||||
memcpy(l.address + 12, &ipn, 4);
|
||||
if (ddsi_conn_join_mc (conn, NULL, &l) < 0)
|
||||
if (ddsi_join_mc (conn, NULL, &l) < 0)
|
||||
{
|
||||
nn_log (LC_WARNING, "failed to join network partition multicast group\n");
|
||||
}
|
||||
|
@ -3112,11 +3167,11 @@ static void join_mcast_helper (const nn_locator_t *n, void * varg)
|
|||
static void leave_mcast_helper (const nn_locator_t *n, void * varg)
|
||||
{
|
||||
ddsi_tran_conn_t conn = (ddsi_tran_conn_t) varg;
|
||||
if (is_mcaddr (n))
|
||||
if (ddsi_is_mcaddr (n))
|
||||
{
|
||||
if (n->kind != NN_LOCATOR_KIND_UDPv4MCGEN)
|
||||
{
|
||||
if (ddsi_conn_leave_mc (conn, NULL, n) < 0)
|
||||
if (ddsi_leave_mc (conn, NULL, n) < 0)
|
||||
{
|
||||
nn_log (LC_WARNING, "failed to leave network partition multicast group\n");
|
||||
}
|
||||
|
@ -3140,7 +3195,7 @@ static void leave_mcast_helper (const nn_locator_t *n, void * varg)
|
|||
iph1 |= (i << l1.base);
|
||||
ipn = htonl(iph1);
|
||||
memcpy(l.address + 12, &ipn, 4);
|
||||
if (ddsi_conn_leave_mc (conn, NULL, &l) < 0)
|
||||
if (ddsi_leave_mc (conn, NULL, &l) < 0)
|
||||
{
|
||||
nn_log (LC_WARNING, "failed to leave network partition multicast group\n");
|
||||
}
|
||||
|
@ -3267,7 +3322,7 @@ static struct reader * new_reader_guid
|
|||
/* Note: SSM requires NETWORK_PARTITIONS; if network partitions
|
||||
do not override the default, we should check whether the
|
||||
default is an SSM address. */
|
||||
if (is_ssm_mcaddr (&gv.loc_default_mc) && config.allowMulticast & AMC_SSM)
|
||||
if (ddsi_is_ssm_mcaddr (&gv.loc_default_mc) && config.allowMulticast & AMC_SSM)
|
||||
rd->favours_ssm = 1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "ddsi/q_pcap.h"
|
||||
#include "ddsi/q_feature_check.h"
|
||||
#include "ddsi/q_debmon.h"
|
||||
#include "ddsi/q_init.h"
|
||||
|
||||
#include "ddsi/sysdeps.h"
|
||||
|
||||
|
@ -54,6 +55,8 @@
|
|||
#include "ddsi/ddsi_tran.h"
|
||||
#include "ddsi/ddsi_udp.h"
|
||||
#include "ddsi/ddsi_tcp.h"
|
||||
#include "ddsi/ddsi_raweth.h"
|
||||
#include "ddsi/ddsi_mcgroup.h"
|
||||
|
||||
#include "dds__tkmap.h"
|
||||
|
||||
|
@ -68,6 +71,17 @@ static void add_peer_addresses (struct addrset *as, const struct config_peer_lis
|
|||
|
||||
static int make_uc_sockets (uint32_t * pdisc, uint32_t * pdata, int ppid)
|
||||
{
|
||||
if (config.many_sockets_mode == MSM_NO_UNICAST)
|
||||
{
|
||||
assert (ppid == PARTICIPANT_INDEX_NONE);
|
||||
*pdata = *pdisc = (uint32_t) (config.port_base + config.port_dg * config.domainId);
|
||||
if (config.allowMulticast)
|
||||
{
|
||||
/* FIXME: ugly hack - but we'll fix up after creating the multicast sockets */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ppid >= 0)
|
||||
{
|
||||
/* FIXME: verify port numbers are in range instead of truncating them like this */
|
||||
|
@ -172,13 +186,13 @@ static int set_recvips (void)
|
|||
int i, have_selected = 0, have_others = 0;
|
||||
for (i = 0; config.networkRecvAddressStrings[i] != NULL; i++)
|
||||
{
|
||||
os_sockaddr_storage parsedaddr;
|
||||
if (!os_sockaddrStringToAddress (config.networkRecvAddressStrings[i], (os_sockaddr *) &parsedaddr, !config.useIpv6))
|
||||
nn_locator_t loc;
|
||||
if (ddsi_locator_from_string(&loc, config.networkRecvAddressStrings[i]) != AFSR_OK)
|
||||
{
|
||||
NN_ERROR ("%s: not a valid IP address\n", config.networkRecvAddressStrings[i]);
|
||||
NN_ERROR ("%s: not a valid address in DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses\n", config.networkRecvAddressStrings[i]);
|
||||
return -1;
|
||||
}
|
||||
if (os_sockaddrIPAddressEqual ((os_sockaddr *) &gv.interfaces[gv.selected_interface].addr, (os_sockaddr *) &parsedaddr))
|
||||
if (compare_locators(&loc, &gv.interfaces[gv.selected_interface].loc) == 0)
|
||||
have_selected = 1;
|
||||
else
|
||||
have_others = 1;
|
||||
|
@ -197,25 +211,24 @@ static int set_recvips (void)
|
|||
gv.recvips_mode = RECVIPS_MODE_SOME;
|
||||
for (i = 0; config.networkRecvAddressStrings[i] != NULL; i++)
|
||||
{
|
||||
os_sockaddr_storage parsedaddr;
|
||||
if (!os_sockaddrStringToAddress (config.networkRecvAddressStrings[i], (os_sockaddr *) &parsedaddr, !config.useIpv6))
|
||||
nn_locator_t loc;
|
||||
if (ddsi_locator_from_string(&loc, config.networkRecvAddressStrings[i]) != AFSR_OK)
|
||||
{
|
||||
NN_ERROR ("%s: not a valid IP address\n", config.networkRecvAddressStrings[i]);
|
||||
NN_ERROR ("%s: not a valid address in DDSI2EService/General/MulticastRecvNetworkInterfaceAddresses\n", config.networkRecvAddressStrings[i]);
|
||||
return -1;
|
||||
}
|
||||
for (j = 0; j < gv.n_interfaces; j++)
|
||||
{
|
||||
if (os_sockaddrIPAddressEqual ((os_sockaddr *) &gv.interfaces[j].addr, (os_sockaddr *) &parsedaddr))
|
||||
if (compare_locators(&loc, &gv.interfaces[j].loc) == 0)
|
||||
break;
|
||||
}
|
||||
if (j == gv.n_interfaces)
|
||||
{
|
||||
NN_ERROR ("No interface bound to requested address '%s'\n",
|
||||
config.networkRecvAddressStrings[i]);
|
||||
NN_ERROR ("No interface bound to requested address '%s'\n", config.networkRecvAddressStrings[i]);
|
||||
return -1;
|
||||
}
|
||||
*recvnode = os_malloc (sizeof (struct ospl_in_addr_node));
|
||||
(*recvnode)->addr = parsedaddr;
|
||||
(*recvnode)->loc = loc;
|
||||
recvnode = &(*recvnode)->next;
|
||||
*recvnode = NULL;
|
||||
}
|
||||
|
@ -232,61 +245,54 @@ static int set_recvips (void)
|
|||
* The return 0 means that the possible changes in 'loc' can be ignored. */
|
||||
static int string_to_default_locator (nn_locator_t *loc, const char *string, uint32_t port, int mc, const char *tag)
|
||||
{
|
||||
os_sockaddr_storage addr;
|
||||
if (strspn (string, " \t") == strlen (string))
|
||||
{
|
||||
/* string consisting of just spaces and/or tabs (that includes the empty string) is ignored */
|
||||
return 0;
|
||||
}
|
||||
else if (!os_sockaddrStringToAddress (string, (os_sockaddr *) &addr, !config.useIpv6))
|
||||
switch (ddsi_locator_from_string(loc, string))
|
||||
{
|
||||
NN_ERROR ("%s: not a valid IP address (%s)\n", string, tag);
|
||||
return -1;
|
||||
case AFSR_OK:
|
||||
break;
|
||||
case AFSR_INVALID:
|
||||
NN_ERROR ("%s: not a valid address (%s)\n", string, tag);
|
||||
return -1;
|
||||
case AFSR_UNKNOWN:
|
||||
NN_ERROR ("%s: address name resolution failure (%s)\n", string, tag);
|
||||
return -1;
|
||||
case AFSR_MISMATCH:
|
||||
NN_ERROR ("%s: invalid address kind (%s)\n", string, tag);
|
||||
return -1;
|
||||
}
|
||||
else if (!config.useIpv6 && addr.ss_family != AF_INET)
|
||||
{
|
||||
NN_ERROR ("%s: not a valid IPv4 address (%s)\n", string, tag);
|
||||
return -1;
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
else if (config.useIpv6 && addr.ss_family != AF_INET6)
|
||||
{
|
||||
NN_ERROR ("%s: not a valid IPv6 address (%s)\n", string, tag);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (port != 0 && !is_unspec_locator(loc))
|
||||
loc->port = port;
|
||||
else
|
||||
loc->port = NN_LOCATOR_PORT_INVALID;
|
||||
assert (mc == -1 || mc == 0 || mc == 1);
|
||||
if (mc >= 0)
|
||||
{
|
||||
nn_address_to_loc (loc, &addr, config.useIpv6 ? NN_LOCATOR_KIND_UDPv6 : NN_LOCATOR_KIND_UDPv4);
|
||||
if (port != 0 && !is_unspec_locator(loc))
|
||||
loc->port = port;
|
||||
assert (mc == -1 || mc == 0 || mc == 1);
|
||||
if (mc >= 0)
|
||||
const char *rel = mc ? "must" : "may not";
|
||||
const int ismc = is_unspec_locator (loc) || ddsi_is_mcaddr (loc);
|
||||
if (mc != ismc)
|
||||
{
|
||||
const char *unspecstr = config.useIpv6 ? "the IPv6 unspecified address (::0)" : "IPv4 ANY (0.0.0.0)";
|
||||
const char *rel = mc ? "must" : "may not";
|
||||
const int ismc = is_unspec_locator (loc) || is_mcaddr (loc);
|
||||
if (mc != ismc)
|
||||
{
|
||||
NN_ERROR ("%s: %s %s be %s or a multicast address\n", string, tag, rel, unspecstr);
|
||||
return -1;
|
||||
}
|
||||
NN_ERROR ("%s: %s %s be the unspecified address or a multicast address\n", string, tag, rel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_spdp_address (void)
|
||||
{
|
||||
const uint32_t port = (uint32_t) (config.port_base + config.port_dg * config.domainId + config.port_d0);
|
||||
int rc = 0;
|
||||
/* FIXME: FIXME: FIXME: */
|
||||
if (strcmp (config.spdpMulticastAddressString, "239.255.0.1") != 0)
|
||||
{
|
||||
if ((rc = string_to_default_locator (&gv.loc_spdp_mc, config.spdpMulticastAddressString, port, 1, "SPDP address")) < 0)
|
||||
return rc;
|
||||
}
|
||||
if (rc == 0)
|
||||
if (rc == 0 && gv.m_factory->m_connless) /* FIXME: connless the right one? */
|
||||
{
|
||||
/* There isn't a standard IPv6 multicast group for DDSI. For
|
||||
some reason, node-local multicast addresses seem to be
|
||||
|
@ -294,12 +300,11 @@ static int set_spdp_address (void)
|
|||
instead do link-local. I suppose we could use the hop limit
|
||||
to make it node-local. If other hosts reach us in some way,
|
||||
we'll of course respond. */
|
||||
const char *def = config.useIpv6 ? "ff02::ffff:239.255.0.1" : "239.255.0.1";
|
||||
rc = string_to_default_locator (&gv.loc_spdp_mc, def, port, 1, "SPDP address");
|
||||
rc = string_to_default_locator (&gv.loc_spdp_mc, gv.m_factory->m_default_spdp_address, port, 1, "SPDP address");
|
||||
assert (rc > 0);
|
||||
}
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
if (is_ssm_mcaddr (&gv.loc_spdp_mc))
|
||||
if (ddsi_is_ssm_mcaddr (&gv.loc_spdp_mc))
|
||||
{
|
||||
NN_ERROR ("%s: SPDP address may not be an SSM address\n", config.spdpMulticastAddressString);
|
||||
return -1;
|
||||
|
@ -338,31 +343,31 @@ static int set_ext_address_and_mask (void)
|
|||
int rc;
|
||||
|
||||
if (!config.externalAddressString)
|
||||
gv.extip = gv.ownip;
|
||||
gv.extloc = gv.ownloc;
|
||||
else if ((rc = string_to_default_locator (&loc, config.externalAddressString, 0, 0, "external address")) < 0)
|
||||
return rc;
|
||||
else if (rc == 0) {
|
||||
NN_WARNING ("Ignoring ExternalNetworkAddress %s\n", config.externalAddressString);
|
||||
gv.extip = gv.ownip;
|
||||
gv.extloc = gv.ownloc;
|
||||
} else {
|
||||
nn_loc_to_address (&gv.extip, &loc);
|
||||
gv.extloc = loc;
|
||||
}
|
||||
|
||||
if (!config.externalMaskString || strcmp (config.externalMaskString, "0.0.0.0") == 0)
|
||||
gv.extmask.s_addr = 0;
|
||||
else if (config.useIpv6)
|
||||
{
|
||||
memset(&gv.extmask.address, 0, sizeof(gv.extmask.address));
|
||||
gv.extmask.kind = NN_LOCATOR_KIND_INVALID;
|
||||
gv.extmask.port = NN_LOCATOR_PORT_INVALID;
|
||||
}
|
||||
else if (config.transport_selector != TRANS_UDP)
|
||||
{
|
||||
NN_ERROR ("external network masks only supported in IPv4 mode\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sockaddr_storage addr;
|
||||
if ((rc = string_to_default_locator (&loc, config.externalMaskString, 0, -1, "external mask")) < 0)
|
||||
if ((rc = string_to_default_locator (&gv.extmask, config.externalMaskString, 0, -1, "external mask")) < 0)
|
||||
return rc;
|
||||
nn_loc_to_address(&addr, &loc);
|
||||
assert (addr.ss_family == AF_INET);
|
||||
gv.extmask = ((const os_sockaddr_in *) &addr)->sin_addr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -477,7 +482,7 @@ int rtps_config_prep (struct cfgst *cfgst)
|
|||
goto err_config_late_error;
|
||||
}
|
||||
|
||||
if (config.besmode == BESMODE_MINIMAL && config.many_sockets_mode)
|
||||
if (config.besmode == BESMODE_MINIMAL && config.many_sockets_mode == MSM_MANY_UNICAST)
|
||||
{
|
||||
/* These two are incompatible because minimal bes mode can result
|
||||
in implicitly creating proxy participants inheriting the
|
||||
|
@ -491,7 +496,7 @@ int rtps_config_prep (struct cfgst *cfgst)
|
|||
|
||||
/* Dependencies between default values is not handled
|
||||
automatically by the config processing (yet) */
|
||||
if (config.many_sockets_mode)
|
||||
if (config.many_sockets_mode == MSM_MANY_UNICAST)
|
||||
{
|
||||
if (config.max_participants == 0)
|
||||
config.max_participants = 100;
|
||||
|
@ -559,7 +564,7 @@ int rtps_config_prep (struct cfgst *cfgst)
|
|||
num_channels++;
|
||||
num_channel_threads += 2; /* xmit and dqueue */
|
||||
|
||||
if (config.useIpv6 && chptr->diffserv_field != 0)
|
||||
if (config.transport_selector != TRANS_UDP && chptr->diffserv_field != 0)
|
||||
{
|
||||
NN_ERROR ("channel %s specifies IPv4 DiffServ settings which is incompatible with IPv6 use\n",
|
||||
chptr->name);
|
||||
|
@ -611,28 +616,6 @@ int rtps_config_prep (struct cfgst *cfgst)
|
|||
|
||||
/* Now the per-thread-log-buffers are set up, so print the configuration */
|
||||
config_print_cfgst (cfgst);
|
||||
|
||||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
/* Convert address sets in partition mappings from string to address sets */
|
||||
{
|
||||
const int port = config.port_base + config.port_dg * config.domainId + config.port_d2;
|
||||
struct config_networkpartition_listelem *np;
|
||||
for (np = config.networkPartitions; np; np = np->next)
|
||||
{
|
||||
static const char msgtag_fixed[] = ": partition address";
|
||||
size_t slen = strlen (np->name) + sizeof (msgtag_fixed);
|
||||
char * msgtag = os_malloc (slen);
|
||||
int rc;
|
||||
(void) snprintf (msgtag, slen, "%s%s", np->name, msgtag_fixed);
|
||||
np->as = new_addrset ();
|
||||
rc = add_addresses_to_addrset (np->as, np->address_string, port, msgtag, 1);
|
||||
os_free (msgtag);
|
||||
if (rc < 0)
|
||||
goto err_config_late_error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
err_config_late_error:
|
||||
|
@ -647,23 +630,23 @@ struct joinleave_spdp_defmcip_helper_arg {
|
|||
static void joinleave_spdp_defmcip_helper (const nn_locator_t *loc, void *varg)
|
||||
{
|
||||
struct joinleave_spdp_defmcip_helper_arg *arg = varg;
|
||||
if (!is_mcaddr (loc))
|
||||
if (!ddsi_is_mcaddr (loc))
|
||||
return;
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
/* Can't join SSM until we actually have a source */
|
||||
if (is_ssm_mcaddr (loc))
|
||||
if (ddsi_is_ssm_mcaddr (loc))
|
||||
return;
|
||||
#endif
|
||||
if (arg->dojoin) {
|
||||
if (ddsi_conn_join_mc (gv.disc_conn_mc, NULL, loc) < 0 || ddsi_conn_join_mc (gv.data_conn_mc, NULL, loc) < 0)
|
||||
if (ddsi_join_mc (gv.disc_conn_mc, NULL, loc) < 0 || ddsi_join_mc (gv.data_conn_mc, NULL, loc) < 0)
|
||||
arg->errcount++;
|
||||
} else {
|
||||
if (ddsi_conn_leave_mc (gv.disc_conn_mc, NULL, loc) < 0 || ddsi_conn_leave_mc (gv.data_conn_mc, NULL, loc) < 0)
|
||||
if (ddsi_leave_mc (gv.disc_conn_mc, NULL, loc) < 0 || ddsi_leave_mc (gv.data_conn_mc, NULL, loc) < 0)
|
||||
arg->errcount++;
|
||||
}
|
||||
}
|
||||
|
||||
static int joinleave_spdp_defmcip (int dojoin)
|
||||
int joinleave_spdp_defmcip (int dojoin)
|
||||
{
|
||||
/* Addrset provides an easy way to filter out duplicates */
|
||||
struct joinleave_spdp_defmcip_helper_arg arg;
|
||||
|
@ -684,6 +667,43 @@ static int joinleave_spdp_defmcip (int dojoin)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int create_multicast_sockets(void)
|
||||
{
|
||||
ddsi_tran_qos_t qos = ddsi_tran_create_qos ();
|
||||
ddsi_tran_conn_t disc, data;
|
||||
uint32_t port;
|
||||
qos->m_multicast = 1;
|
||||
|
||||
/* FIXME: should check for overflow */
|
||||
port = (uint32_t) (config.port_base + config.port_dg * config.domainId + config.port_d0);
|
||||
if ((disc = ddsi_factory_create_conn (gv.m_factory, port, qos)) == NULL)
|
||||
goto err_disc;
|
||||
if (config.many_sockets_mode == MSM_NO_UNICAST)
|
||||
{
|
||||
/* FIXME: not quite logical to tie this to "no unicast" */
|
||||
data = disc;
|
||||
}
|
||||
else
|
||||
{
|
||||
port = (uint32_t) (config.port_base + config.port_dg * config.domainId + config.port_d2);
|
||||
if ((data = ddsi_factory_create_conn (gv.m_factory, port, qos)) == NULL)
|
||||
goto err_data;
|
||||
}
|
||||
ddsi_tran_free_qos (qos);
|
||||
|
||||
gv.disc_conn_mc = disc;
|
||||
gv.data_conn_mc = data;
|
||||
TRACE (("Multicast Ports: discovery %d data %d \n",
|
||||
ddsi_tran_port (gv.disc_conn_mc), ddsi_tran_port (gv.data_conn_mc)));
|
||||
return 1;
|
||||
|
||||
err_data:
|
||||
ddsi_conn_free (disc);
|
||||
err_disc:
|
||||
ddsi_tran_free_qos (qos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtps_init (void)
|
||||
{
|
||||
uint32_t port_disc_uc = 0;
|
||||
|
@ -726,25 +746,39 @@ int rtps_init (void)
|
|||
}
|
||||
|
||||
/* Initialize UDP or TCP transport and resolve factory */
|
||||
|
||||
if (!config.tcp_enable)
|
||||
switch (config.transport_selector)
|
||||
{
|
||||
config.publish_uc_locators = true;
|
||||
if (ddsi_udp_init () < 0)
|
||||
goto err_udp_tcp_init;
|
||||
gv.m_factory = ddsi_factory_find ("udp");
|
||||
}
|
||||
else
|
||||
{
|
||||
config.publish_uc_locators = (config.tcp_port == -1) ? false : true;
|
||||
/* TCP affects what features are supported/required */
|
||||
config.suppress_spdp_multicast = true;
|
||||
config.many_sockets_mode = false;
|
||||
config.allowMulticast = AMC_FALSE;
|
||||
|
||||
if (ddsi_tcp_init () < 0)
|
||||
goto err_udp_tcp_init;
|
||||
gv.m_factory = ddsi_factory_find ("tcp");
|
||||
case TRANS_DEFAULT:
|
||||
assert(0);
|
||||
case TRANS_UDP:
|
||||
case TRANS_UDP6:
|
||||
config.publish_uc_locators = 1;
|
||||
config.enable_uc_locators = 1;
|
||||
if (ddsi_udp_init () < 0)
|
||||
goto err_udp_tcp_init;
|
||||
gv.m_factory = ddsi_factory_find (config.transport_selector == TRANS_UDP ? "udp" : "udp6");
|
||||
break;
|
||||
case TRANS_TCP:
|
||||
case TRANS_TCP6:
|
||||
config.publish_uc_locators = (config.tcp_port != -1);
|
||||
config.enable_uc_locators = 1;
|
||||
/* TCP affects what features are supported/required */
|
||||
config.suppress_spdp_multicast = 1;
|
||||
config.many_sockets_mode = MSM_SINGLE_UNICAST;
|
||||
config.allowMulticast = AMC_FALSE;
|
||||
if (ddsi_tcp_init () < 0)
|
||||
goto err_udp_tcp_init;
|
||||
gv.m_factory = ddsi_factory_find (config.transport_selector == TRANS_TCP ? "tcp" : "tcp6");
|
||||
break;
|
||||
case TRANS_RAWETH:
|
||||
config.publish_uc_locators = 1;
|
||||
config.enable_uc_locators = 0;
|
||||
config.participantIndex = PARTICIPANT_INDEX_NONE;
|
||||
config.many_sockets_mode = MSM_NO_UNICAST;
|
||||
if (ddsi_raweth_init () < 0)
|
||||
goto err_udp_tcp_init;
|
||||
gv.m_factory = ddsi_factory_find ("raweth");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!find_own_ip (config.networkAddressString))
|
||||
|
@ -777,22 +811,43 @@ int rtps_init (void)
|
|||
goto err_set_ext_address;
|
||||
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
nn_log (LC_CONFIG, "ownip: %s\n", sockaddr_to_string_no_port (buf, &gv.ownip));
|
||||
nn_log (LC_CONFIG, "extip: %s\n", sockaddr_to_string_no_port (buf, &gv.extip));
|
||||
(void)inet_ntop(AF_INET, &gv.extmask, buf, sizeof(buf));
|
||||
nn_log (LC_CONFIG, "extmask: %s%s\n", buf, config.useIpv6 ? " (not applicable)" : "");
|
||||
char buf[DDSI_LOCSTRLEN];
|
||||
/* the "ownip", "extip" labels in the trace have been there for so long, that it seems worthwhile to retain them even though they need not be IP any longer */
|
||||
nn_log (LC_CONFIG, "ownip: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.ownloc));
|
||||
nn_log (LC_CONFIG, "extip: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.extloc));
|
||||
nn_log (LC_CONFIG, "extmask: %s%s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.extmask), gv.m_factory->m_kind != NN_LOCATOR_KIND_UDPv4 ? " (not applicable)" : "");
|
||||
nn_log (LC_CONFIG, "networkid: 0x%lx\n", (unsigned long) gv.myNetworkId);
|
||||
nn_log (LC_CONFIG, "SPDP MC: %s\n", locator_to_string_no_port (buf, &gv.loc_spdp_mc));
|
||||
nn_log (LC_CONFIG, "default MC: %s\n", locator_to_string_no_port (buf, &gv.loc_default_mc));
|
||||
nn_log (LC_CONFIG, "SPDP MC: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.loc_spdp_mc));
|
||||
nn_log (LC_CONFIG, "default MC: %s\n", ddsi_locator_to_string_no_port (buf, sizeof(buf), &gv.loc_default_mc));
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
nn_log (LC_CONFIG, "SSM support included\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (gv.ownip.ss_family != gv.extip.ss_family)
|
||||
if (gv.ownloc.kind != gv.extloc.kind)
|
||||
NN_FATAL ("mismatch between network address kinds\n");
|
||||
|
||||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
/* Convert address sets in partition mappings from string to address sets */
|
||||
{
|
||||
const int port = config.port_base + config.port_dg * config.domainId + config.port_d2;
|
||||
struct config_networkpartition_listelem *np;
|
||||
for (np = config.networkPartitions; np; np = np->next)
|
||||
{
|
||||
static const char msgtag_fixed[] = ": partition address";
|
||||
size_t slen = strlen (np->name) + sizeof (msgtag_fixed);
|
||||
char * msgtag = os_malloc (slen);
|
||||
int rc;
|
||||
snprintf (msgtag, slen, "%s%s", np->name, msgtag_fixed);
|
||||
np->as = new_addrset ();
|
||||
rc = add_addresses_to_addrset (np->as, np->address_string, port, msgtag, 1);
|
||||
os_free (msgtag);
|
||||
if (rc < 0)
|
||||
goto err_network_partition_addrset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gv.startup_mode = (config.startup_mode_duration > 0) ? 1 : 0;
|
||||
nn_log (LC_CONFIG, "startup-mode: %s\n", gv.startup_mode ? "enabled" : "disabled");
|
||||
|
||||
|
@ -831,7 +886,7 @@ int rtps_init (void)
|
|||
gv.privileged_pp = NULL;
|
||||
|
||||
/* Template PP guid -- protected by privileged_pp_lock for simplicity */
|
||||
gv.next_ppguid.prefix.u[0] = sockaddr_to_hopefully_unique_uint32 (&gv.ownip);
|
||||
gv.next_ppguid.prefix.u[0] = locator_to_hopefully_unique_uint32 (&gv.ownloc);
|
||||
gv.next_ppguid.prefix.u[1] = (unsigned) os_procIdSelf ();
|
||||
gv.next_ppguid.prefix.u[2] = 1;
|
||||
gv.next_ppguid.entityid.u = NN_ENTITYID_PARTICIPANT;
|
||||
|
@ -901,32 +956,23 @@ int rtps_init (void)
|
|||
gv.pcap_fp = NULL;
|
||||
}
|
||||
|
||||
gv.mship = new_group_membership();
|
||||
|
||||
if (gv.m_factory->m_connless)
|
||||
{
|
||||
uint32_t port;
|
||||
|
||||
TRACE (("Unicast Ports: discovery %u data %u \n",
|
||||
ddsi_tran_port (gv.disc_conn_uc), ddsi_tran_port (gv.data_conn_uc)));
|
||||
if (!(config.many_sockets_mode == MSM_NO_UNICAST && config.allowMulticast))
|
||||
TRACE (("Unicast Ports: discovery %d data %d\n", ddsi_tran_port (gv.disc_conn_uc), ddsi_tran_port (gv.data_conn_uc)));
|
||||
|
||||
if (config.allowMulticast)
|
||||
{
|
||||
ddsi_tran_qos_t qos = ddsi_tran_create_qos ();
|
||||
qos->m_multicast = true;
|
||||
|
||||
/* FIXME: should check for overflow */
|
||||
port = (uint32_t) (config.port_base + config.port_dg * config.domainId + config.port_d0);
|
||||
gv.disc_conn_mc = ddsi_factory_create_conn (gv.m_factory, port, qos);
|
||||
|
||||
port = (uint32_t) (config.port_base + config.port_dg * config.domainId + config.port_d2);
|
||||
gv.data_conn_mc = ddsi_factory_create_conn (gv.m_factory, port, qos);
|
||||
|
||||
ddsi_tran_free_qos (qos);
|
||||
|
||||
if (gv.disc_conn_mc == NULL || gv.data_conn_mc == NULL)
|
||||
if (!create_multicast_sockets())
|
||||
goto err_mc_conn;
|
||||
|
||||
TRACE (("Multicast Ports: discovery %u data %u \n",
|
||||
ddsi_tran_port (gv.disc_conn_mc), ddsi_tran_port (gv.data_conn_mc)));
|
||||
if (config.many_sockets_mode == MSM_NO_UNICAST)
|
||||
{
|
||||
gv.data_conn_uc = gv.data_conn_mc;
|
||||
gv.disc_conn_uc = gv.disc_conn_mc;
|
||||
}
|
||||
|
||||
/* Set multicast locators */
|
||||
if (!is_unspec_locator(&gv.loc_spdp_mc))
|
||||
|
@ -1122,18 +1168,16 @@ int rtps_init (void)
|
|||
err_mc_conn:
|
||||
if (gv.disc_conn_mc)
|
||||
ddsi_conn_free (gv.disc_conn_mc);
|
||||
if (gv.data_conn_mc)
|
||||
if (gv.data_conn_mc && gv.data_conn_mc != gv.disc_conn_mc)
|
||||
ddsi_conn_free (gv.data_conn_mc);
|
||||
if (gv.pcap_fp)
|
||||
os_mutexDestroy (&gv.pcap_lock);
|
||||
os_sockWaitsetFree (gv.waitset);
|
||||
if (gv.disc_conn_uc == gv.data_conn_uc)
|
||||
if (gv.disc_conn_uc != gv.disc_conn_mc)
|
||||
ddsi_conn_free (gv.data_conn_uc);
|
||||
else
|
||||
{
|
||||
if (gv.data_conn_uc != gv.disc_conn_uc)
|
||||
ddsi_conn_free (gv.data_conn_uc);
|
||||
ddsi_conn_free (gv.disc_conn_uc);
|
||||
}
|
||||
free_group_membership(gv.mship);
|
||||
err_unicast_sockets:
|
||||
dds_tkmap_free (gv.m_tkmap);
|
||||
nn_reorder_free (gv.spdp_reorder);
|
||||
|
@ -1164,6 +1208,9 @@ err_unicast_sockets:
|
|||
ddsi_serstatepool_free (gv.serpool);
|
||||
nn_xmsgpool_free (gv.xmsgpool);
|
||||
(ddsi_plugin.fini_fn) ();
|
||||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||
err_network_partition_addrset:
|
||||
#endif
|
||||
err_set_ext_address:
|
||||
while (gv.recvips)
|
||||
{
|
||||
|
@ -1404,6 +1451,7 @@ void rtps_term (void)
|
|||
|
||||
/* Not freeing gv.tev_conn: it aliases data_conn_uc */
|
||||
|
||||
free_group_membership(gv.mship);
|
||||
ddsi_tran_factories_fini ();
|
||||
|
||||
if (gv.pcap_fp)
|
||||
|
|
168
src/core/ddsi/src/q_inverse_uint32_set.c
Normal file
168
src/core/ddsi/src/q_inverse_uint32_set.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include "os/os.h"
|
||||
#include "util/ut_avl.h"
|
||||
#include "ddsi/q_config.h"
|
||||
#include "ddsi/q_log.h"
|
||||
#include "ddsi/q_inverse_uint32_set.h"
|
||||
|
||||
static int uint32_t_cmp(const void *va, const void *vb);
|
||||
|
||||
static ut_avlTreedef_t inverse_uint32_set_td = UT_AVL_TREEDEF_INITIALIZER(offsetof(struct inverse_uint32_set_node, avlnode), offsetof(struct inverse_uint32_set_node, min), uint32_t_cmp, 0);
|
||||
|
||||
static int uint32_t_cmp(const void *va, const void *vb)
|
||||
{
|
||||
const uint32_t *a = va;
|
||||
const uint32_t *b = vb;
|
||||
return (*a == *b) ? 0 : (*a < *b) ? -1 : 1;
|
||||
}
|
||||
|
||||
static void check(const struct inverse_uint32_set *set)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
ut_avlIter_t it;
|
||||
struct inverse_uint32_set_node *pn = NULL, *n;
|
||||
assert(set->min <= set->max);
|
||||
assert(set->cursor >= set->min);
|
||||
assert(set->cursor <= set->max);
|
||||
for (n = ut_avlIterFirst(&inverse_uint32_set_td, &set->ids, &it); n; pn = n, n = ut_avlIterNext(&it))
|
||||
{
|
||||
assert(n->min <= n->max);
|
||||
assert(n->min >= set->min);
|
||||
assert(n->max <= set->max);
|
||||
assert(pn == NULL || n->min > pn->max+1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void inverse_uint32_set_init(struct inverse_uint32_set *set, uint32_t min, uint32_t max)
|
||||
{
|
||||
struct inverse_uint32_set_node *n;
|
||||
ut_avlInit(&inverse_uint32_set_td, &set->ids);
|
||||
set->cursor = min;
|
||||
set->min = min;
|
||||
set->max = max;
|
||||
n = os_malloc(sizeof(*n));
|
||||
n->min = min;
|
||||
n->max = max;
|
||||
ut_avlInsert(&inverse_uint32_set_td, &set->ids, n);
|
||||
check(set);
|
||||
}
|
||||
|
||||
void inverse_uint32_set_fini(struct inverse_uint32_set *set)
|
||||
{
|
||||
ut_avlFree(&inverse_uint32_set_td, &set->ids, os_free);
|
||||
}
|
||||
|
||||
static uint32_t inverse_uint32_set_alloc_use_min(struct inverse_uint32_set *set, struct inverse_uint32_set_node *n)
|
||||
{
|
||||
const uint32_t id = n->min;
|
||||
if (n->min == n->max)
|
||||
{
|
||||
ut_avlDelete(&inverse_uint32_set_td, &set->ids, n);
|
||||
os_free(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* changing the key in-place here: the key value may be changing, but the structure of the tree is not */
|
||||
n->min++;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
int inverse_uint32_set_alloc(uint32_t * const id, struct inverse_uint32_set *set)
|
||||
{
|
||||
struct inverse_uint32_set_node *n;
|
||||
if ((n = ut_avlLookupPredEq(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL && set->cursor <= n->max) {
|
||||
/* n is [a,b] s.t. a <= C <= b, so C is available */
|
||||
*id = set->cursor;
|
||||
if (n->min == set->cursor)
|
||||
{
|
||||
(void)inverse_uint32_set_alloc_use_min(set, n);
|
||||
}
|
||||
else if (set->cursor == n->max)
|
||||
{
|
||||
assert(n->min < n->max);
|
||||
n->max--;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct inverse_uint32_set_node *n1 = os_malloc(sizeof(*n1));
|
||||
assert(n->min < set->cursor && set->cursor < n->max);
|
||||
n1->min = set->cursor + 1;
|
||||
n1->max = n->max;
|
||||
n->max = set->cursor - 1;
|
||||
ut_avlInsert(&inverse_uint32_set_td, &set->ids, n1);
|
||||
}
|
||||
}
|
||||
else if ((n = ut_avlLookupSucc(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL)
|
||||
{
|
||||
/* n is [a,b] s.t. a > C and all intervals [a',b'] in tree have a' <= C */
|
||||
*id = inverse_uint32_set_alloc_use_min(set, n);
|
||||
}
|
||||
else if ((n = ut_avlFindMin(&inverse_uint32_set_td, &set->ids)) != NULL)
|
||||
{
|
||||
/* no available ids >= cursor: wrap around and use the first available */
|
||||
assert(n->max < set->cursor);
|
||||
*id = inverse_uint32_set_alloc_use_min(set, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
assert(*id >= set->min);
|
||||
set->cursor = (*id < set->max) ? (*id + 1) : set->min;
|
||||
check(set);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id)
|
||||
{
|
||||
struct inverse_uint32_set_node *n;
|
||||
const uint32_t idp1 = id + 1;
|
||||
ut_avlIPath_t ip;
|
||||
if ((n = ut_avlLookupPredEq(&inverse_uint32_set_td, &set->ids, &id)) != NULL && id <= n->max + 1) {
|
||||
if (id <= n->max)
|
||||
{
|
||||
/* n is [a,b] s.t. a <= I <= b: so it is already in the set */
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct inverse_uint32_set_node *n1;
|
||||
ut_avlDPath_t dp;
|
||||
/* grow the interval, possibly coalesce with next */
|
||||
if ((n1 = ut_avlLookupDPath(&inverse_uint32_set_td, &set->ids, &idp1, &dp)) == NULL) {
|
||||
n->max = id;
|
||||
} else {
|
||||
n->max = n1->max;
|
||||
ut_avlDeleteDPath(&inverse_uint32_set_td, &set->ids, n1, &dp);
|
||||
os_free(n1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((n = ut_avlLookupIPath(&inverse_uint32_set_td, &set->ids, &idp1, &ip)) != NULL) {
|
||||
/* changing the key in-place here: the key value may be changing, but the structure of the tree is not or the previous case would have applied */
|
||||
n->min = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no adjacent interval */
|
||||
n = os_malloc(sizeof(*n));
|
||||
n->min = n->max = id;
|
||||
ut_avlInsertIPath(&inverse_uint32_set_td, &set->ids, n, &ip);
|
||||
}
|
||||
check(set);
|
||||
}
|
||||
|
|
@ -30,341 +30,30 @@
|
|||
#include "ddsi/q_misc.h"
|
||||
#include "ddsi/q_addrset.h" /* unspec locator */
|
||||
#include "ddsi/q_feature_check.h"
|
||||
#include "ddsi/ddsi_ipaddr.h"
|
||||
#include "util/ut_avl.h"
|
||||
|
||||
|
||||
struct nn_group_membership_node {
|
||||
ut_avlNode_t avlnode;
|
||||
os_socket sock;
|
||||
os_sockaddr_storage srcip;
|
||||
os_sockaddr_storage mcip;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
struct nn_group_membership {
|
||||
os_mutex lock;
|
||||
ut_avlTree_t mships;
|
||||
};
|
||||
|
||||
static int sockaddr_compare_no_port (const os_sockaddr_storage *as, const os_sockaddr_storage *bs)
|
||||
{
|
||||
if (as->ss_family != bs->ss_family)
|
||||
return (as->ss_family < bs->ss_family) ? -1 : 1;
|
||||
else if (as->ss_family == 0)
|
||||
return 0; /* unspec address */
|
||||
else if (as->ss_family == AF_INET)
|
||||
{
|
||||
const os_sockaddr_in *a = (const os_sockaddr_in *) as;
|
||||
const os_sockaddr_in *b = (const os_sockaddr_in *) bs;
|
||||
if (a->sin_addr.s_addr != b->sin_addr.s_addr)
|
||||
return (a->sin_addr.s_addr < b->sin_addr.s_addr) ? -1 : 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
else if (as->ss_family == AF_INET6)
|
||||
{
|
||||
const os_sockaddr_in6 *a = (const os_sockaddr_in6 *) as;
|
||||
const os_sockaddr_in6 *b = (const os_sockaddr_in6 *) bs;
|
||||
int c;
|
||||
if ((c = memcmp (&a->sin6_addr, &b->sin6_addr, 16)) != 0)
|
||||
return c;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
assert (0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int cmp_group_membership (const void *va, const void *vb)
|
||||
{
|
||||
const struct nn_group_membership_node *a = va;
|
||||
const struct nn_group_membership_node *b = vb;
|
||||
int c;
|
||||
if (a->sock < b->sock)
|
||||
return -1;
|
||||
else if (a->sock > b->sock)
|
||||
return 1;
|
||||
else if ((c = sockaddr_compare_no_port (&a->srcip, &b->srcip)) != 0)
|
||||
return c;
|
||||
else if ((c = sockaddr_compare_no_port (&a->mcip, &b->mcip)) != 0)
|
||||
return c;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ut_avlTreedef_t mship_td = UT_AVL_TREEDEF_INITIALIZER(offsetof (struct nn_group_membership_node, avlnode), 0, cmp_group_membership, 0);
|
||||
|
||||
struct nn_group_membership *new_group_membership (void)
|
||||
{
|
||||
struct nn_group_membership *mship = os_malloc (sizeof (*mship));
|
||||
os_mutexInit (&mship->lock);
|
||||
ut_avlInit (&mship_td, &mship->mships);
|
||||
return mship;
|
||||
}
|
||||
|
||||
void free_group_membership (struct nn_group_membership *mship)
|
||||
{
|
||||
ut_avlFree (&mship_td, &mship->mships, os_free);
|
||||
os_mutexDestroy (&mship->lock);
|
||||
os_free (mship);
|
||||
}
|
||||
|
||||
static int reg_group_membership (struct nn_group_membership *mship, os_socket sock, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip)
|
||||
{
|
||||
struct nn_group_membership_node key, *n;
|
||||
ut_avlIPath_t ip;
|
||||
int isnew;
|
||||
key.sock = sock;
|
||||
if (srcip)
|
||||
key.srcip = *srcip;
|
||||
else
|
||||
memset (&key.srcip, 0, sizeof (key.srcip));
|
||||
key.mcip = *mcip;
|
||||
if ((n = ut_avlLookupIPath (&mship_td, &mship->mships, &key, &ip)) != NULL) {
|
||||
isnew = 0;
|
||||
n->count++;
|
||||
} else {
|
||||
isnew = 1;
|
||||
n = os_malloc (sizeof (*n));
|
||||
n->sock = sock;
|
||||
n->srcip = key.srcip;
|
||||
n->mcip = key.mcip;
|
||||
n->count = 1;
|
||||
ut_avlInsertIPath (&mship_td, &mship->mships, n, &ip);
|
||||
}
|
||||
return isnew;
|
||||
}
|
||||
|
||||
static int unreg_group_membership (struct nn_group_membership *mship, os_socket sock, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip)
|
||||
{
|
||||
struct nn_group_membership_node key, *n;
|
||||
ut_avlDPath_t dp;
|
||||
int mustdel;
|
||||
key.sock = sock;
|
||||
if (srcip)
|
||||
key.srcip = *srcip;
|
||||
else
|
||||
memset (&key.srcip, 0, sizeof (key.srcip));
|
||||
key.mcip = *mcip;
|
||||
n = ut_avlLookupDPath (&mship_td, &mship->mships, &key, &dp);
|
||||
assert (n != NULL);
|
||||
assert (n->count > 0);
|
||||
if (--n->count > 0)
|
||||
mustdel = 0;
|
||||
else
|
||||
{
|
||||
mustdel = 1;
|
||||
ut_avlDeleteDPath (&mship_td, &mship->mships, n, &dp);
|
||||
os_free (n);
|
||||
}
|
||||
return mustdel;
|
||||
}
|
||||
|
||||
void nn_loc_to_address (os_sockaddr_storage *dst, const nn_locator_t *src)
|
||||
{
|
||||
memset (dst, 0, sizeof (*dst));
|
||||
switch (src->kind)
|
||||
{
|
||||
case NN_LOCATOR_KIND_INVALID:
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
dst->ss_family = config.useIpv6 ? AF_INET6 : AF_INET;
|
||||
#else
|
||||
dst->ss_family = AF_INET;
|
||||
#endif
|
||||
break;
|
||||
case NN_LOCATOR_KIND_UDPv4:
|
||||
case NN_LOCATOR_KIND_TCPv4:
|
||||
{
|
||||
os_sockaddr_in *x = (os_sockaddr_in *) dst;
|
||||
x->sin_family = AF_INET;
|
||||
x->sin_port = htons ((unsigned short) src->port);
|
||||
memcpy (&x->sin_addr.s_addr, src->address + 12, 4);
|
||||
break;
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case NN_LOCATOR_KIND_UDPv6:
|
||||
case NN_LOCATOR_KIND_TCPv6:
|
||||
{
|
||||
os_sockaddr_in6 *x = (os_sockaddr_in6 *) dst;
|
||||
x->sin6_family = AF_INET6;
|
||||
x->sin6_port = htons ((unsigned short) src->port);
|
||||
memcpy (&x->sin6_addr.s6_addr, src->address, 16);
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&x->sin6_addr))
|
||||
{
|
||||
x->sin6_scope_id = gv.interfaceNo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case NN_LOCATOR_KIND_UDPv4MCGEN:
|
||||
NN_ERROR ("nn_address_to_loc: kind %x unsupported\n", src->kind);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void nn_address_to_loc (nn_locator_t *dst, const os_sockaddr_storage *src, int32_t kind)
|
||||
{
|
||||
dst->kind = kind;
|
||||
switch (src->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
const os_sockaddr_in *x = (const os_sockaddr_in *) src;
|
||||
assert (kind == NN_LOCATOR_KIND_UDPv4 || kind == NN_LOCATOR_KIND_TCPv4);
|
||||
if (x->sin_addr.s_addr == htonl (INADDR_ANY))
|
||||
set_unspec_locator (dst);
|
||||
else
|
||||
{
|
||||
dst->port = ntohs (x->sin_port);
|
||||
memset (dst->address, 0, 12);
|
||||
memcpy (dst->address + 12, &x->sin_addr.s_addr, 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case AF_INET6:
|
||||
{
|
||||
const os_sockaddr_in6 *x = (const os_sockaddr_in6 *) src;
|
||||
assert (kind == NN_LOCATOR_KIND_UDPv6 || kind == NN_LOCATOR_KIND_TCPv6);
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&x->sin6_addr))
|
||||
set_unspec_locator (dst);
|
||||
else
|
||||
{
|
||||
dst->port = ntohs (x->sin6_port);
|
||||
memcpy (dst->address, &x->sin6_addr.s6_addr, 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
NN_FATAL ("nn_address_to_loc: family %d unsupported\n", (int) src->ss_family);
|
||||
}
|
||||
}
|
||||
|
||||
void print_sockerror (const char *msg)
|
||||
static void print_sockerror (const char *msg)
|
||||
{
|
||||
int err = os_getErrno ();
|
||||
NN_ERROR ("SOCKET %s errno %d\n", msg, err);
|
||||
}
|
||||
|
||||
unsigned short sockaddr_get_port (const os_sockaddr_storage *addr)
|
||||
unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src)
|
||||
{
|
||||
if (addr->ss_family == AF_INET)
|
||||
return ntohs (((os_sockaddr_in *) addr)->sin_port);
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
unsigned id;
|
||||
if (src->kind == NN_LOCATOR_KIND_UDPv4 || src->kind == NN_LOCATOR_KIND_TCPv4)
|
||||
memcpy (&id, src->address + 12, sizeof (id));
|
||||
else
|
||||
return ntohs (((os_sockaddr_in6 *) addr)->sin6_port);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sockaddr_set_port (os_sockaddr_storage *addr, unsigned short port)
|
||||
{
|
||||
if (addr->ss_family == AF_INET)
|
||||
((os_sockaddr_in *) addr)->sin_port = htons (port);
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
else
|
||||
((os_sockaddr_in6 *) addr)->sin6_port = htons (port);
|
||||
#endif
|
||||
}
|
||||
|
||||
char *sockaddr_to_string_with_port (char addrbuf[INET6_ADDRSTRLEN_EXTENDED], const os_sockaddr_storage *src)
|
||||
{
|
||||
size_t pos;
|
||||
int n;
|
||||
switch (src->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
os_sockaddrAddressToString ((const os_sockaddr *) src, addrbuf, INET6_ADDRSTRLEN);
|
||||
pos = strlen (addrbuf);
|
||||
assert(pos <= INET6_ADDRSTRLEN_EXTENDED);
|
||||
n = snprintf (addrbuf + pos, INET6_ADDRSTRLEN_EXTENDED - pos, ":%u", ntohs (((os_sockaddr_in *) src)->sin_port));
|
||||
assert (n < INET6_ADDRSTRLEN_EXTENDED);
|
||||
(void)n;
|
||||
break;
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case AF_INET6:
|
||||
addrbuf[0] = '[';
|
||||
os_sockaddrAddressToString ((const os_sockaddr *) src, addrbuf + 1, INET6_ADDRSTRLEN);
|
||||
pos = strlen (addrbuf);
|
||||
assert(pos <= INET6_ADDRSTRLEN_EXTENDED);
|
||||
n = snprintf (addrbuf + pos, INET6_ADDRSTRLEN_EXTENDED - pos, "]:%u", ntohs (((os_sockaddr_in6 *) src)->sin6_port));
|
||||
assert (n < INET6_ADDRSTRLEN_EXTENDED);
|
||||
(void)n;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
NN_WARNING ("sockaddr_to_string_with_port: unknown address family\n");
|
||||
strcpy (addrbuf, "???");
|
||||
break;
|
||||
}
|
||||
return addrbuf;
|
||||
}
|
||||
|
||||
char *sockaddr_to_string_no_port (char addrbuf[INET6_ADDRSTRLEN_EXTENDED], const os_sockaddr_storage *src)
|
||||
{
|
||||
return os_sockaddrAddressToString ((const os_sockaddr *) src, addrbuf, INET6_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
char *locator_to_string_with_port (char addrbuf[INET6_ADDRSTRLEN_EXTENDED], const nn_locator_t *loc)
|
||||
{
|
||||
os_sockaddr_storage addr;
|
||||
nn_locator_t tmploc = *loc;
|
||||
if (tmploc.kind == NN_LOCATOR_KIND_UDPv4MCGEN)
|
||||
{
|
||||
nn_udpv4mcgen_address_t *x = (nn_udpv4mcgen_address_t *) &tmploc.address;
|
||||
memmove(tmploc.address + 12, &x->ipv4, 4);
|
||||
memset(tmploc.address, 0, 12);
|
||||
tmploc.kind = NN_LOCATOR_KIND_UDPv4;
|
||||
}
|
||||
nn_loc_to_address (&addr, &tmploc);
|
||||
return sockaddr_to_string_with_port (addrbuf, &addr);
|
||||
}
|
||||
|
||||
char *locator_to_string_no_port (char addrbuf[INET6_ADDRSTRLEN_EXTENDED], const nn_locator_t *loc)
|
||||
{
|
||||
os_sockaddr_storage addr;
|
||||
nn_locator_t tmploc = *loc;
|
||||
if (tmploc.kind == NN_LOCATOR_KIND_UDPv4MCGEN)
|
||||
{
|
||||
nn_udpv4mcgen_address_t *x = (nn_udpv4mcgen_address_t *) &tmploc.address;
|
||||
memmove(tmploc.address + 12, &x->ipv4, 4);
|
||||
memset(tmploc.address, 0, 12);
|
||||
tmploc.kind = NN_LOCATOR_KIND_UDPv4;
|
||||
}
|
||||
nn_loc_to_address (&addr, &tmploc);
|
||||
return sockaddr_to_string_no_port (addrbuf, &addr);
|
||||
}
|
||||
|
||||
unsigned sockaddr_to_hopefully_unique_uint32 (const os_sockaddr_storage *src)
|
||||
{
|
||||
switch (src->ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
return (unsigned) ((const os_sockaddr_in *) src)->sin_addr.s_addr;
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case AF_INET6:
|
||||
{
|
||||
unsigned id;
|
||||
md5_state_t st;
|
||||
md5_byte_t digest[16];
|
||||
md5_init (&st);
|
||||
md5_append (&st, (const md5_byte_t *) ((const os_sockaddr_in6 *) src)->sin6_addr.s6_addr, 16);
|
||||
md5_finish (&st, digest);
|
||||
memcpy (&id, digest, sizeof (id));
|
||||
return id;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
NN_FATAL ("sockaddr_to_hopefully_unique_uint32: unknown address family\n");
|
||||
return 0;
|
||||
md5_state_t st;
|
||||
md5_byte_t digest[16];
|
||||
md5_init (&st);
|
||||
md5_append (&st, (const md5_byte_t *) ((const os_sockaddr_in6 *) src)->sin6_addr.s6_addr, 16);
|
||||
md5_finish (&st, digest);
|
||||
memcpy (&id, digest, sizeof (id));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
unsigned short get_socket_port (os_socket socket)
|
||||
|
@ -493,7 +182,7 @@ static int maybe_set_dont_route (os_socket socket)
|
|||
if (config.dontRoute)
|
||||
{
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
|
||||
{
|
||||
unsigned ipv6Flag = 1;
|
||||
if (os_sockSetsockopt (socket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ipv6Flag, sizeof (ipv6Flag)))
|
||||
|
@ -504,6 +193,7 @@ static int maybe_set_dont_route (os_socket socket)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
|
||||
{
|
||||
int one = 1;
|
||||
if (os_sockSetsockopt (socket, SOL_SOCKET, SO_DONTROUTE, (char *) &one, sizeof (one)) != os_resultSuccess)
|
||||
|
@ -530,23 +220,12 @@ static int set_reuse_options (os_socket socket)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int interface_in_recvips_p (const struct nn_interface *interf)
|
||||
{
|
||||
struct ospl_in_addr_node *nodeaddr;
|
||||
for (nodeaddr = gv.recvips; nodeaddr; nodeaddr = nodeaddr->next)
|
||||
{
|
||||
if (os_sockaddrIPAddressEqual ((const os_sockaddr *) &nodeaddr->addr, (const os_sockaddr *) &interf->addr))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bind_socket (os_socket socket, unsigned short port)
|
||||
{
|
||||
int rc;
|
||||
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
|
||||
{
|
||||
os_sockaddr_in6 socketname;
|
||||
memset (&socketname, 0, sizeof (socketname));
|
||||
|
@ -560,6 +239,7 @@ static int bind_socket (os_socket socket, unsigned short port)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
|
||||
{
|
||||
struct sockaddr_in socketname;
|
||||
socketname.sin_family = AF_INET;
|
||||
|
@ -567,6 +247,10 @@ static int bind_socket (os_socket socket, unsigned short port)
|
|||
socketname.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
rc = os_sockBind (socket, (struct sockaddr *) &socketname, sizeof (socketname));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = os_resultFail;
|
||||
}
|
||||
if (rc != os_resultSuccess)
|
||||
{
|
||||
if (os_getErrno () != os_sockEADDRINUSE)
|
||||
|
@ -617,7 +301,7 @@ static int set_mc_options_transmit_ipv4 (os_socket socket)
|
|||
/* looks like imr_multiaddr is not relevant, not sure about imr_address */
|
||||
mreqn.imr_multiaddr.s_addr = htonl (INADDR_ANY);
|
||||
if (config.use_multicast_if_mreqn > 1)
|
||||
mreqn.imr_address.s_addr = ((os_sockaddr_in *) &gv.ownip)->sin_addr.s_addr;
|
||||
memcpy (&mreqn.imr_address.s_addr, gv.ownloc.address + 12, 4);
|
||||
else
|
||||
mreqn.imr_address.s_addr = htonl (INADDR_ANY);
|
||||
mreqn.imr_ifindex = (int) gv.interfaceNo;
|
||||
|
@ -626,7 +310,7 @@ static int set_mc_options_transmit_ipv4 (os_socket socket)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
ret = os_sockSetsockopt (socket, IPPROTO_IP, IP_MULTICAST_IF, (char *) &((os_sockaddr_in *) &gv.ownip)->sin_addr, sizeof (((os_sockaddr_in *) &gv.ownip)->sin_addr));
|
||||
ret = os_sockSetsockopt (socket, IPPROTO_IP, IP_MULTICAST_IF, gv.ownloc.address + 12, 4);
|
||||
}
|
||||
if (ret != os_resultSuccess)
|
||||
{
|
||||
|
@ -651,197 +335,20 @@ static int set_mc_options_transmit_ipv4 (os_socket socket)
|
|||
static int set_mc_options_transmit (os_socket socket)
|
||||
{
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
|
||||
{
|
||||
return set_mc_options_transmit_ipv6 (socket);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
|
||||
{
|
||||
return set_mc_options_transmit_ipv4 (socket);
|
||||
}
|
||||
}
|
||||
|
||||
static int joinleave_asm_mcgroup (os_socket socket, int join, const os_sockaddr_storage *mcip, const struct nn_interface *interf)
|
||||
{
|
||||
int rc;
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
{
|
||||
os_ipv6_mreq ipv6mreq;
|
||||
memset (&ipv6mreq, 0, sizeof (ipv6mreq));
|
||||
memcpy (&ipv6mreq.ipv6mr_multiaddr, &((os_sockaddr_in6 *) mcip)->sin6_addr, sizeof (ipv6mreq.ipv6mr_multiaddr));
|
||||
ipv6mreq.ipv6mr_interface = interf ? interf->if_index : 0;
|
||||
rc = os_sockSetsockopt (socket, IPPROTO_IPV6, join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, &ipv6mreq, sizeof (ipv6mreq));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr = ((os_sockaddr_in *) mcip)->sin_addr;
|
||||
if (interf)
|
||||
mreq.imr_interface = ((os_sockaddr_in *) &interf->addr)->sin_addr;
|
||||
else
|
||||
mreq.imr_interface.s_addr = htonl (INADDR_ANY);
|
||||
rc = os_sockSetsockopt (socket, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, (char *) &mreq, sizeof (mreq));
|
||||
}
|
||||
return (rc == -1) ? os_getErrno() : 0;
|
||||
}
|
||||
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
static int joinleave_ssm_mcgroup (os_socket socket, int join, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip, const struct nn_interface *interf)
|
||||
{
|
||||
int rc;
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
{
|
||||
struct group_source_req gsr;
|
||||
memset (&gsr, 0, sizeof (gsr));
|
||||
gsr.gsr_interface = interf ? interf->if_index : 0;
|
||||
memcpy (&gsr.gsr_group, mcip, sizeof (gsr.gsr_group));
|
||||
memcpy (&gsr.gsr_source, srcip, sizeof (gsr.gsr_source));
|
||||
rc = os_sockSetsockopt (socket, IPPROTO_IPV6, join ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP, &gsr, sizeof (gsr));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct ip_mreq_source mreq;
|
||||
memset (&mreq, 0, sizeof (mreq));
|
||||
mreq.imr_sourceaddr = ((os_sockaddr_in *) srcip)->sin_addr;
|
||||
mreq.imr_multiaddr = ((os_sockaddr_in *) mcip)->sin_addr;
|
||||
if (interf)
|
||||
mreq.imr_interface = ((os_sockaddr_in *) &interf->addr)->sin_addr;
|
||||
else
|
||||
mreq.imr_interface.s_addr = INADDR_ANY;
|
||||
rc = os_sockSetsockopt (socket, IPPROTO_IP, join ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP, &mreq, sizeof (mreq));
|
||||
}
|
||||
return (rc == -1) ? os_getErrno() : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *make_joinleave_msg (char *buf, size_t bufsz, os_socket socket, int join, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip, const struct nn_interface *interf, int err)
|
||||
{
|
||||
char mcstr[INET6_ADDRSTRLEN_EXTENDED], srcstr[INET6_ADDRSTRLEN_EXTENDED], interfstr[INET6_ADDRSTRLEN_EXTENDED];
|
||||
int n;
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
if (srcip)
|
||||
sockaddr_to_string_no_port(srcstr, srcip);
|
||||
else
|
||||
strcpy (srcstr, "*");
|
||||
#else
|
||||
OS_UNUSED_ARG (srcip);
|
||||
strcpy (srcstr, "*");
|
||||
#endif
|
||||
sockaddr_to_string_no_port (mcstr, mcip);
|
||||
if (interf)
|
||||
sockaddr_to_string_no_port(interfstr, &interf->addr);
|
||||
else
|
||||
(void) snprintf (interfstr, sizeof (interfstr), "(default)");
|
||||
n = err ? snprintf (buf, bufsz, "error %d in ", err) : 0;
|
||||
if ((size_t) n < bufsz)
|
||||
(void) snprintf (buf + n, bufsz - (size_t) n, "%s socket %lu for (%s, %s) interface %s", join ? "join" : "leave", (unsigned long) socket, mcstr, srcstr, interfstr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int joinleave_mcgroup (os_socket socket, int join, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip, const struct nn_interface *interf)
|
||||
{
|
||||
char buf[256];
|
||||
int err;
|
||||
nn_log (LC_DISCOVERY, "%s\n", make_joinleave_msg (buf, sizeof(buf), socket, join, srcip, mcip, interf, 0));
|
||||
#ifdef DDSI_INCLUDE_SSM
|
||||
if (srcip)
|
||||
err = joinleave_ssm_mcgroup(socket, join, srcip, mcip, interf);
|
||||
else
|
||||
err = joinleave_asm_mcgroup(socket, join, mcip, interf);
|
||||
#else
|
||||
assert (srcip == NULL);
|
||||
err = joinleave_asm_mcgroup(socket, join, mcip, interf);
|
||||
#endif
|
||||
if (err)
|
||||
NN_WARNING ("%s\n", make_joinleave_msg (buf, sizeof(buf), socket, join, srcip, mcip, interf, err));
|
||||
return err ? -1 : 0;
|
||||
}
|
||||
|
||||
static int joinleave_mcgroups (os_socket socket, int join, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip)
|
||||
{
|
||||
int rc;
|
||||
switch (gv.recvips_mode)
|
||||
{
|
||||
case RECVIPS_MODE_NONE:
|
||||
break;
|
||||
case RECVIPS_MODE_ANY:
|
||||
/* User has specified to use the OS default interface */
|
||||
if ((rc = joinleave_mcgroup (socket, join, srcip, mcip, NULL)) < 0)
|
||||
return rc;
|
||||
break;
|
||||
case RECVIPS_MODE_PREFERRED:
|
||||
if (gv.interfaces[gv.selected_interface].mc_capable)
|
||||
return joinleave_mcgroup (socket, join, srcip, mcip, &gv.interfaces[gv.selected_interface]);
|
||||
return 0;
|
||||
case RECVIPS_MODE_ALL:
|
||||
case RECVIPS_MODE_SOME:
|
||||
{
|
||||
int i, fails = 0, oks = 0;
|
||||
for (i = 0; i < gv.n_interfaces; i++)
|
||||
{
|
||||
if (gv.interfaces[i].mc_capable)
|
||||
{
|
||||
if (gv.recvips_mode == RECVIPS_MODE_ALL || interface_in_recvips_p (&gv.interfaces[i]))
|
||||
{
|
||||
if ((rc = joinleave_mcgroup (socket, join, srcip, mcip, &gv.interfaces[i])) < 0)
|
||||
fails++;
|
||||
else
|
||||
oks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fails > 0)
|
||||
{
|
||||
if (oks > 0)
|
||||
TRACE (("multicast join failed for some but not all interfaces, proceeding\n"));
|
||||
else
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int join_mcgroups (struct nn_group_membership *mship, os_socket socket, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip)
|
||||
{
|
||||
int ret;
|
||||
os_mutexLock (&mship->lock);
|
||||
if (!reg_group_membership (mship, socket, srcip, mcip))
|
||||
{
|
||||
char buf[256];
|
||||
TRACE (("%s: already joined\n", make_joinleave_msg (buf, sizeof(buf), socket, 1, srcip, mcip, NULL, 0)));
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = joinleave_mcgroups (socket, 1, srcip, mcip);
|
||||
return -2;
|
||||
}
|
||||
os_mutexUnlock (&mship->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int leave_mcgroups (struct nn_group_membership *mship, os_socket socket, const os_sockaddr_storage *srcip, const os_sockaddr_storage *mcip)
|
||||
{
|
||||
int ret;
|
||||
os_mutexLock (&mship->lock);
|
||||
if (!unreg_group_membership (mship, socket, srcip, mcip))
|
||||
{
|
||||
char buf[256];
|
||||
TRACE (("%s: not leaving yet\n", make_joinleave_msg (buf, sizeof(buf), socket, 0, srcip, mcip, NULL, 0)));
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = joinleave_mcgroups (socket, 0, srcip, mcip);
|
||||
}
|
||||
os_mutexUnlock (&mship->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int make_socket
|
||||
|
@ -855,15 +362,20 @@ int make_socket
|
|||
int rc = -2;
|
||||
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
|
||||
{
|
||||
*sock = os_sockNew (AF_INET6, stream ? SOCK_STREAM : SOCK_DGRAM);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
|
||||
{
|
||||
*sock = os_sockNew (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (! Q_VALID_SOCKET (*sock))
|
||||
{
|
||||
|
@ -933,6 +445,11 @@ static int multicast_override(const char *ifname)
|
|||
return match;
|
||||
}
|
||||
|
||||
#ifdef __linux
|
||||
/* FIMXE: HACK HACK */
|
||||
#include <linux/if_packet.h>
|
||||
#endif
|
||||
|
||||
int find_own_ip (const char *requested_address)
|
||||
{
|
||||
const char *sep = " ";
|
||||
|
@ -946,21 +463,44 @@ int find_own_ip (const char *requested_address)
|
|||
int maxq_count = 0;
|
||||
size_t maxq_strlen = 0;
|
||||
int selected_idx = -1;
|
||||
char addrbuf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
char addrbuf[DDSI_LOCSTRLEN];
|
||||
|
||||
ifs = os_malloc (MAX_INTERFACES * sizeof (*ifs));
|
||||
|
||||
nn_log (LC_CONFIG, "interfaces:");
|
||||
|
||||
if (config.useIpv6)
|
||||
res = os_sockQueryIPv6Interfaces (ifs, MAX_INTERFACES, &nif);
|
||||
else
|
||||
res = os_sockQueryInterfaces (ifs, MAX_INTERFACES, &nif);
|
||||
if (res != os_resultSuccess)
|
||||
{
|
||||
NN_ERROR ("os_sockQueryInterfaces: %d\n", (int) res);
|
||||
os_free (ifs);
|
||||
return 0;
|
||||
int retcode;
|
||||
nif = 0;
|
||||
retcode = ddsi_enumerate_interfaces(gv.m_factory, (int)(MAX_INTERFACES - nif), ifs);
|
||||
if (retcode > 0)
|
||||
{
|
||||
nif = (unsigned)retcode;
|
||||
res = os_resultSuccess;
|
||||
}
|
||||
else if (retcode < 0)
|
||||
{
|
||||
NN_ERROR ("ddsi_enumerate_interfaces(%s): %d\n", gv.m_factory->m_typename, retcode);
|
||||
res = os_resultFail;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (config.transport_selector == TRANS_TCP6 || config.transport_selector == TRANS_UDP6)
|
||||
res = os_sockQueryIPv6Interfaces (ifs, MAX_INTERFACES, &nif);
|
||||
else if (config.transport_selector == TRANS_TCP || config.transport_selector == TRANS_UDP)
|
||||
res = os_sockQueryInterfaces (ifs, MAX_INTERFACES, &nif);
|
||||
else
|
||||
{
|
||||
NN_ERROR ("ddsi_enumerate_interfaces(%s): no go but neither UDP[46] nor TCP[46]\n", gv.m_factory->m_typename);
|
||||
res = os_resultFail;
|
||||
}
|
||||
}
|
||||
if (res != os_resultSuccess)
|
||||
{
|
||||
NN_ERROR ("os_sockQueryInterfaces: %d\n", (int) res);
|
||||
os_free (ifs);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
gv.n_interfaces = 0;
|
||||
|
@ -987,7 +527,22 @@ int find_own_ip (const char *requested_address)
|
|||
|
||||
tmpip = ifs[i].address;
|
||||
tmpmask = ifs[i].network_mask;
|
||||
sockaddr_to_string_no_port (addrbuf, &tmpip);
|
||||
#ifdef __linux
|
||||
if (tmpip.ss_family == AF_PACKET)
|
||||
{
|
||||
/* FIXME: weirdo warning warranted */
|
||||
nn_locator_t *l = &gv.interfaces[gv.n_interfaces].loc;
|
||||
l->kind = NN_LOCATOR_KIND_RAWETH;
|
||||
l->port = NN_LOCATOR_PORT_INVALID;
|
||||
memset(l->address, 0, 10);
|
||||
memcpy(l->address + 10, ((struct sockaddr_ll *)&tmpip)->sll_addr, 6);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].loc, &tmpip, gv.m_factory->m_kind);
|
||||
}
|
||||
ddsi_locator_to_string_no_port(addrbuf, sizeof(addrbuf), &gv.interfaces[gv.n_interfaces].loc);
|
||||
nn_log (LC_CONFIG, " %s(", addrbuf);
|
||||
|
||||
if (!(ifs[i].flags & IFF_MULTICAST) && multicast_override (if_name))
|
||||
|
@ -1047,8 +602,19 @@ int find_own_ip (const char *requested_address)
|
|||
quality = q;
|
||||
}
|
||||
|
||||
gv.interfaces[gv.n_interfaces].addr = tmpip;
|
||||
gv.interfaces[gv.n_interfaces].netmask = tmpmask;
|
||||
/* FIXME: HACK HACK */
|
||||
//ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].loc, &tmpip, gv.m_factory->m_kind);
|
||||
if (tmpip.ss_family == AF_INET || tmpip.ss_family == AF_INET6)
|
||||
{
|
||||
tmpmask.ss_family = tmpip.ss_family;
|
||||
ddsi_ipaddr_to_loc(&gv.interfaces[gv.n_interfaces].netmask, &tmpmask, gv.m_factory->m_kind);
|
||||
}
|
||||
else
|
||||
{
|
||||
gv.interfaces[gv.n_interfaces].netmask.kind = gv.m_factory->m_kind;
|
||||
gv.interfaces[gv.n_interfaces].netmask.port = NN_LOCATOR_PORT_INVALID;
|
||||
memset(&gv.interfaces[gv.n_interfaces].netmask.address, 0, sizeof(gv.interfaces[gv.n_interfaces].netmask.address));
|
||||
}
|
||||
gv.interfaces[gv.n_interfaces].mc_capable = ((ifs[i].flags & IFF_MULTICAST) != 0);
|
||||
gv.interfaces[gv.n_interfaces].point_to_point = ((ifs[i].flags & IFF_POINTOPOINT) != 0);
|
||||
gv.interfaces[gv.n_interfaces].if_index = ifs[i].interfaceIndexNo;
|
||||
|
@ -1065,7 +631,7 @@ int find_own_ip (const char *requested_address)
|
|||
const int idx = maxq_list[0];
|
||||
char *names;
|
||||
int p;
|
||||
sockaddr_to_string_no_port (addrbuf, &gv.interfaces[idx].addr);
|
||||
ddsi_locator_to_string_no_port (addrbuf, sizeof(addrbuf), &gv.interfaces[idx].loc);
|
||||
names = os_malloc (maxq_strlen + 1);
|
||||
p = 0;
|
||||
for (i = 0; i < maxq_count && (size_t) p < maxq_strlen; i++)
|
||||
|
@ -1082,7 +648,7 @@ int find_own_ip (const char *requested_address)
|
|||
}
|
||||
else
|
||||
{
|
||||
os_sockaddr_storage req;
|
||||
nn_locator_t req;
|
||||
/* Presumably an interface name */
|
||||
for (i = 0; i < gv.n_interfaces; i++)
|
||||
{
|
||||
|
@ -1091,36 +657,32 @@ int find_own_ip (const char *requested_address)
|
|||
}
|
||||
if (i < gv.n_interfaces)
|
||||
; /* got a match */
|
||||
else if (!os_sockaddrStringToAddress (config.networkAddressString, (os_sockaddr *) &req, !config.useIpv6))
|
||||
else if (ddsi_locator_from_string(&req, config.networkAddressString) != AFSR_OK)
|
||||
; /* not good, i = gv.n_interfaces, so error handling will kick in */
|
||||
else
|
||||
{
|
||||
/* Try an exact match on the address */
|
||||
for (i = 0; i < gv.n_interfaces; i++)
|
||||
if (os_sockaddrIPAddressEqual ((os_sockaddr *) &gv.interfaces[i].addr, (os_sockaddr *) &req))
|
||||
if (compare_locators(&gv.interfaces[i].loc, &req) == 0)
|
||||
break;
|
||||
if (i == gv.n_interfaces && !config.useIpv6)
|
||||
if (i == gv.n_interfaces && req.kind == NN_LOCATOR_KIND_UDPv4)
|
||||
{
|
||||
/* Try matching on network portion only, where the network
|
||||
portion is based on the netmask of the interface under
|
||||
consideration */
|
||||
for (i = 0; i < gv.n_interfaces; i++)
|
||||
{
|
||||
os_sockaddr_storage req1 = req, ip1 = gv.interfaces[i].addr;
|
||||
assert (req1.ss_family == AF_INET);
|
||||
assert (ip1.ss_family == AF_INET);
|
||||
uint32_t req1, ip1, nm1;
|
||||
memcpy (&req1, req.address + 12, sizeof (req1));
|
||||
memcpy (&ip1, gv.interfaces[i].loc.address + 12, sizeof (ip1));
|
||||
memcpy (&nm1, gv.interfaces[i].netmask.address + 12, sizeof (nm1));
|
||||
|
||||
/* If the host portion of the requested address is non-zero,
|
||||
skip this interface */
|
||||
if (((os_sockaddr_in *) &req1)->sin_addr.s_addr &
|
||||
~((os_sockaddr_in *) &gv.interfaces[i].netmask)->sin_addr.s_addr)
|
||||
if (req1 & ~nm1)
|
||||
continue;
|
||||
|
||||
((os_sockaddr_in *) &req1)->sin_addr.s_addr &=
|
||||
((os_sockaddr_in *) &gv.interfaces[i].netmask)->sin_addr.s_addr;
|
||||
((os_sockaddr_in *) &ip1)->sin_addr.s_addr &=
|
||||
((os_sockaddr_in *) &gv.interfaces[i].netmask)->sin_addr.s_addr;
|
||||
if (os_sockaddrIPAddressEqual ((os_sockaddr *) &ip1, (os_sockaddr *) &req1))
|
||||
if ((req1 & nm1) == (ip1 & nm1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1136,16 +698,15 @@ int find_own_ip (const char *requested_address)
|
|||
return 0;
|
||||
else
|
||||
{
|
||||
gv.ownip = gv.interfaces[selected_idx].addr;
|
||||
sockaddr_set_port (&gv.ownip, 0);
|
||||
gv.ownloc = gv.interfaces[selected_idx].loc;
|
||||
gv.selected_interface = selected_idx;
|
||||
gv.interfaceNo = gv.interfaces[selected_idx].if_index;
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
if (config.useIpv6)
|
||||
if (gv.extloc.kind == NN_LOCATOR_KIND_TCPv6 || gv.extloc.kind == NN_LOCATOR_KIND_UDPv6)
|
||||
{
|
||||
assert (gv.ownip.ss_family == AF_INET6);
|
||||
gv.ipv6_link_local =
|
||||
IN6_IS_ADDR_LINKLOCAL (&((os_sockaddr_in6 *) &gv.ownip)->sin6_addr) != 0;
|
||||
os_sockaddr_in6 addr;
|
||||
memcpy(&addr.sin6_addr, gv.ownloc.address, sizeof(addr.sin6_addr));
|
||||
gv.ipv6_link_local = IN6_IS_ADDR_LINKLOCAL (&addr.sin6_addr) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -137,7 +137,7 @@ void write_pcap_received
|
|||
size_t sz
|
||||
)
|
||||
{
|
||||
if (!config.useIpv6)
|
||||
if (config.transport_selector == TRANS_UDP)
|
||||
{
|
||||
pcaprec_hdr_t pcap_hdr;
|
||||
union {
|
||||
|
@ -177,7 +177,7 @@ void write_pcap_sent
|
|||
size_t sz
|
||||
)
|
||||
{
|
||||
if (!config.useIpv6)
|
||||
if (config.transport_selector == TRANS_UDP)
|
||||
{
|
||||
pcaprec_hdr_t pcap_hdr;
|
||||
union {
|
||||
|
|
|
@ -1546,7 +1546,7 @@ static int do_locator
|
|||
break;
|
||||
case NN_LOCATOR_KIND_UDPv4MCGEN: {
|
||||
const nn_udpv4mcgen_address_t *x = (const nn_udpv4mcgen_address_t *) loc.address;
|
||||
if (config.useIpv6 || config.tcp_enable)
|
||||
if (!ddsi_factory_supports(gv.m_factory, NN_LOCATOR_KIND_UDPv4))
|
||||
return 0;
|
||||
if (loc.port <= 0 || loc.port > 65536)
|
||||
{
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
#include "ddsi/q_transmit.h"
|
||||
#include "ddsi/q_globals.h"
|
||||
#include "ddsi/q_static_assert.h"
|
||||
#include "ddsi/q_init.h"
|
||||
#include "ddsi/ddsi_mcgroup.h"
|
||||
|
||||
#include "ddsi/sysdeps.h"
|
||||
|
||||
|
@ -2658,6 +2660,7 @@ static struct receiver_state *rst_cow_if_needed (int *rst_live, struct nn_rmsg *
|
|||
static int handle_submsg_sequence
|
||||
(
|
||||
ddsi_tran_conn_t conn,
|
||||
const nn_locator_t *srcloc,
|
||||
struct thread_state1 * const self,
|
||||
nn_wctime_t tnowWC,
|
||||
nn_etime_t tnowE,
|
||||
|
@ -2700,6 +2703,7 @@ static int handle_submsg_sequence
|
|||
rst->forme = 1;
|
||||
rst->vendor = hdr->vendorid;
|
||||
rst->protocol_version = hdr->version;
|
||||
rst->srcloc = *srcloc;
|
||||
rst_live = 0;
|
||||
ts_for_latmeas = 0;
|
||||
timestamp = invalid_ddsi_timestamp;
|
||||
|
@ -2883,7 +2887,7 @@ static int handle_submsg_sequence
|
|||
size_t len2 = decode_container (submsg1, len1);
|
||||
if ( len2 != 0 ) {
|
||||
TRACE ((")\n"));
|
||||
if (handle_submsg_sequence (conn, self, tnowWC, tnowE, src_prefix, dst_prefix, msg, (size_t) (submsg1 - msg) + len2, submsg1, rmsg) < 0)
|
||||
if (handle_submsg_sequence (conn, srcloc, self, tnowWC, tnowE, src_prefix, dst_prefix, msg, (size_t) (submsg1 - msg) + len2, submsg1, rmsg) < 0)
|
||||
goto malformed;
|
||||
}
|
||||
TRACE (("PT_INFO_CONTAINER END"));
|
||||
|
@ -2977,6 +2981,7 @@ static bool do_packet
|
|||
unsigned char * buff;
|
||||
size_t buff_len = maxsz;
|
||||
Header_t * hdr;
|
||||
nn_locator_t srcloc;
|
||||
|
||||
if (rmsg == NULL)
|
||||
{
|
||||
|
@ -2996,7 +3001,7 @@ static bool do_packet
|
|||
|
||||
/* Read in DDSI header plus MSG_LEN sub message that follows it */
|
||||
|
||||
sz = ddsi_conn_read (conn, buff, stream_hdr_size);
|
||||
sz = ddsi_conn_read (conn, buff, stream_hdr_size, &srcloc);
|
||||
|
||||
/* Read in remainder of packet */
|
||||
|
||||
|
@ -3024,7 +3029,7 @@ static bool do_packet
|
|||
}
|
||||
else
|
||||
{
|
||||
sz = ddsi_conn_read (conn, buff + stream_hdr_size, ml->length - stream_hdr_size);
|
||||
sz = ddsi_conn_read (conn, buff + stream_hdr_size, ml->length - stream_hdr_size, NULL);
|
||||
if (sz > 0)
|
||||
{
|
||||
sz = (ssize_t) ml->length;
|
||||
|
@ -3036,7 +3041,7 @@ static bool do_packet
|
|||
{
|
||||
/* Get next packet */
|
||||
|
||||
sz = ddsi_conn_read (conn, buff, buff_len);
|
||||
sz = ddsi_conn_read (conn, buff, buff_len, &srcloc);
|
||||
}
|
||||
|
||||
if (sz > 0 && !gv.deaf)
|
||||
|
@ -3052,7 +3057,7 @@ static bool do_packet
|
|||
)
|
||||
{
|
||||
if ((hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM))
|
||||
TRACE (("HDR("PGIDFMT" vendor %d.%d) len %lu\n, version mismatch: %d.%d\n",
|
||||
TRACE (("HDR(%x:%x:%x vendor %d.%d) len %lu\n, version mismatch: %d.%d\n",
|
||||
PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, hdr->version.major, hdr->version.minor));
|
||||
if (NN_PEDANTIC_P)
|
||||
malformed_packet_received_nosubmsg (buff, sz, "header", hdr->vendorid);
|
||||
|
@ -3061,13 +3066,19 @@ static bool do_packet
|
|||
{
|
||||
hdr->guid_prefix = nn_ntoh_guid_prefix (hdr->guid_prefix);
|
||||
|
||||
TRACE (("HDR(%x:%x:%x vendor %u.%u) len %lu\n",
|
||||
PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz));
|
||||
if (config.enabled_logcats & LC_TRACE)
|
||||
{
|
||||
char addrstr[DDSI_LOCSTRLEN];
|
||||
ddsi_locator_to_string(addrstr, sizeof(addrstr), &srcloc);
|
||||
nn_log (LC_TRACE, "HDR(%x:%x:%x vendor %d.%d) len %lu from %s\n",
|
||||
PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr);
|
||||
}
|
||||
|
||||
{
|
||||
handle_submsg_sequence
|
||||
(
|
||||
conn,
|
||||
&srcloc,
|
||||
self,
|
||||
now (),
|
||||
now_et (),
|
||||
|
@ -3228,6 +3239,95 @@ uint32_t listen_thread (struct ddsi_tran_listener * listener)
|
|||
return 0;
|
||||
}
|
||||
|
||||
enum local_deaf_state_recover {
|
||||
LDSR_NORMAL = 0, /* matches gv.deaf for normal operation */
|
||||
LDSR_DEAF = 1, /* matches gv.deaf for "deaf" state */
|
||||
LDSR_REJOIN = 2
|
||||
};
|
||||
|
||||
struct local_deaf_state {
|
||||
enum local_deaf_state_recover state;
|
||||
nn_mtime_t tnext;
|
||||
};
|
||||
|
||||
static int check_and_handle_deafness_recover(struct local_deaf_state *st)
|
||||
{
|
||||
int rebuildws = 0;
|
||||
if (now_mt().v < st->tnext.v)
|
||||
{
|
||||
TRACE(("check_and_handle_deafness_recover: state %d too early\n", (int)st->state));
|
||||
return 0;
|
||||
}
|
||||
switch (st->state)
|
||||
{
|
||||
case LDSR_NORMAL:
|
||||
assert(0);
|
||||
break;
|
||||
case LDSR_DEAF: {
|
||||
ddsi_tran_conn_t disc = gv.disc_conn_mc, data = gv.data_conn_mc;
|
||||
TRACE(("check_and_handle_deafness_recover: state %d create new sockets\n", (int)st->state));
|
||||
if (!create_multicast_sockets())
|
||||
goto error;
|
||||
TRACE(("check_and_handle_deafness_recover: state %d transfer group membership admin\n", (int)st->state));
|
||||
ddsi_transfer_group_membership(disc, gv.disc_conn_mc);
|
||||
ddsi_transfer_group_membership(data, gv.data_conn_mc);
|
||||
TRACE(("check_and_handle_deafness_recover: state %d drop from waitset and add new\n", (int)st->state));
|
||||
/* see waitset construction code in recv_thread */
|
||||
os_sockWaitsetPurge (gv.waitset, 1 + (gv.disc_conn_uc != gv.data_conn_uc));
|
||||
os_sockWaitsetAdd (gv.waitset, gv.disc_conn_mc);
|
||||
os_sockWaitsetAdd (gv.waitset, gv.data_conn_mc);
|
||||
TRACE(("check_and_handle_deafness_recover: state %d close sockets\n", (int)st->state));
|
||||
ddsi_conn_free(disc);
|
||||
ddsi_conn_free(data);
|
||||
rebuildws = 1;
|
||||
st->state = LDSR_REJOIN;
|
||||
/* FALLS THROUGH */
|
||||
}
|
||||
case LDSR_REJOIN:
|
||||
TRACE(("check_and_handle_deafness_recover: state %d rejoin on disc socket\n", (int)st->state));
|
||||
if (ddsi_rejoin_transferred_mcgroups(gv.disc_conn_mc) < 0)
|
||||
goto error;
|
||||
TRACE(("check_and_handle_deafness_recover: state %d rejoin on data socket\n", (int)st->state));
|
||||
if (ddsi_rejoin_transferred_mcgroups(gv.data_conn_mc) < 0)
|
||||
goto error;
|
||||
TRACE(("check_and_handle_deafness_recover: state %d done\n", (int)st->state));
|
||||
st->state = LDSR_NORMAL;
|
||||
break;
|
||||
}
|
||||
TRACE(("check_and_handle_deafness_recover: state %d returning %d\n", (int)st->state, rebuildws));
|
||||
return rebuildws;
|
||||
error:
|
||||
TRACE(("check_and_handle_deafness_recover: state %d failed, returning %d\n", (int)st->state, rebuildws));
|
||||
st->state = LDSR_DEAF;
|
||||
st->tnext = add_duration_to_mtime(now_mt(), T_SECOND);
|
||||
return rebuildws;
|
||||
}
|
||||
|
||||
static int check_and_handle_deafness(struct local_deaf_state *st)
|
||||
{
|
||||
const int gv_deaf = gv.deaf;
|
||||
assert (gv_deaf == 0 || gv_deaf == 1);
|
||||
if (gv_deaf == (int)st->state)
|
||||
return 0;
|
||||
else if (gv_deaf)
|
||||
{
|
||||
TRACE(("check_and_handle_deafness: going deaf (%d -> %d)\n", (int)st->state, (int)LDSR_DEAF));
|
||||
st->state = LDSR_DEAF;
|
||||
st->tnext = now_mt();
|
||||
return 0;
|
||||
}
|
||||
else if (!config.allowMulticast)
|
||||
{
|
||||
TRACE(("check_and_handle_deafness: no longer deaf (multicast disabled)\n"));
|
||||
st->state = LDSR_NORMAL;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return check_and_handle_deafness_recover(st);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t recv_thread (struct nn_rbufpool * rbpool)
|
||||
{
|
||||
struct thread_state1 *self = lookup_thread_state ();
|
||||
|
@ -3236,39 +3336,58 @@ uint32_t recv_thread (struct nn_rbufpool * rbpool)
|
|||
nn_mtime_t next_thread_cputime = { 0 };
|
||||
os_sockWaitsetCtx ctx;
|
||||
unsigned i;
|
||||
struct local_deaf_state lds;
|
||||
|
||||
lds.state = gv.deaf ? LDSR_DEAF : LDSR_NORMAL;
|
||||
lds.tnext = now_mt();
|
||||
|
||||
local_participant_set_init (&lps);
|
||||
nn_rbufpool_setowner (rbpool, os_threadIdSelf ());
|
||||
|
||||
if (gv.m_factory->m_connless)
|
||||
{
|
||||
os_sockWaitsetAdd (gv.waitset, gv.disc_conn_uc);
|
||||
os_sockWaitsetAdd (gv.waitset, gv.data_conn_uc);
|
||||
num_fixed = 2;
|
||||
if (config.allowMulticast)
|
||||
if (config.many_sockets_mode == MSM_NO_UNICAST)
|
||||
{
|
||||
os_sockWaitsetAdd (gv.waitset, gv.disc_conn_mc);
|
||||
os_sockWaitsetAdd (gv.waitset, gv.data_conn_mc);
|
||||
num_fixed += 2;
|
||||
/* we only have one - disc, data, uc and mc all alias each other */
|
||||
os_sockWaitsetAdd (gv.waitset, gv.disc_conn_uc);
|
||||
num_fixed = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sockWaitsetAdd (gv.waitset, gv.disc_conn_uc);
|
||||
os_sockWaitsetAdd (gv.waitset, gv.data_conn_uc);
|
||||
num_fixed = 1 + (gv.disc_conn_uc != gv.data_conn_uc);
|
||||
if (config.allowMulticast)
|
||||
{
|
||||
os_sockWaitsetAdd (gv.waitset, gv.disc_conn_mc);
|
||||
os_sockWaitsetAdd (gv.waitset, gv.data_conn_mc);
|
||||
num_fixed += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (gv.rtps_keepgoing)
|
||||
{
|
||||
int rebuildws;
|
||||
|
||||
LOG_THREAD_CPUTIME (next_thread_cputime);
|
||||
|
||||
if (! config.many_sockets_mode)
|
||||
rebuildws = check_and_handle_deafness(&lds);
|
||||
|
||||
if (config.many_sockets_mode != MSM_MANY_UNICAST)
|
||||
{
|
||||
/* no other sockets to check */
|
||||
}
|
||||
else if (os_atomic_ld32 (&gv.participant_set_generation) != lps.gen)
|
||||
{
|
||||
/* rebuild local participant set */
|
||||
rebuildws = 1;
|
||||
}
|
||||
|
||||
if (rebuildws && config.many_sockets_mode == MSM_MANY_UNICAST)
|
||||
{
|
||||
/* first rebuild local participant set - unless someone's toggling "deafness", this
|
||||
only happens when the participant set has changed, so might as well rebuild it */
|
||||
rebuild_local_participant_set (self, &lps);
|
||||
|
||||
/* and rebuild waitset */
|
||||
|
||||
os_sockWaitsetPurge (gv.waitset, num_fixed);
|
||||
for (i = 0; i < lps.nps; i++)
|
||||
{
|
||||
|
@ -3288,7 +3407,7 @@ uint32_t recv_thread (struct nn_rbufpool * rbpool)
|
|||
while ((idx = os_sockWaitsetNextEvent (ctx, &conn)) >= 0)
|
||||
{
|
||||
bool ret;
|
||||
if (((unsigned)idx < num_fixed) || ! config.many_sockets_mode)
|
||||
if (((unsigned)idx < num_fixed) || config.many_sockets_mode != MSM_MANY_UNICAST)
|
||||
{
|
||||
ret = do_packet (self, conn, NULL, rbpool);
|
||||
}
|
||||
|
|
|
@ -1661,30 +1661,28 @@ static c_bool q_securityDecodeInPlace
|
|||
static os_ssize_t q_security_sendmsg
|
||||
(
|
||||
ddsi_tran_conn_t conn,
|
||||
struct msghdr *message,
|
||||
const nn_locator_t *dst,
|
||||
size_t niov, ddsi_iovec_t *iov,
|
||||
q_securityEncoderSet *codec,
|
||||
os_uint32 encoderId,
|
||||
os_uint32 flags
|
||||
)
|
||||
{
|
||||
char stbuf[2048], *buf;
|
||||
os_uint32 sz, data_size;
|
||||
os_ssize_t ret = ERR_UNSPECIFIED;
|
||||
PT_InfoContainer_t * securityHeader = (PT_InfoContainer_t*) message->msg_iov[1].iov_base;
|
||||
size_t sz, data_size;
|
||||
uint32_t sz32, data_size32;
|
||||
ssize_t ret = ERR_UNSPECIFIED;
|
||||
PT_InfoContainer_t * securityHeader;
|
||||
unsigned i;
|
||||
|
||||
#if SYSDEPS_MSGHDR_ACCRIGHTS
|
||||
assert (message->msg_accrightslen == 0);
|
||||
#else
|
||||
assert (message->msg_controllen == 0);
|
||||
#endif
|
||||
assert (message->msg_iovlen > 2);
|
||||
assert (niov > 2);
|
||||
securityHeader = iov[1].iov_base;
|
||||
/* first determine the size of the message, then select the
|
||||
on-stack buffer or allocate one on the heap ... */
|
||||
sz = q_securityEncoderSetHeaderSize (*codec); /* reserve appropriate headersize */
|
||||
for (i = 2; i < (unsigned) message->msg_iovlen; i++)
|
||||
for (i = 2; i < niov; i++)
|
||||
{
|
||||
sz += (os_uint32) message->msg_iov[i].iov_len;
|
||||
sz += iov[i].iov_len;
|
||||
}
|
||||
if (sz <= sizeof (stbuf))
|
||||
{
|
||||
|
@ -1696,23 +1694,26 @@ static os_ssize_t q_security_sendmsg
|
|||
}
|
||||
/* ... then copy data into buffer */
|
||||
data_size = 0;
|
||||
for (i = 2; i < (unsigned) message->msg_iovlen; i++)
|
||||
for (i = 2; i < niov; i++)
|
||||
{
|
||||
memcpy (buf + data_size, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len);
|
||||
data_size += (os_uint32) message->msg_iov[i].iov_len;
|
||||
memcpy (buf + data_size, iov[i].iov_base, iov[i].iov_len);
|
||||
data_size += iov[i].iov_len;
|
||||
}
|
||||
sz = data_size + q_securityEncoderSetHeaderSize (*codec);
|
||||
assert(sz <= UINT32_MAX);
|
||||
sz32 = (uint32_t) sz;
|
||||
data_size32 = (uint32_t) data_size;
|
||||
|
||||
/* Encrypt the buf in place with the given encoder */
|
||||
|
||||
if (q_securityEncodeInPlace (*codec, encoderId, buf, sz, &data_size))
|
||||
if (q_securityEncodeInPlace (*codec, encoderId, buf, sz32, &data_size32))
|
||||
{
|
||||
os_size_t nbytes;
|
||||
/* replace encrypted buffer into iov */
|
||||
|
||||
message->msg_iov[2].iov_base = buf;
|
||||
message->msg_iov[2].iov_len = data_size;
|
||||
message->msg_iovlen = 3;
|
||||
iov[2].iov_base = buf;
|
||||
iov[2].iov_len = data_size;
|
||||
niov = 3;
|
||||
/* correct size in security header */
|
||||
securityHeader->smhdr.octetsToNextHeader = (unsigned short) (data_size + 4);
|
||||
|
||||
|
@ -1720,11 +1721,11 @@ static os_ssize_t q_security_sendmsg
|
|||
|
||||
nbytes = message->msg_iov[0].iov_len + message->msg_iov[1].iov_len + message->msg_iov[2].iov_len;
|
||||
if (!gv.mute)
|
||||
ret = ddsi_conn_write (conn, message, nbytes, flags);
|
||||
ret = ddsi_conn_write (conn, dst, niov, iov, flags);
|
||||
else
|
||||
{
|
||||
TRACE (("(dropped)"));
|
||||
ret = (os_ssize_t) nbytes;
|
||||
ret = (ssize_t) (iov[0].iov_len + iov[1].iov_len + iov[2].iov_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -167,6 +167,14 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl)
|
|||
/* We are never active in a way that matters for the garbage
|
||||
collection of old writers, &c. */
|
||||
thread_state_asleep (self);
|
||||
|
||||
/* While deaf, we need to make sure the receive thread wakes up
|
||||
every now and then to try recreating sockets & rejoining multicast
|
||||
groups */
|
||||
if (gv.deaf)
|
||||
{
|
||||
os_sockWaitsetTrigger(gv.waitset);
|
||||
}
|
||||
}
|
||||
os_mutexUnlock (&sl->lock);
|
||||
return 0;
|
||||
|
|
|
@ -869,7 +869,7 @@ void nn_xmsg_addpar_octetseq (struct nn_xmsg *m, unsigned pid, const nn_octetseq
|
|||
|
||||
void nn_xmsg_addpar_stringseq (struct nn_xmsg *m, unsigned pid, const nn_stringseq_t *sseq)
|
||||
{
|
||||
char *tmp;
|
||||
unsigned char *tmp;
|
||||
unsigned i, len = 0;
|
||||
|
||||
for (i = 0; i < sseq->n; i++)
|
||||
|
@ -1294,42 +1294,15 @@ void nn_xpack_free (struct nn_xpack *xp)
|
|||
os_free (xp);
|
||||
}
|
||||
|
||||
|
||||
static socklen_t sockaddr_size (const os_sockaddr_storage *a)
|
||||
{
|
||||
switch (a->ss_family)
|
||||
{
|
||||
case AF_INET: return sizeof (os_sockaddr_in);
|
||||
#if OS_SOCKET_HAS_IPV6
|
||||
case AF_INET6: return sizeof (os_sockaddr_in6);
|
||||
#endif
|
||||
default: assert (0); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Turns out Darwin uses "int" for msg_iovlen, but glibc uses "size_t". The simplest
|
||||
way out is to do the assignment with the conversion warnings disabled */
|
||||
OS_WARNING_GNUC_OFF(conversion)
|
||||
static void set_msghdr_iov (struct msghdr *mhdr, struct iovec *iov, size_t iovlen)
|
||||
{
|
||||
mhdr->msg_iov = iov;
|
||||
mhdr->msg_iovlen = iovlen;
|
||||
}
|
||||
OS_WARNING_GNUC_ON(conversion)
|
||||
|
||||
static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg)
|
||||
{
|
||||
struct iovec iov[NN_XMSG_MAX_MESSAGE_IOVECS];
|
||||
struct nn_xpack * xp = varg;
|
||||
struct msghdr mhdr;
|
||||
ssize_t nbytes = 0;
|
||||
os_sockaddr_storage addr;
|
||||
|
||||
nn_loc_to_address(&addr, loc);
|
||||
if (config.enabled_logcats & LC_TRACE)
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN_EXTENDED];
|
||||
TRACE ((" %s", sockaddr_to_string_with_port (buf, &addr)));
|
||||
char buf[DDSI_LOCSTRLEN];
|
||||
TRACE ((" %s", ddsi_locator_to_string (buf, sizeof(buf), loc)));
|
||||
}
|
||||
|
||||
if (config.xmit_lossiness > 0)
|
||||
|
@ -1344,24 +1317,18 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg)
|
|||
}
|
||||
}
|
||||
|
||||
/* Set target data/address in message */
|
||||
|
||||
memcpy (iov, xp->iov, sizeof (iov));
|
||||
memset (&mhdr, 0, sizeof (mhdr));
|
||||
set_msghdr_iov (&mhdr, iov, xp->niov);
|
||||
mhdr.msg_name = &addr;
|
||||
mhdr.msg_namelen = sockaddr_size (&addr);
|
||||
|
||||
#ifdef DDSI_INCLUDE_ENCRYPTION
|
||||
if (q_security_plugin.send_encoded && xp->encoderId != 0 && (q_security_plugin.encoder_type) (xp->codec, xp->encoderId) != Q_CIPHER_NONE)
|
||||
{
|
||||
nbytes = (q_security_plugin.send_encoded) (xp->conn, &mhdr, &xp->codec, xp->encoderId, xp->call_flags);
|
||||
struct iovec iov[NN_XMSG_MAX_MESSAGE_IOVECS];
|
||||
memcpy (iov, xp->iov, sizeof (iov));
|
||||
nbytes = (q_security_plugin.send_encoded) (xp->conn, loc, xp->niov, iov, &xp->codec, xp->encoderId, xp->call_flags);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!gv.mute)
|
||||
nbytes = ddsi_conn_write (xp->conn, &mhdr, xp->msg_len.length, xp->call_flags);
|
||||
nbytes = ddsi_conn_write (xp->conn, loc, xp->niov, xp->iov, xp->call_flags);
|
||||
else
|
||||
{
|
||||
TRACE (("(dropped)"));
|
||||
|
|
|
@ -148,27 +148,19 @@ ssize_t sendmsg (os_handle fd, const struct msghdr *message, int flags)
|
|||
#else /* _WIN32 && !WINCE */
|
||||
ssize_t sendmsg (os_handle fd, const struct msghdr *message, int flags)
|
||||
{
|
||||
WSABUF stbufs[128], *bufs;
|
||||
DWORD sent;
|
||||
unsigned i;
|
||||
ssize_t ret;
|
||||
|
||||
DDSI_IOVEC_MATCHES_WSABUF;
|
||||
|
||||
#if SYSDEPS_MSGHDR_ACCRIGHTS
|
||||
assert (message->msg_accrightslen == 0);
|
||||
#else
|
||||
assert (message->msg_controllen == 0);
|
||||
#endif
|
||||
|
||||
if (message->msg_iovlen <= (int)(sizeof(stbufs) / sizeof(*stbufs)))
|
||||
bufs = stbufs;
|
||||
else
|
||||
bufs = os_malloc (message->msg_iovlen * sizeof (*bufs));
|
||||
for (i = 0; i < message->msg_iovlen; i++)
|
||||
{
|
||||
bufs[i].buf = (void *) message->msg_iov[i].iov_base;
|
||||
bufs[i].len = (unsigned) message->msg_iov[i].iov_len;
|
||||
}
|
||||
if (WSASendTo (fd, bufs, (DWORD)message->msg_iovlen, &sent, (DWORD)flags, (SOCKADDR *) message->msg_name, message->msg_namelen, NULL, NULL) == 0) /* Type casting to silence the warning of conversion from 'size_t' to 'DWORD', which may cause possible loss of data */
|
||||
if (WSASendTo (fd, (const WSABUF *) message->msg_iov, message->msg_iovlen, &sent, flags, (SOCKADDR *) message->msg_name, message->msg_namelen, NULL, NULL) == 0)
|
||||
ret = (ssize_t) sent;
|
||||
else
|
||||
ret = -1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue