From 0abe1093ad8f89e562ea583a18e8c4d79a2ff2b2 Mon Sep 17 00:00:00 2001 From: Douglas Young Date: Mon, 7 May 2012 23:20:57 +0100 Subject: Return an error on invalid (e)pgm:// connection This prevents the long-standing issue of an invalid pgm or epgm connection string from causing an assert when the connection is attempted and fails. --- src/pgm_socket.cpp | 63 +++++++++++++++++++++++++++++++++-------------------- src/pgm_socket.hpp | 2 ++ src/socket_base.cpp | 15 +++++++++++++ 3 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/pgm_socket.cpp b/src/pgm_socket.cpp index 7747fe0..bc2c0e4 100644 --- a/src/pgm_socket.cpp +++ b/src/pgm_socket.cpp @@ -67,16 +67,13 @@ xs::pgm_socket_t::pgm_socket_t (bool receiver_, const options_t &options_) : { } -// Create, bind and connect PGM socket. // network_ of the form : // e.g. eth0;239.192.0.1:7500 // link-local;224.250.0.1,224.250.0.2;224.250.0.3:8000 // ;[fe80::1%en0]:7500 -int xs::pgm_socket_t::init (bool udp_encapsulation_, const char *network_) +int xs::pgm_socket_t::init_address(const char *network_, + struct pgm_addrinfo_t **addr, uint16_t *port_number) { - // Can not open transport before destroying old one. - xs_assert (sock == NULL); - // Parse port number, start from end for IPv6 const char *port_delim = strrchr (network_, ':'); if (!port_delim) { @@ -84,8 +81,8 @@ int xs::pgm_socket_t::init (bool udp_encapsulation_, const char *network_) return -1; } - uint16_t port_number = atoi (port_delim + 1); - + *port_number = atoi (port_delim + 1); + char network [256]; if (port_delim - network_ >= (int) sizeof (network) - 1) { errno = EINVAL; @@ -93,36 +90,54 @@ int xs::pgm_socket_t::init (bool udp_encapsulation_, const char *network_) } memset (network, '\0', sizeof (network)); memcpy (network, network_, port_delim - network_); - - xs_assert (options.rate > 0); - - // Zero counter used in msgrecv. - nbytes_rec = 0; - nbytes_processed = 0; - pgm_msgv_processed = 0; - pgm_error_t *pgm_error = NULL; - struct pgm_addrinfo_t hints, *res = NULL; - sa_family_t sa_family; + struct pgm_addrinfo_t hints; memset (&hints, 0, sizeof (hints)); hints.ai_family = AF_UNSPEC; - if (!pgm_getaddrinfo (network, NULL, &res, &pgm_error)) { + + if (!pgm_getaddrinfo (network, NULL, addr, &pgm_error)) { // Invalid parameters don't set pgm_error_t. xs_assert (pgm_error != NULL); - if (pgm_error->domain == PGM_ERROR_DOMAIN_IF && ( - - // NB: cannot catch EAI_BADFLAGS. - pgm_error->code != PGM_ERROR_SERVICE && - pgm_error->code != PGM_ERROR_SOCKTNOSUPPORT)) + if (pgm_error->domain == PGM_ERROR_DOMAIN_IF && + // NB: cannot catch EAI_BADFLAGS. + ( pgm_error->code != PGM_ERROR_SERVICE && + pgm_error->code != PGM_ERROR_SOCKTNOSUPPORT)) { // User, host, or network configuration or transient error. - goto err_abort; + pgm_error_free (pgm_error); + errno = EINVAL; + return -1; + } // Fatal OpenPGM internal error. xs_assert (false); } + return 0; +} + +// Create, bind and connect PGM socket. +int xs::pgm_socket_t::init (bool udp_encapsulation_, const char *network_) +{ + // Can not open transport before destroying old one. + xs_assert (sock == NULL); + xs_assert (options.rate > 0); + + // Zero counter used in msgrecv. + nbytes_rec = 0; + nbytes_processed = 0; + pgm_msgv_processed = 0; + + uint16_t port_number; + struct pgm_addrinfo_t *res = NULL; + sa_family_t sa_family; + + pgm_error_t *pgm_error = NULL; + + if (init_address(network_, &res, &port_number) < 0) { + goto err_abort; + } xs_assert (res != NULL); diff --git a/src/pgm_socket.hpp b/src/pgm_socket.hpp index d2c6e15..0d6fe33 100644 --- a/src/pgm_socket.hpp +++ b/src/pgm_socket.hpp @@ -57,6 +57,8 @@ namespace xs // Initialize PGM network structures (GSI, GSRs). int init (bool udp_encapsulation_, const char *network_); + + static int init_address(const char *network_, struct pgm_addrinfo_t **addr, uint16_t *port_number); // Get receiver fds and store them into user allocated memory. void get_receiver_fds (fd_t *receive_fd_, fd_t *waiting_pipe_fd_); diff --git a/src/socket_base.cpp b/src/socket_base.cpp index 8ee8bd3..f1e7fca 100644 --- a/src/socket_base.cpp +++ b/src/socket_base.cpp @@ -34,6 +34,9 @@ #else #include #endif +#ifdef XS_HAVE_OPENPGM +#include "pgm_socket.hpp" +#endif #include "socket_base.hpp" #include "tcp_listener.hpp" @@ -508,6 +511,18 @@ int xs::socket_base_t::connect (const char *addr_) } } +#ifdef XS_HAVE_OPENPGM + if (protocol == "pgm" || protocol == "epgm") { + struct pgm_addrinfo_t *res = NULL; + uint16_t port_number = 0; + int rc = pgm_socket_t::init_address(address.c_str(), &res, &port_number); + if (res != NULL) + pgm_freeaddrinfo (res); + if (rc != 0 || port_number == 0) + return -1; + } +#endif + // Create session. session_base_t *session = session_base_t::create (thread, true, this, options, protocol.c_str (), address.c_str ()); -- cgit v1.2.3