gst_multiudpsink_init_send in a mixed v4 and v6 land (Was: udpsink: Could not set TTL socket option)

Dirk-Willem van Gulik dirkx at webweaving.org
Fri Oct 12 05:42:55 PDT 2012


Various posts have lamented about brokenness on OSX of IPv4 of udpsink. Part of the issue seems gst_multiudpsink_init_send() in gst-plugins-good. And FreeBSD is also struggling a wee little for me.

Right now the code simply tries to create an IPv6 socket. And when that fails it will create an IPv4 one. And leaves it at that - hoping that later setsocket() setting will do the right thing and that IPv6 gracefully accepts IPv4 setsocket calls.

Below is a suggestion for a slightly more robust approach - which involves checking what your potential clients one - and tuning the socket to that. Falling back to the old strategy when things fail.

This stops one full step short of having two sockets (one for IPv4 and one for IPv6; or a socket for each client in the clients list).

Thanks,

Dw.

/* create a socket for sending to remote machine */
static gboolean
gst_multiudpsink_init_send (GstMultiUDPSink * sink)
{
  guint bc_val;
  GList *clients;
  GstUDPClient *client;
  int sndsize, ret;
  socklen_t len;

  if (sink->sockfd == -1) {
    int hasIPv4 = (sink->ss_family == AF_INET ) ? 1 : 0;
    int hasIPv6 = (sink->ss_family == AF_INET6) ? 1 : 0;

    GST_DEBUG_OBJECT (sink, "creating sockets - Type is %s",
         (sink->ss_family == AF_INET) ? "IPv4" : (( sink->ss_family == AF_INET6) ? "IPv6" : "not yet defined"));

    if (! hasIPv4 && ! hasIPv6) {
      for (clients = sink->clients; clients; clients = g_list_next (clients)) {
        client = (GstUDPClient *) clients->data;
        GST_DEBUG_OBJECT (sink, "Socket for host %p port %d", client->host, client->port);

        if (client->theiraddr.ss_family == AF_INET6)
                hasIPv6 = 1;
        if (client->theiraddr.ss_family == AF_INET)
                hasIPv4 = 1;
      };
    };

    if (hasIPv6) {
        sink->ss_family = AF_INET6;
        GST_DEBUG_OBJECT (sink, "Creating an IPv6 socket %s.",
                hasIPv4 ? "(Which ought to work with IPv4 - as we also have IPv4 clients to stream to)" : "and that is the only flavour needed");
        sink->sock = socket (AF_INET6, SOCK_DGRAM, 0); // XX to check - 0 ought to be IP_UDP I guess
    }

    if (hasIPv4 ||  sink->sock == -1) {
        sink->ss_family = AF_INET;
        GST_DEBUG_OBJECT (sink, "Creating an IPv4 socket %s.",
                hasIPv6 ? "(Which may break the IPv6 clients we also have and for whom creation of an IPv6 socket failed)" : "and that is the only flavour needed");
        sink->sock = socket (AF_INET, SOCK_DGRAM, 0); ; // XX to check - 0 ought to be IP_UDP I guess
    }

    if (sink->sock == -1) {
        goto no_socket;
    }
…
…



More information about the gstreamer-devel mailing list