summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Young <rcxdude@gmail.com>2012-05-07 23:20:57 +0100
committerMartin Sustrik <sustrik@250bpm.com>2012-05-09 07:50:19 +0200
commit0abe1093ad8f89e562ea583a18e8c4d79a2ff2b2 (patch)
tree3b5edbfa6ac715f777678098cc96e09430ebe9c3
parent1dbcf1a01f0bb704db85d3117baafe86ce4d2d8e (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.cpp63
-rw-r--r--src/pgm_socket.hpp2
-rw-r--r--src/socket_base.cpp15
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 ());