From 658f4b67027025542fe494448838ff5e6277d455 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Thu, 25 Sep 2014 00:51:01 +0200 Subject: removing clients works now --- src/datatypes.h | 7 ++++++- src/udp.c | 57 ++++++++++++++++++++++++++++++++++++++++++--------------- src/utils.c | 10 +++++----- src/utils.h | 2 +- 4 files changed, 54 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/datatypes.h b/src/datatypes.h index b6c6003..cc8179c 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -43,12 +43,17 @@ #include -struct addr_port{ +struct addr_port { enum { IPv4, IPv6 } type_; gchar addr_[INET6_ADDRSTRLEN + 1]; guint16 port_; }; +struct udp_client { + struct addr_port host_; + GstClockTime last_seen_; +}; + struct udp_sink { GstElement *udp_; GList* clients_; diff --git a/src/udp.c b/src/udp.c index 3c51511..c4da533 100644 --- a/src/udp.c +++ b/src/udp.c @@ -52,31 +52,46 @@ #define UDP_PROTO_CMD_RM_CLIENT "remove_client\n" #define UDP_PROTO_CMD_RM_CLIENT_LEN (sizeof(UDP_PROTO_CMD_RM_CLIENT)-1) - -static void udpsink_add_client(struct sockaddr_storage *addr, socklen_t addrlen, struct udp_sink* sink) +static struct udp_client* udp_client_new(struct sockaddr_storage *addr, socklen_t addrlen) { - struct addr_port* client = g_new(struct addr_port, 1); - if(!client) return; + struct udp_client* client = g_new(struct udp_client, 1); + if(!client) return NULL; switch(addr->ss_family) { - case AF_INET: client->type_ = IPv4; client->port_ = ntohs(((struct sockaddr_in*)addr)->sin_port); break; - case AF_INET6: client->type_ = IPv6; client->port_ = ntohs(((struct sockaddr_in6*)addr)->sin6_port); break; - default: return; + case AF_INET: client->host_.type_ = IPv4; client->host_.port_ = ntohs(((struct sockaddr_in*)addr)->sin_port); break; + case AF_INET6: client->host_.type_ = IPv6; client->host_.port_ = ntohs(((struct sockaddr_in6*)addr)->sin6_port); break; + default: g_free(client); return NULL; } - int errcode = getnameinfo((struct sockaddr *)addr, addrlen, client->addr_, sizeof(client->addr_), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + int errcode = getnameinfo((struct sockaddr *)addr, addrlen, client->host_.addr_, sizeof(client->host_.addr_), + NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); if (errcode != 0) { log_printf(WARNING, "getnameinfo() error: %s", gai_strerror(errcode)); - return; + g_free(client); + return NULL; } + return client; +} + +static void udpsink_add_client(struct sockaddr_storage *addr, socklen_t addrlen, struct udp_sink* sink) +{ + struct udp_client* client = udp_client_new(addr, addrlen); + if(!client) return; + + GTimeVal now; + g_get_current_time(&now); + client->last_seen_ = GST_TIMEVAL_TO_TIME(now); + gchar* name = gst_element_get_name(sink->udp_); - if(!g_list_find_custom(sink->clients_, client, cmp_addr_port)) { - log_printf(INFO, "adding host %s%c%d to list of receivers for element %s", client->addr_, client->type_ == IPv4 ? ':' : '.', client->port_, name); - g_signal_emit_by_name(G_OBJECT(sink->udp_), "add", client->addr_, client->port_, NULL); + if(!g_list_find_custom(sink->clients_, client, cmp_udp_client)) { + log_printf(INFO, "adding host %s%c%d to list of receivers for element %s", + client->host_.addr_, client->host_.type_ == IPv4 ? ':' : '.', client->host_.port_, name); + g_signal_emit_by_name(G_OBJECT(sink->udp_), "add", client->host_.addr_, client->host_.port_, NULL); sink->clients_ = g_list_append(sink->clients_, client); } else { - log_printf(DEBUG, "not adding host %s%c%d to list of receivers for element %s - already added", client->addr_, client->type_ == IPv4 ? ':' : '.', client->port_, name); + log_printf(DEBUG, "not adding host %s%c%d to list of receivers for element %s since it already exists", + client->host_.addr_, client->host_.type_ == IPv4 ? ':' : '.', client->host_.port_, name); g_free(client); } g_free(name); @@ -84,10 +99,22 @@ static void udpsink_add_client(struct sockaddr_storage *addr, socklen_t addrlen, static void udpsink_remove_client(struct sockaddr_storage *addr, socklen_t addrlen, struct udp_sink* sink) { - // TODO: implement this! + struct udp_client* client = udp_client_new(addr, addrlen); + if(!client) return; + + GList* removee = g_list_find_custom(sink->clients_, client, cmp_udp_client); gchar* name = gst_element_get_name(sink->udp_); - log_printf(ERROR, "removing client from %s failed! - removing not yet implemented!", name); + if(!removee) { + log_printf(WARNING, "client %s%c%d not found in client list for %s - nothing removed", + client->host_.addr_, client->host_.type_ == IPv4 ? ':' : '.', client->host_.port_, name, name); + } else { + g_signal_emit_by_name(G_OBJECT(sink->udp_), "remove", client->host_.addr_, client->host_.port_, NULL); + log_printf(INFO, "client %s%c%d removed from list of receivers for element %s", + client->host_.addr_, client->host_.type_ == IPv4 ? ':' : '.', client->host_.port_, name, name); + sink->clients_ = g_list_remove(sink->clients_, removee->data); + } g_free(name); + g_free(client); } static gboolean on_udp_desc_ready(gint fd, GIOCondition cond, gpointer user_data) diff --git a/src/utils.c b/src/utils.c index 1180b0a..729b23a 100644 --- a/src/utils.c +++ b/src/utils.c @@ -41,14 +41,14 @@ #include -gint cmp_addr_port(gconstpointer A, gconstpointer B) +gint cmp_udp_client(gconstpointer A, gconstpointer B) { - const struct addr_port *a = (const struct addr_port *)A; - const struct addr_port *b = (const struct addr_port *)B; + const struct udp_client *a = (const struct udp_client *)A; + const struct udp_client *b = (const struct udp_client *)B; - if(a->type_ != b->type_ || a->port_ != b->port_) + if(a->host_.type_ != b->host_.type_ || a->host_.port_ != b->host_.port_) return -1; - return strncmp(a->addr_, b->addr_, sizeof(a->addr_)); + return strncmp(a->host_.addr_, b->host_.addr_, sizeof(a->host_.addr_)); } GstElement* sydra_create_bin_from_desc(const char* type, const char* desc) diff --git a/src/utils.h b/src/utils.h index 9916ea3..d1797db 100644 --- a/src/utils.h +++ b/src/utils.h @@ -38,7 +38,7 @@ #include -gint cmp_addr_port(gconstpointer A, gconstpointer B); +gint cmp_udp_client(gconstpointer A, gconstpointer B); GstElement* sydra_create_bin_from_desc(const char* type, const char* desc); GstElement* sydra_create_element(const char* type, const char* name); gboolean sydra_link_request_static(GstElement* src, const char* src_pad_name, GstElement* sink, const char* sink_pad_name); -- cgit v1.2.3