static void test_ipv6 (void) { NiceAddress addr, other, v4addr; gchar str[NICE_ADDRESS_STRING_LEN]; struct sockaddr_in6 sin, sin2; g_assert (nice_address_set_from_string (&v4addr, "172.1.0.1") == TRUE); memset (&sin, 0, sizeof (sin)); memset (&sin2, 0, sizeof (sin2)); memset (&addr, 0, sizeof (NiceAddress)); memset (&other, 0, sizeof (NiceAddress)); nice_address_init (&addr); nice_address_init (&other); nice_address_set_ipv6 (&addr, (guchar *) "\x00\x11\x22\x33" "\x44\x55\x66\x77" "\x88\x99\xaa\xbb" "\xcc\xdd\xee\xff"); g_assert (addr.s.ip6.sin6_family == AF_INET6); nice_address_to_string (&addr, str); g_assert (0 == strcmp (str, "11:2233:4455:6677:8899:aabb:ccdd:eeff")); nice_address_set_port (&addr, 9876); /* in native byte order */ nice_address_set_from_string (&other, "11:2233:4455:6677:8899:aabb:ccdd:eeff"); nice_address_set_port (&other, 9876); /* in native byte order */ nice_address_copy_to_sockaddr (&other, (struct sockaddr*)&sin2); nice_address_copy_to_sockaddr (&addr, (struct sockaddr*)&sin); g_assert (nice_address_equal (&addr, &other) == TRUE); nice_address_to_string (&addr, str); nice_address_to_string (&other, str); g_assert (memcmp (&sin, &sin2, sizeof(sin)) == 0); /* private IPv6 address */ nice_address_set_ipv6 (&addr, (guchar *) "\xfc\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x00\x00\x01"); g_assert (nice_address_is_private (&addr) == TRUE); nice_address_set_ipv6 (&addr, (guchar *) "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x00\x00\x01"); g_assert (nice_address_is_private (&addr) == TRUE); /* mismatching address families */ g_assert (nice_address_equal (&addr, &v4addr) != TRUE); /* mismatched type */ addr.s.addr.sa_family = AF_UNSPEC; /*g_assert (nice_address_equal (&addr, &v4addr) != TRUE);*/ }
static gboolean socket_send (NiceSocket *sock, const NiceAddress *to, guint len, const gchar *buf) { struct sockaddr_storage sa; ssize_t sent; nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa); sent = sendto (sock->fileno, buf, len, 0, (struct sockaddr *) &sa, sa.ss_family == AF_INET? sizeof (struct sockaddr_in) : sizeof(struct sockaddr_in6)); return sent == (ssize_t)len; }
NiceSocket * nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr) { union { struct sockaddr_storage storage; struct sockaddr addr; } name; NiceSocket *sock; TcpPriv *priv; GSocket *gsock = NULL; GError *gerr = NULL; gboolean gret = FALSE; GSocketAddress *gaddr; if (addr == NULL) { /* We can't connect a tcp socket with no destination address */ return NULL; } sock = g_slice_new0 (NiceSocket); nice_address_copy_to_sockaddr (addr, &name.addr); if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) { gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL); name.storage.ss_family = AF_INET; #ifdef HAVE_SA_LEN name.storage.ss_len = sizeof (struct sockaddr_in); #endif } else if (name.storage.ss_family == AF_INET6) { gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL); name.storage.ss_family = AF_INET6; #ifdef HAVE_SA_LEN name.storage.ss_len = sizeof (struct sockaddr_in6); #endif } if (gsock == NULL) { g_slice_free (NiceSocket, sock); return NULL; } gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name)); if (gaddr == NULL) { g_object_unref (gsock); g_slice_free (NiceSocket, sock); return NULL; } /* GSocket: All socket file descriptors are set to be close-on-exec. */ g_socket_set_blocking (gsock, false); gret = g_socket_connect (gsock, gaddr, NULL, &gerr); g_object_unref (gaddr); if (gret == FALSE) { if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_PENDING) == FALSE) { g_error_free (gerr); g_socket_close (gsock, NULL); g_object_unref (gsock); g_slice_free (NiceSocket, sock); return NULL; } g_error_free (gerr); } gaddr = g_socket_get_local_address (gsock, NULL); if (gaddr == NULL || !g_socket_address_to_native (gaddr, &name.addr, sizeof (name), NULL)) { g_slice_free (NiceSocket, sock); g_socket_close (gsock, NULL); g_object_unref (gsock); return NULL; } g_object_unref (gaddr); nice_address_set_from_sockaddr (&sock->addr, &name.addr); sock->priv = priv = g_slice_new0 (TcpPriv); if (ctx == NULL) ctx = g_main_context_default (); priv->context = g_main_context_ref (ctx); priv->server_addr = *addr; priv->error = FALSE; sock->fileno = gsock; sock->send_messages = socket_send_messages; sock->recv_messages = socket_recv_messages; sock->is_reliable = socket_is_reliable; sock->close = socket_close; return sock; }
NiceSocket * nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *local_addr, NiceAddress *remote_addr, gboolean reliable) { union { struct sockaddr_storage storage; struct sockaddr addr; } name; NiceSocket *sock; GSocket *gsock = NULL; GError *gerr = NULL; gboolean gret = FALSE; GSocketAddress *gaddr; if (remote_addr == NULL) { /* We can't connect a tcp socket with no destination address */ return NULL; } nice_address_copy_to_sockaddr (remote_addr, &name.addr); if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) { gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL); name.storage.ss_family = AF_INET; #ifdef HAVE_SA_LEN name.storage.ss_len = sizeof (struct sockaddr_in); #endif } else if (name.storage.ss_family == AF_INET6) { gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL); name.storage.ss_family = AF_INET6; #ifdef HAVE_SA_LEN name.storage.ss_len = sizeof (struct sockaddr_in6); #endif } if (gsock == NULL) { return NULL; } gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name)); if (gaddr == NULL) { g_object_unref (gsock); return NULL; } /* GSocket: All socket file descriptors are set to be close-on-exec. */ g_socket_set_blocking (gsock, false); gret = g_socket_connect (gsock, gaddr, NULL, &gerr); g_object_unref (gaddr); if (gret == FALSE) { if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_PENDING) == FALSE) { g_error_free (gerr); g_socket_close (gsock, NULL); g_object_unref (gsock); return NULL; } g_error_free (gerr); } nice_address_copy_to_sockaddr (local_addr, &name.addr); gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name)); if (gaddr == NULL) { g_socket_close (gsock, NULL); g_object_unref (gsock); return NULL; } g_socket_bind (gsock, gaddr, FALSE, NULL); g_object_unref (gaddr); sock = nice_tcp_bsd_socket_new_from_gsock (ctx, gsock, local_addr, remote_addr, reliable); g_object_unref (gsock); return sock; }
NiceSocket * nice_tcp_passive_socket_new (GMainContext *ctx, NiceAddress *addr) { union { struct sockaddr_storage storage; struct sockaddr addr; } name; NiceSocket *sock; TcpPassivePriv *priv; GSocket *gsock = NULL; gboolean gret = FALSE; GSocketAddress *gaddr; if (addr != NULL) { nice_address_copy_to_sockaddr(addr, &name.addr); } else { memset (&name, 0, sizeof (name)); name.storage.ss_family = AF_UNSPEC; } if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) { gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL); name.storage.ss_family = AF_INET; #ifdef HAVE_SA_LEN name.storage.ss_len = sizeof (struct sockaddr_in); #endif } else if (name.storage.ss_family == AF_INET6) { gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL); name.storage.ss_family = AF_INET6; #ifdef HAVE_SA_LEN name.storage.ss_len = sizeof (struct sockaddr_in6); #endif } if (gsock == NULL) { return NULL; } gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name)); if (gaddr == NULL) { g_object_unref (gsock); return NULL; } /* GSocket: All socket file descriptors are set to be close-on-exec. */ g_socket_set_blocking (gsock, false); gret = g_socket_bind (gsock, gaddr, FALSE, NULL) && g_socket_listen (gsock, NULL); g_object_unref (gaddr); if (gret == FALSE) { g_socket_close (gsock, NULL); g_object_unref (gsock); return NULL; } gaddr = g_socket_get_local_address (gsock, NULL); if (gaddr == NULL || !g_socket_address_to_native (gaddr, &name.addr, sizeof (name), NULL)) { g_socket_close (gsock, NULL); g_object_unref (gsock); return NULL; } g_object_unref (gaddr); if (ctx == NULL) { ctx = g_main_context_default (); } sock = g_slice_new0 (NiceSocket); nice_address_set_from_sockaddr (&sock->addr, &name.addr); sock->priv = priv = g_slice_new0 (TcpPassivePriv); priv->context = g_main_context_ref (ctx); priv->connections = g_hash_table_new_full ((GHashFunc) nice_address_hash, (GEqualFunc) nice_address_equal, ( GDestroyNotify) nice_address_free, NULL); priv->writable_cb = NULL; priv->writable_data = NULL; sock->type = NICE_SOCKET_TYPE_TCP_PASSIVE; sock->fileno = gsock; sock->send_messages = socket_send_messages; sock->send_messages_reliable = socket_send_messages_reliable; sock->recv_messages = socket_recv_messages; sock->is_reliable = socket_is_reliable; sock->can_send = socket_can_send; sock->set_writable_callback = socket_set_writable_callback; sock->close = socket_close; return sock; }
NiceSocket * nice_udp_bsd_socket_new (NiceAddress *addr) { int sockfd = -1; struct sockaddr_storage name; socklen_t name_len = sizeof (name); NiceSocket *sock = g_slice_new0 (NiceSocket); if (addr != NULL) { nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name); } else { memset (&name, 0, sizeof (name)); name.ss_family = AF_UNSPEC; } if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) { sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); name.ss_family = AF_INET; #ifdef HAVE_SA_LEN name.ss_len = sizeof (struct sockaddr_in); #endif } else if (name.ss_family == AF_INET6) { sockfd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP); name.ss_family = AF_INET6; #ifdef HAVE_SA_LEN name.ss_len = sizeof (struct sockaddr_in6); #endif } if (sockfd == -1) { g_slice_free (NiceSocket, sock); return NULL; } #ifdef FD_CLOEXEC fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC); #endif #ifdef O_NONBLOCK fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK); #endif if(bind (sockfd, (struct sockaddr *) &name, name.ss_family == AF_INET? sizeof (struct sockaddr_in) : sizeof(struct sockaddr_in6)) < 0) { g_slice_free (NiceSocket, sock); #ifdef G_OS_WIN32 closesocket(sockfd); #else close (sockfd); #endif return NULL; } name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) : sizeof(struct sockaddr_in6); if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) < 0) { g_slice_free (NiceSocket, sock); #ifdef G_OS_WIN32 closesocket(sockfd); #else close (sockfd); #endif return NULL; } nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name); sock->fileno = sockfd; sock->send = socket_send; sock->recv = socket_recv; sock->is_reliable = socket_is_reliable; sock->close = socket_close; return sock; }