diff options
| author | Douglas Young <rcxdude@gmail.com> | 2012-05-07 23:20:57 +0100 | 
|---|---|---|
| committer | Martin Sustrik <sustrik@250bpm.com> | 2012-05-09 07:50:19 +0200 | 
| commit | 0abe1093ad8f89e562ea583a18e8c4d79a2ff2b2 (patch) | |
| tree | 3b5edbfa6ac715f777678098cc96e09430ebe9c3 | |
| parent | 1dbcf1a01f0bb704db85d3117baafe86ce4d2d8e (diff) | |
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.
| -rw-r--r-- | src/pgm_socket.cpp | 63 | ||||
| -rw-r--r-- | src/pgm_socket.hpp | 2 | ||||
| -rw-r--r-- | 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 <interface & multicast group decls>:<IP port>  //  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 <unistd.h>  #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 ());  | 
