Merged in default (pull request #479)

Fri, 22 Mar 2019 02:42:46 +0000

author
Gary Kramlich <grim@reaperworld.com>
date
Fri, 22 Mar 2019 02:42:46 +0000
changeset 39496
47ccfc3f8b8b
parent 39493
72d1afcb0a8c (current diff)
parent 39495
8ee55780b724 (diff)
child 39505
c83224788776

Merged in default (pull request #479)

Update most things to use G_DEFINE_DYNAMIC_TYPE and a host of other updates

Approved-by: Elliott Sales de Andrade

--- a/libpurple/protocols/jabber/google/google_p2p.c	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/google/google_p2p.c	Fri Mar 22 02:42:46 2019 +0000
@@ -31,23 +31,11 @@
 
 #include <string.h>
 
-struct _JingleGoogleP2PPrivate
+typedef struct
 {
 	GList *local_candidates;
 	GList *remote_candidates;
-};
-
-#define JINGLE_GOOGLE_P2P_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_GOOGLE_P2P, JingleGoogleP2PPrivate))
-
-static void jingle_google_p2p_class_init (JingleGoogleP2PClass *klass);
-static void jingle_google_p2p_init (JingleGoogleP2P *google_p2p);
-static void jingle_google_p2p_finalize (GObject *object);
-static void jingle_google_p2p_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void jingle_google_p2p_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static JingleTransport *jingle_google_p2p_parse_internal(PurpleXmlNode *google_p2p);
-static PurpleXmlNode *jingle_google_p2p_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action);
-static void jingle_google_p2p_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate);
-static GList *jingle_google_p2p_get_remote_candidates(JingleTransport *transport);
+} JingleGoogleP2PPrivate;
 
 enum {
 	PROP_0,
@@ -56,163 +44,25 @@
 	PROP_LAST
 };
 
-static JingleTransportClass *parent_class = NULL;
 static GParamSpec *properties[PROP_LAST];
 
-static JingleGoogleP2PCandidate *
-jingle_google_p2p_candidate_copy(JingleGoogleP2PCandidate *candidate)
-{
-	JingleGoogleP2PCandidate *new_candidate = g_new0(JingleGoogleP2PCandidate, 1);
-	new_candidate->id = g_strdup(candidate->id);
-	new_candidate->address = g_strdup(candidate->address);
-	new_candidate->port = candidate->port;
-	new_candidate->preference = candidate->preference;
-	new_candidate->type = g_strdup(candidate->type);
-	new_candidate->protocol = g_strdup(candidate->protocol);
-	new_candidate->username = g_strdup(candidate->username);
-	new_candidate->password = g_strdup(candidate->password);
-	new_candidate->generation = candidate->generation;
-
-	new_candidate->rem_known = candidate->rem_known;
-
-	return new_candidate;
-}
-
-static void
-jingle_google_p2p_candidate_free(JingleGoogleP2PCandidate *candidate)
-{
-	g_free(candidate->id);
-	g_free(candidate->address);
-	g_free(candidate->type);
-	g_free(candidate->protocol);
-	g_free(candidate->username);
-	g_free(candidate->password);
-}
-
-G_DEFINE_BOXED_TYPE(JingleGoogleP2PCandidate, jingle_google_p2p_candidate,
-		jingle_google_p2p_candidate_copy, jingle_google_p2p_candidate_free)
-
-JingleGoogleP2PCandidate *
-jingle_google_p2p_candidate_new(const gchar *id, guint generation,
-		const gchar *address, guint port, guint preference,
-		const gchar *type, const gchar *protocol,
-		const gchar *username, const gchar *password)
-{
-	JingleGoogleP2PCandidate *candidate = g_new0(JingleGoogleP2PCandidate, 1);
-	candidate->id = g_strdup(id);
-	candidate->address = g_strdup(address);
-	candidate->port = port;
-	candidate->preference = preference;
-	candidate->type = g_strdup(type);
-	candidate->protocol = g_strdup(protocol);
-	candidate->username = g_strdup(username);
-	candidate->password = g_strdup(password);
-	candidate->generation = generation;
-
-	candidate->rem_known = FALSE;
-	return candidate;
-}
-
-PURPLE_DEFINE_TYPE(JingleGoogleP2P, jingle_google_p2p, JINGLE_TYPE_TRANSPORT);
-
-static void
-jingle_google_p2p_class_init(JingleGoogleP2PClass *klass)
-{
-	GObjectClass *gobject_class = (GObjectClass *)klass;
-	parent_class = g_type_class_peek_parent(klass);
-
-	gobject_class->finalize = jingle_google_p2p_finalize;
-	gobject_class->set_property = jingle_google_p2p_set_property;
-	gobject_class->get_property = jingle_google_p2p_get_property;
-	klass->parent_class.to_xml = jingle_google_p2p_to_xml_internal;
-	klass->parent_class.parse = jingle_google_p2p_parse_internal;
-	klass->parent_class.transport_type = NS_GOOGLE_TRANSPORT_P2P;
-	klass->parent_class.add_local_candidate = jingle_google_p2p_add_local_candidate;
-	klass->parent_class.get_remote_candidates = jingle_google_p2p_get_remote_candidates;
-
-	g_type_class_add_private(klass, sizeof(JingleGoogleP2PPrivate));
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(
+	JingleGoogleP2P,
+	jingle_google_p2p,
+	JINGLE_TYPE_TRANSPORT,
+	0,
+	G_ADD_PRIVATE_DYNAMIC(JingleGoogleP2P)
+);
 
-	properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
-			"Local candidates",
-			"The local candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
-			"Remote candidates",
-			"The remote candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(gobject_class, PROP_LAST, properties);
-}
-
-static void
-jingle_google_p2p_init(JingleGoogleP2P *google_p2p)
-{
-	google_p2p->priv = JINGLE_GOOGLE_P2P_GET_PRIVATE(google_p2p);
-	google_p2p->priv->local_candidates = NULL;
-	google_p2p->priv->remote_candidates = NULL;
-}
-
-static void
-jingle_google_p2p_finalize(GObject *google_p2p)
-{
-/*	JingleGoogleP2PPrivate *priv = JINGLE_GOOGLE_P2P_GET_PRIVATE(google_p2p); */
-	purple_debug_info("jingle","jingle_google_p2p_finalize\n");
-
-	G_OBJECT_CLASS(parent_class)->finalize(google_p2p);
-}
-
-static void
-jingle_google_p2p_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleGoogleP2P *google_p2p;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_GOOGLE_P2P(object));
-
-	google_p2p = JINGLE_GOOGLE_P2P(object);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			google_p2p->priv->local_candidates = g_value_get_pointer(value);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			google_p2p->priv->remote_candidates = g_value_get_pointer(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_google_p2p_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleGoogleP2P *google_p2p;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_GOOGLE_P2P(object));
-
-	google_p2p = JINGLE_GOOGLE_P2P(object);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			g_value_set_pointer(value, google_p2p->priv->local_candidates);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			g_value_set_pointer(value, google_p2p->priv->remote_candidates);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
+/******************************************************************************
+ * JingleGoogleP2P Transport Implementation
+ *****************************************************************************/
 static void
 jingle_google_p2p_add_local_candidate(JingleTransport *transport, const gchar *id,
                                       guint generation, PurpleMediaCandidate *candidate)
 {
 	JingleGoogleP2P *google_p2p = JINGLE_GOOGLE_P2P(transport);
+	JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
 	JingleGoogleP2PCandidate *google_p2p_candidate;
 	gchar *ip;
 	gchar *username;
@@ -242,19 +92,19 @@
 	g_free(username);
 	g_free(ip);
 
-	for (iter = google_p2p->priv->local_candidates; iter; iter = g_list_next(iter)) {
+	for (iter = priv->local_candidates; iter; iter = g_list_next(iter)) {
 		JingleGoogleP2PCandidate *c = iter->data;
 		if (!strcmp(c->id, id)) {
 			generation = c->generation + 1;
 
 			g_boxed_free(JINGLE_TYPE_GOOGLE_P2P_CANDIDATE, c);
-			google_p2p->priv->local_candidates = g_list_delete_link(
-					google_p2p->priv->local_candidates, iter);
+			priv->local_candidates = g_list_delete_link(
+					priv->local_candidates, iter);
 
 			google_p2p_candidate->generation = generation;
 
-			google_p2p->priv->local_candidates = g_list_append(
-					google_p2p->priv->local_candidates, candidate);
+			priv->local_candidates = g_list_append(
+					priv->local_candidates, candidate);
 
 			g_object_notify_by_pspec(G_OBJECT(google_p2p), properties[PROP_LOCAL_CANDIDATES]);
 
@@ -262,17 +112,50 @@
 		}
 	}
 
-	google_p2p->priv->local_candidates = g_list_append(
-			google_p2p->priv->local_candidates, google_p2p_candidate);
+	priv->local_candidates = g_list_append(
+			priv->local_candidates, google_p2p_candidate);
 
 	g_object_notify_by_pspec(G_OBJECT(google_p2p), properties[PROP_LOCAL_CANDIDATES]);
 }
 
+static JingleGoogleP2PCandidate *
+jingle_google_p2p_get_remote_candidate_by_id(JingleGoogleP2P *google_p2p,
+		const gchar *id)
+{
+	JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
+	GList *iter = priv->remote_candidates;
+	for (; iter; iter = g_list_next(iter)) {
+		JingleGoogleP2PCandidate *candidate = iter->data;
+		if (!strcmp(candidate->id, id)) {
+			return candidate;
+		}
+	}
+	return NULL;
+}
+
+static void
+jingle_google_p2p_add_remote_candidate(JingleGoogleP2P *google_p2p, JingleGoogleP2PCandidate *candidate)
+{
+	JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
+	JingleGoogleP2PCandidate *google_p2p_candidate =
+			jingle_google_p2p_get_remote_candidate_by_id(google_p2p,
+					candidate->id);
+	if (google_p2p_candidate != NULL) {
+		priv->remote_candidates = g_list_remove(priv->remote_candidates,
+		                                        google_p2p_candidate);
+		g_boxed_free(JINGLE_TYPE_GOOGLE_P2P_CANDIDATE, google_p2p_candidate);
+	}
+	priv->remote_candidates = g_list_append(priv->remote_candidates, candidate);
+
+	g_object_notify_by_pspec(G_OBJECT(google_p2p), properties[PROP_REMOTE_CANDIDATES]);
+}
+
 static GList *
 jingle_google_p2p_get_remote_candidates(JingleTransport *transport)
 {
 	JingleGoogleP2P *google_p2p = JINGLE_GOOGLE_P2P(transport);
-	GList *candidates = google_p2p->priv->remote_candidates;
+	JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
+	GList *candidates = priv->remote_candidates;
 	GList *ret = NULL;
 
 	for (; candidates; candidates = g_list_next(candidates)) {
@@ -301,85 +184,17 @@
 	return ret;
 }
 
-static JingleGoogleP2PCandidate *
-jingle_google_p2p_get_remote_candidate_by_id(JingleGoogleP2P *google_p2p,
-		const gchar *id)
-{
-	GList *iter = google_p2p->priv->remote_candidates;
-	for (; iter; iter = g_list_next(iter)) {
-		JingleGoogleP2PCandidate *candidate = iter->data;
-		if (!strcmp(candidate->id, id)) {
-			return candidate;
-		}
-	}
-	return NULL;
-}
-
-static void
-jingle_google_p2p_add_remote_candidate(JingleGoogleP2P *google_p2p, JingleGoogleP2PCandidate *candidate)
-{
-	JingleGoogleP2PPrivate *priv = JINGLE_GOOGLE_P2P_GET_PRIVATE(google_p2p);
-	JingleGoogleP2PCandidate *google_p2p_candidate =
-			jingle_google_p2p_get_remote_candidate_by_id(google_p2p,
-					candidate->id);
-	if (google_p2p_candidate != NULL) {
-		priv->remote_candidates = g_list_remove(priv->remote_candidates,
-		                                        google_p2p_candidate);
-		g_boxed_free(JINGLE_TYPE_GOOGLE_P2P_CANDIDATE, google_p2p_candidate);
-	}
-	priv->remote_candidates = g_list_append(priv->remote_candidates, candidate);
-
-	g_object_notify_by_pspec(G_OBJECT(google_p2p), properties[PROP_REMOTE_CANDIDATES]);
-}
-
-static JingleTransport *
-jingle_google_p2p_parse_internal(PurpleXmlNode *google_p2p)
-{
-	JingleTransport *transport = parent_class->parse(google_p2p);
-	PurpleXmlNode *candidate = purple_xmlnode_get_child(google_p2p, "candidate");
-	JingleGoogleP2PCandidate *google_p2p_candidate = NULL;
-
-	for (; candidate; candidate = purple_xmlnode_get_next_twin(candidate)) {
-		const gchar *generation = purple_xmlnode_get_attrib(candidate, "generation");
-		const gchar *id = purple_xmlnode_get_attrib(candidate, "name");
-		const gchar *address = purple_xmlnode_get_attrib(candidate, "address");
-		const gchar *port = purple_xmlnode_get_attrib(candidate, "port");
-		const gchar *preference = purple_xmlnode_get_attrib(candidate, "preference");
-		const gchar *type = purple_xmlnode_get_attrib(candidate, "type");
-		const gchar *protocol = purple_xmlnode_get_attrib(candidate, "protocol");
-		const gchar *username = purple_xmlnode_get_attrib(candidate, "username");
-		const gchar *password = purple_xmlnode_get_attrib(candidate, "password");
-
-		if (!generation || !id || !address || !port || !preference ||
-				!type || !protocol || !username || !password)
-			continue;
-
-		google_p2p_candidate = jingle_google_p2p_candidate_new(id,
-				atoi(generation),
-				address,
-				atoi(port),
-				atoi(preference),
-				type,
-				protocol,
-				username, password);
-		google_p2p_candidate->rem_known = TRUE;
-		jingle_google_p2p_add_remote_candidate(JINGLE_GOOGLE_P2P(transport), google_p2p_candidate);
-	}
-
-	return transport;
-}
-
 static PurpleXmlNode *
 jingle_google_p2p_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
 {
-	PurpleXmlNode *node = parent_class->to_xml(transport, content, action);
+	PurpleXmlNode *node = JINGLE_TRANSPORT_CLASS(jingle_google_p2p_parent_class)->to_xml(transport, content, action);
 
 	if (action == JINGLE_SESSION_INITIATE ||
 			action == JINGLE_SESSION_ACCEPT ||
 			action == JINGLE_TRANSPORT_INFO ||
 			action == JINGLE_CONTENT_ADD ||
 			action == JINGLE_TRANSPORT_REPLACE) {
-		JingleGoogleP2PPrivate *priv = JINGLE_GOOGLE_P2P_GET_PRIVATE(transport);
+		JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(JINGLE_GOOGLE_P2P(transport));
 		GList *iter = priv->local_candidates;
 
 		for (; iter; iter = g_list_next(iter)) {
@@ -419,3 +234,193 @@
 	return node;
 }
 
+static JingleTransport *
+jingle_google_p2p_parse_internal(PurpleXmlNode *google_p2p)
+{
+	JingleTransport *transport = JINGLE_TRANSPORT_CLASS(jingle_google_p2p_parent_class)->parse(google_p2p);
+	PurpleXmlNode *candidate = purple_xmlnode_get_child(google_p2p, "candidate");
+	JingleGoogleP2PCandidate *google_p2p_candidate = NULL;
+
+	for (; candidate; candidate = purple_xmlnode_get_next_twin(candidate)) {
+		const gchar *generation = purple_xmlnode_get_attrib(candidate, "generation");
+		const gchar *id = purple_xmlnode_get_attrib(candidate, "name");
+		const gchar *address = purple_xmlnode_get_attrib(candidate, "address");
+		const gchar *port = purple_xmlnode_get_attrib(candidate, "port");
+		const gchar *preference = purple_xmlnode_get_attrib(candidate, "preference");
+		const gchar *type = purple_xmlnode_get_attrib(candidate, "type");
+		const gchar *protocol = purple_xmlnode_get_attrib(candidate, "protocol");
+		const gchar *username = purple_xmlnode_get_attrib(candidate, "username");
+		const gchar *password = purple_xmlnode_get_attrib(candidate, "password");
+
+		if (!generation || !id || !address || !port || !preference ||
+				!type || !protocol || !username || !password)
+			continue;
+
+		google_p2p_candidate = jingle_google_p2p_candidate_new(id,
+				atoi(generation),
+				address,
+				atoi(port),
+				atoi(preference),
+				type,
+				protocol,
+				username, password);
+		google_p2p_candidate->rem_known = TRUE;
+		jingle_google_p2p_add_remote_candidate(JINGLE_GOOGLE_P2P(transport), google_p2p_candidate);
+	}
+
+	return transport;
+}
+
+/******************************************************************************
+ * JingleGoogleP2P GObject stuff
+ *****************************************************************************/
+static void
+jingle_google_p2p_init(JingleGoogleP2P *google_p2p)
+{
+}
+
+static void
+jingle_google_p2p_finalize(GObject *google_p2p)
+{
+/*	JingleGoogleP2PPrivate *priv = JINGLE_GOOGLE_P2P_GET_PRIVATE(google_p2p); */
+	purple_debug_info("jingle","jingle_google_p2p_finalize\n");
+
+	G_OBJECT_CLASS(jingle_google_p2p_parent_class)->finalize(google_p2p);
+}
+
+static void
+jingle_google_p2p_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	JingleGoogleP2P *google_p2p = JINGLE_GOOGLE_P2P(object);
+	JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
+
+	switch (prop_id) {
+		case PROP_LOCAL_CANDIDATES:
+			priv->local_candidates = g_value_get_pointer(value);
+			break;
+		case PROP_REMOTE_CANDIDATES:
+			priv->remote_candidates = g_value_get_pointer(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_google_p2p_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	JingleGoogleP2P *google_p2p = JINGLE_GOOGLE_P2P(object);
+	JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
+
+	switch (prop_id) {
+		case PROP_LOCAL_CANDIDATES:
+			g_value_set_pointer(value, priv->local_candidates);
+			break;
+		case PROP_REMOTE_CANDIDATES:
+			g_value_set_pointer(value, priv->remote_candidates);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_google_p2p_class_finalize(JingleGoogleP2PClass *klass) {
+}
+
+static void
+jingle_google_p2p_class_init(JingleGoogleP2PClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	JingleTransportClass *transport_class = JINGLE_TRANSPORT_CLASS(klass);
+
+	obj_class->finalize = jingle_google_p2p_finalize;
+	obj_class->set_property = jingle_google_p2p_set_property;
+	obj_class->get_property = jingle_google_p2p_get_property;
+
+	transport_class->to_xml = jingle_google_p2p_to_xml_internal;
+	transport_class->parse = jingle_google_p2p_parse_internal;
+	transport_class->transport_type = NS_GOOGLE_TRANSPORT_P2P;
+	transport_class->add_local_candidate = jingle_google_p2p_add_local_candidate;
+	transport_class->get_remote_candidates = jingle_google_p2p_get_remote_candidates;
+
+	properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
+			"Local candidates",
+			"The local candidates for this transport.",
+			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
+			"Remote candidates",
+			"The remote candidates for this transport.",
+			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(obj_class, PROP_LAST, properties);
+}
+
+/******************************************************************************
+ * JingleGoogleP2PCandidate Boxed Implementation
+ *****************************************************************************/
+static JingleGoogleP2PCandidate *
+jingle_google_p2p_candidate_copy(JingleGoogleP2PCandidate *candidate)
+{
+	JingleGoogleP2PCandidate *new_candidate = g_new0(JingleGoogleP2PCandidate, 1);
+	new_candidate->id = g_strdup(candidate->id);
+	new_candidate->address = g_strdup(candidate->address);
+	new_candidate->port = candidate->port;
+	new_candidate->preference = candidate->preference;
+	new_candidate->type = g_strdup(candidate->type);
+	new_candidate->protocol = g_strdup(candidate->protocol);
+	new_candidate->username = g_strdup(candidate->username);
+	new_candidate->password = g_strdup(candidate->password);
+	new_candidate->generation = candidate->generation;
+
+	new_candidate->rem_known = candidate->rem_known;
+
+	return new_candidate;
+}
+
+static void
+jingle_google_p2p_candidate_free(JingleGoogleP2PCandidate *candidate)
+{
+	g_free(candidate->id);
+	g_free(candidate->address);
+	g_free(candidate->type);
+	g_free(candidate->protocol);
+	g_free(candidate->username);
+	g_free(candidate->password);
+}
+
+G_DEFINE_BOXED_TYPE(JingleGoogleP2PCandidate, jingle_google_p2p_candidate,
+		jingle_google_p2p_candidate_copy, jingle_google_p2p_candidate_free)
+
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+void
+jingle_google_p2p_register(PurplePlugin *plugin) {
+	jingle_google_p2p_register_type(G_TYPE_MODULE(plugin));
+}
+
+JingleGoogleP2PCandidate *
+jingle_google_p2p_candidate_new(const gchar *id, guint generation,
+		const gchar *address, guint port, guint preference,
+		const gchar *type, const gchar *protocol,
+		const gchar *username, const gchar *password)
+{
+	JingleGoogleP2PCandidate *candidate = g_new0(JingleGoogleP2PCandidate, 1);
+	candidate->id = g_strdup(id);
+	candidate->address = g_strdup(address);
+	candidate->port = port;
+	candidate->preference = preference;
+	candidate->type = g_strdup(type);
+	candidate->protocol = g_strdup(protocol);
+	candidate->username = g_strdup(username);
+	candidate->password = g_strdup(password);
+	candidate->generation = generation;
+
+	candidate->rem_known = FALSE;
+	return candidate;
+}
--- a/libpurple/protocols/jabber/google/google_p2p.h	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/google/google_p2p.h	Fri Mar 22 02:42:46 2019 +0000
@@ -33,7 +33,6 @@
 G_BEGIN_DECLS
 
 #define JINGLE_TYPE_GOOGLE_P2P            (jingle_google_p2p_get_type())
-#define JINGLE_TYPE_GOOGLE_P2P_CANDIDATE  (jingle_google_p2p_candidate_get_type())
 #define JINGLE_GOOGLE_P2P(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), JINGLE_TYPE_GOOGLE_P2P, JingleGoogleP2P))
 #define JINGLE_GOOGLE_P2P_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), JINGLE_TYPE_GOOGLE_P2P, JingleGoogleP2PClass))
 #define JINGLE_IS_GOOGLE_P2P(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), JINGLE_TYPE_GOOGLE_P2P))
@@ -44,8 +43,9 @@
 typedef struct _JingleGoogleP2P JingleGoogleP2P;
 /** @copydoc _JingleGoogleP2PClass */
 typedef struct _JingleGoogleP2PClass JingleGoogleP2PClass;
-/** @copydoc _JingleGoogleP2PPrivate */
-typedef struct _JingleGoogleP2PPrivate JingleGoogleP2PPrivate;
+
+#define JINGLE_TYPE_GOOGLE_P2P_CANDIDATE  (jingle_google_p2p_candidate_get_type())
+
 /** @copydoc _JingleGoogleP2PCandidate */
 typedef struct _JingleGoogleP2PCandidate JingleGoogleP2PCandidate;
 
@@ -62,7 +62,6 @@
 struct _JingleGoogleP2P
 {
 	JingleTransport parent;         /**< The parent of this object. */
-	JingleGoogleP2PPrivate *priv;   /**< The private data of this object. */
 };
 
 struct _JingleGoogleP2PCandidate
@@ -94,7 +93,7 @@
 /**
  * Registers the JingleGoogleP2P type in the type system.
  */
-void jingle_google_p2p_register_type(PurplePlugin *plugin);
+void jingle_google_p2p_register(PurplePlugin *plugin);
 
 JingleGoogleP2PCandidate *jingle_google_p2p_candidate_new(const gchar *id,
 		guint generation, const gchar *address, guint port, guint preference,
--- a/libpurple/protocols/jabber/jabber.c	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Fri Mar 22 02:42:46 2019 +0000
@@ -4259,16 +4259,16 @@
 static gboolean
 plugin_load(PurplePlugin *plugin, GError **error)
 {
-	jingle_session_register_type(plugin);
-
-	jingle_transport_register_type(plugin);
-	jingle_iceudp_register_type(plugin);
-	jingle_rawudp_register_type(plugin);
-	jingle_google_p2p_register_type(plugin);
-
-	jingle_content_register_type(plugin);
+	jingle_session_register(plugin);
+
+	jingle_transport_register(plugin);
+	jingle_iceudp_register(plugin);
+	jingle_rawudp_register(plugin);
+	jingle_google_p2p_register(plugin);
+
+	jingle_content_register(plugin);
 #ifdef USE_VV
-	jingle_rtp_register_type(plugin);
+	jingle_rtp_register(plugin);
 #endif
 
 	jabber_protocol_register_type(plugin);
--- a/libpurple/protocols/jabber/jingle/content.c	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/content.c	Fri Mar 22 02:42:46 2019 +0000
@@ -31,7 +31,7 @@
 
 #include <string.h>
 
-struct _JingleContentPrivate
+typedef struct
 {
 	JingleSession *session;
 	gchar *description_type;
@@ -41,17 +41,7 @@
 	gchar *senders;
 	JingleTransport *transport;
 	JingleTransport *pending_transport;
-};
-
-#define JINGLE_CONTENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_CONTENT, JingleContentPrivate))
-
-static void jingle_content_class_init (JingleContentClass *klass);
-static void jingle_content_init (JingleContent *content);
-static void jingle_content_finalize (GObject *object);
-static void jingle_content_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void jingle_content_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static PurpleXmlNode *jingle_content_to_xml_internal(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action);
-static JingleContent *jingle_content_parse_internal(PurpleXmlNode *content);
+} JingleContentPrivate;
 
 enum {
 	PROP_0,
@@ -65,25 +55,205 @@
 	PROP_LAST
 };
 
-static GObjectClass *parent_class = NULL;
 static GParamSpec *properties[PROP_LAST];
 
-PURPLE_DEFINE_TYPE(JingleContent, jingle_content, G_TYPE_OBJECT);
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(
+	JingleContent,
+	jingle_content,
+	G_TYPE_OBJECT,
+	0,
+	G_ADD_PRIVATE_DYNAMIC(JingleContent)
+);
+
+/******************************************************************************
+ * JingleContent Implementation
+ *****************************************************************************/
+static JingleContent *
+jingle_content_parse_internal(PurpleXmlNode *content)
+{
+	PurpleXmlNode *description = purple_xmlnode_get_child(content, "description");
+	const gchar *type = purple_xmlnode_get_namespace(description);
+	const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
+	const gchar *disposition = purple_xmlnode_get_attrib(content, "disposition");
+	const gchar *senders = purple_xmlnode_get_attrib(content, "senders");
+	const gchar *name = purple_xmlnode_get_attrib(content, "name");
+	JingleTransport *transport =
+			jingle_transport_parse(purple_xmlnode_get_child(content, "transport"));
+	if (transport == NULL)
+		return NULL;
+
+	if (senders == NULL)
+		senders = "both";
+
+	return jingle_content_create(type, creator, disposition, name, senders, transport);
+}
+
+static PurpleXmlNode *
+jingle_content_to_xml_internal(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action)
+{
+	PurpleXmlNode *node = purple_xmlnode_new_child(jingle, "content");
+	gchar *creator = jingle_content_get_creator(content);
+	gchar *name = jingle_content_get_name(content);
+	gchar *senders = jingle_content_get_senders(content);
+	gchar *disposition = jingle_content_get_disposition(content);
+
+	purple_xmlnode_set_attrib(node, "creator", creator);
+	purple_xmlnode_set_attrib(node, "name", name);
+	purple_xmlnode_set_attrib(node, "senders", senders);
+	if (!purple_strequal("session", disposition))
+		purple_xmlnode_set_attrib(node, "disposition", disposition);
+
+	g_free(disposition);
+	g_free(senders);
+	g_free(name);
+	g_free(creator);
+
+	if (action != JINGLE_CONTENT_REMOVE) {
+		JingleTransport *transport;
+
+		if (action != JINGLE_TRANSPORT_ACCEPT &&
+				action != JINGLE_TRANSPORT_INFO &&
+				action != JINGLE_TRANSPORT_REJECT &&
+				action != JINGLE_TRANSPORT_REPLACE) {
+			PurpleXmlNode *description = purple_xmlnode_new_child(node, "description");
+
+			purple_xmlnode_set_namespace(description,
+					jingle_content_get_description_type(content));
+		}
+
+		if (action != JINGLE_TRANSPORT_REJECT && action == JINGLE_TRANSPORT_REPLACE)
+			transport = jingle_content_get_pending_transport(content);
+		else
+			transport = jingle_content_get_transport(content);
+
+		jingle_transport_to_xml(transport, node, action);
+		g_object_unref(transport);
+	}
+
+	return node;
+}
+
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+static void
+jingle_content_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	JingleContent *content = JINGLE_CONTENT(object);
+	JingleContentPrivate *priv = jingle_content_get_instance_private(content);
+
+	switch (prop_id) {
+		case PROP_SESSION:
+			priv->session = g_value_get_object(value);
+			break;
+		case PROP_CREATOR:
+			g_free(priv->creator);
+			priv->creator = g_value_dup_string(value);
+			break;
+		case PROP_DISPOSITION:
+			g_free(priv->disposition);
+			priv->disposition = g_value_dup_string(value);
+			break;
+		case PROP_NAME:
+			g_free(priv->name);
+			priv->name = g_value_dup_string(value);
+			break;
+		case PROP_SENDERS:
+			g_free(priv->senders);
+			priv->senders = g_value_dup_string(value);
+			break;
+		case PROP_TRANSPORT:
+			if (priv->transport)
+				g_object_unref(priv->transport);
+			priv->transport = g_value_get_object(value);
+			break;
+		case PROP_PENDING_TRANSPORT:
+			if (priv->pending_transport)
+				g_object_unref(priv->pending_transport);
+			priv->pending_transport = g_value_get_object(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_content_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	JingleContent *content = JINGLE_CONTENT(object);
+	JingleContentPrivate *priv = jingle_content_get_instance_private(content);
+
+	switch (prop_id) {
+		case PROP_SESSION:
+			g_value_set_object(value, priv->session);
+			break;
+		case PROP_CREATOR:
+			g_value_set_string(value, priv->creator);
+			break;
+		case PROP_DISPOSITION:
+			g_value_set_string(value, priv->disposition);
+			break;
+		case PROP_NAME:
+			g_value_set_string(value, priv->name);
+			break;
+		case PROP_SENDERS:
+			g_value_set_string(value, priv->senders);
+			break;
+		case PROP_TRANSPORT:
+			g_value_set_object(value, priv->transport);
+			break;
+		case PROP_PENDING_TRANSPORT:
+			g_value_set_object(value, priv->pending_transport);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_content_init (JingleContent *content)
+{
+}
+
+static void
+jingle_content_finalize (GObject *content)
+{
+	JingleContentPrivate *priv = jingle_content_get_instance_private(JINGLE_CONTENT(content));
+
+	purple_debug_info("jingle","jingle_content_finalize\n");
+
+	g_free(priv->description_type);
+	g_free(priv->creator);
+	g_free(priv->disposition);
+	g_free(priv->name);
+	g_free(priv->senders);
+	g_object_unref(priv->transport);
+	if (priv->pending_transport)
+		g_object_unref(priv->pending_transport);
+
+	G_OBJECT_CLASS(jingle_content_parent_class)->finalize(content);
+}
+
+
+static void
+jingle_content_class_finalize (JingleContentClass *klass)
+{
+}
 
 static void
 jingle_content_class_init (JingleContentClass *klass)
 {
-	GObjectClass *gobject_class = (GObjectClass*)klass;
-	parent_class = g_type_class_peek_parent(klass);
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
-	gobject_class->finalize = jingle_content_finalize;
-	gobject_class->set_property = jingle_content_set_property;
-	gobject_class->get_property = jingle_content_get_property;
+	obj_class->finalize = jingle_content_finalize;
+	obj_class->set_property = jingle_content_set_property;
+	obj_class->get_property = jingle_content_get_property;
+
 	klass->to_xml = jingle_content_to_xml_internal;
 	klass->parse = jingle_content_parse_internal;
 
-	g_type_class_add_private(klass, sizeof(JingleContentPrivate));
-
 	properties[PROP_SESSION] = g_param_spec_object("session",
 			"Jingle Session",
 			"The jingle session parent of this content.",
@@ -126,116 +296,16 @@
 			JINGLE_TYPE_TRANSPORT,
 			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
-	g_object_class_install_properties(gobject_class, PROP_LAST, properties);
-}
-
-static void
-jingle_content_init (JingleContent *content)
-{
-	content->priv = JINGLE_CONTENT_GET_PRIVATE(content);
-	memset(content->priv, 0, sizeof(*content->priv));
-}
-
-static void
-jingle_content_finalize (GObject *content)
-{
-	JingleContentPrivate *priv = JINGLE_CONTENT_GET_PRIVATE(content);
-	purple_debug_info("jingle","jingle_content_finalize\n");
-
-	g_free(priv->description_type);
-	g_free(priv->creator);
-	g_free(priv->disposition);
-	g_free(priv->name);
-	g_free(priv->senders);
-	g_object_unref(priv->transport);
-	if (priv->pending_transport)
-		g_object_unref(priv->pending_transport);
-
-	parent_class->finalize(content);
+	g_object_class_install_properties(obj_class, PROP_LAST, properties);
 }
 
-static void
-jingle_content_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+void
+jingle_content_register(PurplePlugin *plugin)
 {
-	JingleContent *content;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_CONTENT(object));
-
-	content = JINGLE_CONTENT(object);
-
-	switch (prop_id) {
-		case PROP_SESSION:
-			content->priv->session = g_value_get_object(value);
-			break;
-		case PROP_CREATOR:
-			g_free(content->priv->creator);
-			content->priv->creator = g_value_dup_string(value);
-			break;
-		case PROP_DISPOSITION:
-			g_free(content->priv->disposition);
-			content->priv->disposition = g_value_dup_string(value);
-			break;
-		case PROP_NAME:
-			g_free(content->priv->name);
-			content->priv->name = g_value_dup_string(value);
-			break;
-		case PROP_SENDERS:
-			g_free(content->priv->senders);
-			content->priv->senders = g_value_dup_string(value);
-			break;
-		case PROP_TRANSPORT:
-			if (content->priv->transport)
-				g_object_unref(content->priv->transport);
-			content->priv->transport = g_value_get_object(value);
-			break;
-		case PROP_PENDING_TRANSPORT:
-			if (content->priv->pending_transport)
-				g_object_unref(content->priv->pending_transport);
-			content->priv->pending_transport = g_value_get_object(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_content_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleContent *content;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_CONTENT(object));
-
-	content = JINGLE_CONTENT(object);
-
-	switch (prop_id) {
-		case PROP_SESSION:
-			g_value_set_object(value, content->priv->session);
-			break;
-		case PROP_CREATOR:
-			g_value_set_string(value, content->priv->creator);
-			break;
-		case PROP_DISPOSITION:
-			g_value_set_string(value, content->priv->disposition);
-			break;
-		case PROP_NAME:
-			g_value_set_string(value, content->priv->name);
-			break;
-		case PROP_SENDERS:
-			g_value_set_string(value, content->priv->senders);
-			break;
-		case PROP_TRANSPORT:
-			g_value_set_object(value, content->priv->transport);
-			break;
-		case PROP_PENDING_TRANSPORT:
-			g_value_set_object(value, content->priv->pending_transport);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
+	jingle_content_register_type(G_TYPE_MODULE(plugin));
 }
 
 JingleContent *
@@ -308,6 +378,14 @@
 	return transport;
 }
 
+JingleTransport *
+jingle_content_get_pending_transport(JingleContent *content)
+{
+	JingleTransport *pending_transport;
+	g_object_get(content, "pending-transport", &pending_transport, NULL);
+	return pending_transport;
+}
+
 void
 jingle_content_set_session(JingleContent *content, JingleSession *session)
 {
@@ -316,14 +394,6 @@
 	g_object_set(content, "session", session, NULL);
 }
 
-JingleTransport *
-jingle_content_get_pending_transport(JingleContent *content)
-{
-	JingleTransport *pending_transport;
-	g_object_get(content, "pending-transport", &pending_transport, NULL);
-	return pending_transport;
-}
-
 void
 jingle_content_set_pending_transport(JingleContent *content, JingleTransport *transport)
 {
@@ -333,13 +403,18 @@
 void
 jingle_content_accept_transport(JingleContent *content)
 {
+	JingleContentPrivate *priv = NULL;
 	GObject *obj;
 
-	if (content->priv->transport)
-		g_object_unref(content->priv->transport);
+	g_return_if_fail(JINGLE_IS_CONTENT(content));
+
+	priv = jingle_content_get_instance_private(content);
 
-	content->priv->transport = content->priv->pending_transport;
-	content->priv->pending_transport = NULL;
+	if (priv->transport)
+		g_object_unref(priv->transport);
+
+	priv->transport = priv->pending_transport;
+	priv->pending_transport = NULL;
 
 	obj = G_OBJECT(content);
 	g_object_freeze_notify(obj);
@@ -351,9 +426,15 @@
 void
 jingle_content_remove_pending_transport(JingleContent *content)
 {
-	if (content->priv->pending_transport) {
-		g_object_unref(content->priv->pending_transport);
-		content->priv->pending_transport = NULL;
+	JingleContentPrivate *priv = NULL;
+
+	g_return_if_fail(JINGLE_IS_CONTENT(content));
+
+	priv = jingle_content_get_instance_private(content);
+
+	if (priv->pending_transport) {
+		g_object_unref(priv->pending_transport);
+		priv->pending_transport = NULL;
 	}
 
 	g_object_notify_by_pspec(G_OBJECT(content), properties[PROP_PENDING_TRANSPORT]);
@@ -365,26 +446,6 @@
 	g_object_set(content, "senders", senders, NULL);
 }
 
-static JingleContent *
-jingle_content_parse_internal(PurpleXmlNode *content)
-{
-	PurpleXmlNode *description = purple_xmlnode_get_child(content, "description");
-	const gchar *type = purple_xmlnode_get_namespace(description);
-	const gchar *creator = purple_xmlnode_get_attrib(content, "creator");
-	const gchar *disposition = purple_xmlnode_get_attrib(content, "disposition");
-	const gchar *senders = purple_xmlnode_get_attrib(content, "senders");
-	const gchar *name = purple_xmlnode_get_attrib(content, "name");
-	JingleTransport *transport =
-			jingle_transport_parse(purple_xmlnode_get_child(content, "transport"));
-	if (transport == NULL)
-		return NULL;
-
-	if (senders == NULL)
-		senders = "both";
-
-	return jingle_content_create(type, creator, disposition, name, senders, transport);
-}
-
 JingleContent *
 jingle_content_parse(PurpleXmlNode *content)
 {
@@ -398,51 +459,6 @@
 	}
 }
 
-static PurpleXmlNode *
-jingle_content_to_xml_internal(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action)
-{
-	PurpleXmlNode *node = purple_xmlnode_new_child(jingle, "content");
-	gchar *creator = jingle_content_get_creator(content);
-	gchar *name = jingle_content_get_name(content);
-	gchar *senders = jingle_content_get_senders(content);
-	gchar *disposition = jingle_content_get_disposition(content);
-
-	purple_xmlnode_set_attrib(node, "creator", creator);
-	purple_xmlnode_set_attrib(node, "name", name);
-	purple_xmlnode_set_attrib(node, "senders", senders);
-	if (!purple_strequal("session", disposition))
-		purple_xmlnode_set_attrib(node, "disposition", disposition);
-
-	g_free(disposition);
-	g_free(senders);
-	g_free(name);
-	g_free(creator);
-
-	if (action != JINGLE_CONTENT_REMOVE) {
-		JingleTransport *transport;
-
-		if (action != JINGLE_TRANSPORT_ACCEPT &&
-				action != JINGLE_TRANSPORT_INFO &&
-				action != JINGLE_TRANSPORT_REJECT &&
-				action != JINGLE_TRANSPORT_REPLACE) {
-			PurpleXmlNode *description = purple_xmlnode_new_child(node, "description");
-
-			purple_xmlnode_set_namespace(description,
-					jingle_content_get_description_type(content));
-		}
-
-		if (action != JINGLE_TRANSPORT_REJECT && action == JINGLE_TRANSPORT_REPLACE)
-			transport = jingle_content_get_pending_transport(content);
-		else
-			transport = jingle_content_get_transport(content);
-
-		jingle_transport_to_xml(transport, node, action);
-		g_object_unref(transport);
-	}
-
-	return node;
-}
-
 PurpleXmlNode *
 jingle_content_to_xml(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action)
 {
--- a/libpurple/protocols/jabber/jingle/content.h	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/content.h	Fri Mar 22 02:42:46 2019 +0000
@@ -47,8 +47,6 @@
 typedef struct _JingleContent JingleContent;
 /** @copydoc _JingleContentClass */
 typedef struct _JingleContentClass JingleContentClass;
-/** @copydoc _JingleContentPrivate */
-typedef struct _JingleContentPrivate JingleContentPrivate;
 
 /** The content class */
 struct _JingleContentClass
@@ -65,7 +63,6 @@
 struct _JingleContent
 {
 	GObject parent;                /**< The parent of this object. */
-	JingleContentPrivate *priv;      /**< The private data of this object. */
 };
 
 /**
@@ -78,7 +75,7 @@
 /**
  * Registers the JingleContent type in the type system.
  */
-void jingle_content_register_type(PurplePlugin *plugin);
+void jingle_content_register(PurplePlugin *plugin);
 
 JingleContent *jingle_content_create(const gchar *type, const gchar *creator,
 		const gchar *disposition, const gchar *name,
--- a/libpurple/protocols/jabber/jingle/iceudp.c	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/iceudp.c	Fri Mar 22 02:42:46 2019 +0000
@@ -31,23 +31,11 @@
 
 #include <string.h>
 
-struct _JingleIceUdpPrivate
+typedef struct
 {
 	GList *local_candidates;
 	GList *remote_candidates;
-};
-
-#define JINGLE_ICEUDP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_ICEUDP, JingleIceUdpPrivate))
-
-static void jingle_iceudp_class_init (JingleIceUdpClass *klass);
-static void jingle_iceudp_init (JingleIceUdp *iceudp);
-static void jingle_iceudp_finalize (GObject *object);
-static void jingle_iceudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void jingle_iceudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static JingleTransport *jingle_iceudp_parse_internal(PurpleXmlNode *iceudp);
-static PurpleXmlNode *jingle_iceudp_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action);
-static void jingle_iceudp_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate);
-static GList *jingle_iceudp_get_remote_candidates(JingleTransport *transport);
+} JingleIceUdpPrivate;
 
 enum {
 	PROP_0,
@@ -56,177 +44,24 @@
 	PROP_LAST
 };
 
-static JingleTransportClass *parent_class = NULL;
 static GParamSpec *properties[PROP_LAST];
 
-static JingleIceUdpCandidate *
-jingle_iceudp_candidate_copy(JingleIceUdpCandidate *candidate)
-{
-	JingleIceUdpCandidate *new_candidate = g_new0(JingleIceUdpCandidate, 1);
-	new_candidate->id = g_strdup(candidate->id);
-	new_candidate->component = candidate->component;
-	new_candidate->foundation = g_strdup(candidate->foundation);
-	new_candidate->generation = candidate->generation;
-	new_candidate->ip = g_strdup(candidate->ip);
-	new_candidate->network = candidate->network;
-	new_candidate->port = candidate->port;
-	new_candidate->priority = candidate->priority;
-	new_candidate->protocol = g_strdup(candidate->protocol);
-	new_candidate->type = g_strdup(candidate->type);
-
-	new_candidate->username = g_strdup(candidate->username);
-	new_candidate->password = g_strdup(candidate->password);
-
-	new_candidate->rem_known = candidate->rem_known;
-
-	return new_candidate;
-}
-
-static void
-jingle_iceudp_candidate_free(JingleIceUdpCandidate *candidate)
-{
-	g_free(candidate->foundation);
-	g_free(candidate->id);
-	g_free(candidate->ip);
-	g_free(candidate->protocol);
-	g_free(candidate->reladdr);
-	g_free(candidate->type);
-
-	g_free(candidate->username);
-	g_free(candidate->password);
-}
-
-G_DEFINE_BOXED_TYPE(JingleIceUdpCandidate, jingle_iceudp_candidate,
-		jingle_iceudp_candidate_copy, jingle_iceudp_candidate_free)
-
-JingleIceUdpCandidate *
-jingle_iceudp_candidate_new(const gchar *id,
-		guint component, const gchar *foundation,
-		guint generation, const gchar *ip,
-		guint network, guint port, guint priority,
-		const gchar *protocol, const gchar *type,
-		const gchar *username, const gchar *password)
-{
-	JingleIceUdpCandidate *candidate = g_new0(JingleIceUdpCandidate, 1);
-	candidate->id = g_strdup(id);
-	candidate->component = component;
-	candidate->foundation = g_strdup(foundation);
-	candidate->generation = generation;
-	candidate->ip = g_strdup(ip);
-	candidate->network = network;
-	candidate->port = port;
-	candidate->priority = priority;
-	candidate->protocol = g_strdup(protocol);
-	candidate->type = g_strdup(type);
-
-	candidate->username = g_strdup(username);
-	candidate->password = g_strdup(password);
-
-	candidate->rem_known = FALSE;
-	return candidate;
-}
-
-PURPLE_DEFINE_TYPE(JingleIceUdp, jingle_iceudp, JINGLE_TYPE_TRANSPORT);
-
-static void
-jingle_iceudp_class_init (JingleIceUdpClass *klass)
-{
-	GObjectClass *gobject_class = (GObjectClass*)klass;
-	parent_class = g_type_class_peek_parent(klass);
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(
+	JingleIceUdp,
+	jingle_iceudp,
+	JINGLE_TYPE_TRANSPORT,
+	0,
+	G_ADD_PRIVATE_DYNAMIC(JingleIceUdp)
+);
 
-	gobject_class->finalize = jingle_iceudp_finalize;
-	gobject_class->set_property = jingle_iceudp_set_property;
-	gobject_class->get_property = jingle_iceudp_get_property;
-	klass->parent_class.to_xml = jingle_iceudp_to_xml_internal;
-	klass->parent_class.parse = jingle_iceudp_parse_internal;
-	klass->parent_class.transport_type = JINGLE_TRANSPORT_ICEUDP;
-	klass->parent_class.add_local_candidate = jingle_iceudp_add_local_candidate;
-	klass->parent_class.get_remote_candidates = jingle_iceudp_get_remote_candidates;
-
-	g_type_class_add_private(klass, sizeof(JingleIceUdpPrivate));
-
-	properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
-			"Local candidates",
-			"The local candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
-			"Remote candidates",
-			"The remote candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(gobject_class, PROP_LAST, properties);
-}
-
-static void
-jingle_iceudp_init (JingleIceUdp *iceudp)
-{
-	iceudp->priv = JINGLE_ICEUDP_GET_PRIVATE(iceudp);
-	iceudp->priv->local_candidates = NULL;
-	iceudp->priv->remote_candidates = NULL;
-}
-
-static void
-jingle_iceudp_finalize (GObject *iceudp)
-{
-/*	JingleIceUdpPrivate *priv = JINGLE_ICEUDP_GET_PRIVATE(iceudp); */
-	purple_debug_info("jingle","jingle_iceudp_finalize\n");
-
-	G_OBJECT_CLASS(parent_class)->finalize(iceudp);
-}
-
-static void
-jingle_iceudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleIceUdp *iceudp;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_ICEUDP(object));
-
-	iceudp = JINGLE_ICEUDP(object);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			iceudp->priv->local_candidates =
-					g_value_get_pointer(value);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			iceudp->priv->remote_candidates =
-					g_value_get_pointer(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_iceudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleIceUdp *iceudp;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_ICEUDP(object));
-
-	iceudp = JINGLE_ICEUDP(object);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			g_value_set_pointer(value, iceudp->priv->local_candidates);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			g_value_set_pointer(value, iceudp->priv->remote_candidates);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
+/******************************************************************************
+ * JingleIceUdp Transport Implementation
+ *****************************************************************************/
 static void
 jingle_iceudp_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate)
 {
 	JingleIceUdp *iceudp = JINGLE_ICEUDP(transport);
+	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
 	PurpleMediaCandidateType type;
 	gchar *ip;
 	gchar *username;
@@ -257,19 +92,19 @@
 	g_free(username);
 	g_free(ip);
 
-	for (iter = iceudp->priv->local_candidates; iter; iter = g_list_next(iter)) {
+	for (iter = priv->local_candidates; iter; iter = g_list_next(iter)) {
 		JingleIceUdpCandidate *c = iter->data;
 		if (purple_strequal(c->id, id)) {
 			generation = c->generation + 1;
 
 			g_boxed_free(JINGLE_TYPE_ICEUDP_CANDIDATE, c);
-			iceudp->priv->local_candidates = g_list_delete_link(
-					iceudp->priv->local_candidates, iter);
+			priv->local_candidates = g_list_delete_link(
+					priv->local_candidates, iter);
 
 			iceudp_candidate->generation = generation;
 
-			iceudp->priv->local_candidates = g_list_append(
-					iceudp->priv->local_candidates, iceudp_candidate);
+			priv->local_candidates = g_list_append(
+					priv->local_candidates, iceudp_candidate);
 
 			g_object_notify_by_pspec(G_OBJECT(iceudp), properties[PROP_LOCAL_CANDIDATES]);
 
@@ -277,8 +112,8 @@
 		}
 	}
 
-	iceudp->priv->local_candidates = g_list_append(
-			iceudp->priv->local_candidates, iceudp_candidate);
+	priv->local_candidates = g_list_append(
+			priv->local_candidates, iceudp_candidate);
 
 	g_object_notify_by_pspec(G_OBJECT(iceudp), properties[PROP_LOCAL_CANDIDATES]);
 }
@@ -287,7 +122,8 @@
 jingle_iceudp_get_remote_candidates(JingleTransport *transport)
 {
 	JingleIceUdp *iceudp = JINGLE_ICEUDP(transport);
-	GList *candidates = iceudp->priv->remote_candidates;
+	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
+	GList *candidates = priv->remote_candidates;
 	GList *ret = NULL;
 
 	for (; candidates; candidates = g_list_next(candidates)) {
@@ -321,7 +157,8 @@
 jingle_iceudp_get_remote_candidate_by_id(JingleIceUdp *iceudp,
 		const gchar *id)
 {
-	GList *iter = iceudp->priv->remote_candidates;
+	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
+	GList *iter = priv->remote_candidates;
 	for (; iter; iter = g_list_next(iter)) {
 		JingleIceUdpCandidate *candidate = iter->data;
 		if (purple_strequal(candidate->id, id)) {
@@ -334,7 +171,7 @@
 static void
 jingle_iceudp_add_remote_candidate(JingleIceUdp *iceudp, JingleIceUdpCandidate *candidate)
 {
-	JingleIceUdpPrivate *priv = JINGLE_ICEUDP_GET_PRIVATE(iceudp);
+	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
 	JingleIceUdpCandidate *iceudp_candidate =
 			jingle_iceudp_get_remote_candidate_by_id(iceudp,
 					candidate->id);
@@ -351,7 +188,7 @@
 static JingleTransport *
 jingle_iceudp_parse_internal(PurpleXmlNode *iceudp)
 {
-	JingleTransport *transport = parent_class->parse(iceudp);
+	JingleTransport *transport = JINGLE_TRANSPORT_CLASS(jingle_iceudp_parent_class)->parse(iceudp);
 	PurpleXmlNode *candidate = purple_xmlnode_get_child(iceudp, "candidate");
 	JingleIceUdpCandidate *iceudp_candidate = NULL;
 
@@ -401,14 +238,14 @@
 static PurpleXmlNode *
 jingle_iceudp_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
 {
-	PurpleXmlNode *node = parent_class->to_xml(transport, content, action);
+	PurpleXmlNode *node = JINGLE_TRANSPORT_CLASS(jingle_iceudp_parent_class)->to_xml(transport, content, action);
 
 	if (action == JINGLE_SESSION_INITIATE ||
 			action == JINGLE_SESSION_ACCEPT ||
 			action == JINGLE_TRANSPORT_INFO ||
 			action == JINGLE_CONTENT_ADD ||
 			action == JINGLE_TRANSPORT_REPLACE) {
-		JingleIceUdpPrivate *priv = JINGLE_ICEUDP_GET_PRIVATE(transport);
+		JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(JINGLE_ICEUDP(transport));
 		GList *iter = priv->local_candidates;
 		gboolean used_candidate = FALSE;
 
@@ -474,3 +311,171 @@
 	return node;
 }
 
+/******************************************************************************
+ * JingleIceUdp GObject Implementation
+ *****************************************************************************/
+static void
+jingle_iceudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	JingleIceUdp *iceudp = JINGLE_ICEUDP(object);
+	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
+
+	switch (prop_id) {
+		case PROP_LOCAL_CANDIDATES:
+			priv->local_candidates =
+					g_value_get_pointer(value);
+			break;
+		case PROP_REMOTE_CANDIDATES:
+			priv->remote_candidates =
+					g_value_get_pointer(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_iceudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	JingleIceUdp *iceudp = JINGLE_ICEUDP(object);
+	JingleIceUdpPrivate *priv = jingle_iceudp_get_instance_private(iceudp);
+
+	switch (prop_id) {
+		case PROP_LOCAL_CANDIDATES:
+			g_value_set_pointer(value, priv->local_candidates);
+			break;
+		case PROP_REMOTE_CANDIDATES:
+			g_value_set_pointer(value, priv->remote_candidates);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_iceudp_init (JingleIceUdp *iceudp)
+{
+}
+
+static void
+jingle_iceudp_finalize (GObject *iceudp)
+{
+/*	JingleIceUdpPrivate *priv = JINGLE_ICEUDP_GET_PRIVATE(iceudp); */
+	purple_debug_info("jingle","jingle_iceudp_finalize\n");
+
+	G_OBJECT_CLASS(jingle_iceudp_parent_class)->finalize(iceudp);
+}
+
+static void
+jingle_iceudp_class_finalize (JingleIceUdpClass *klass)
+{
+}
+
+static void
+jingle_iceudp_class_init (JingleIceUdpClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	JingleTransportClass *transport_class = JINGLE_TRANSPORT_CLASS(klass);
+
+	obj_class->finalize = jingle_iceudp_finalize;
+	obj_class->set_property = jingle_iceudp_set_property;
+	obj_class->get_property = jingle_iceudp_get_property;
+
+	transport_class->to_xml = jingle_iceudp_to_xml_internal;
+	transport_class->parse = jingle_iceudp_parse_internal;
+	transport_class->transport_type = JINGLE_TRANSPORT_ICEUDP;
+	transport_class->add_local_candidate = jingle_iceudp_add_local_candidate;
+	transport_class->get_remote_candidates = jingle_iceudp_get_remote_candidates;
+
+	properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
+			"Local candidates",
+			"The local candidates for this transport.",
+			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
+			"Remote candidates",
+			"The remote candidates for this transport.",
+			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(obj_class, PROP_LAST, properties);
+}
+
+/******************************************************************************
+ * JingleIceUdpCandidate Boxed Implementation
+ *****************************************************************************/
+static JingleIceUdpCandidate *
+jingle_iceudp_candidate_copy(JingleIceUdpCandidate *candidate)
+{
+	JingleIceUdpCandidate *new_candidate = g_new0(JingleIceUdpCandidate, 1);
+	new_candidate->id = g_strdup(candidate->id);
+	new_candidate->component = candidate->component;
+	new_candidate->foundation = g_strdup(candidate->foundation);
+	new_candidate->generation = candidate->generation;
+	new_candidate->ip = g_strdup(candidate->ip);
+	new_candidate->network = candidate->network;
+	new_candidate->port = candidate->port;
+	new_candidate->priority = candidate->priority;
+	new_candidate->protocol = g_strdup(candidate->protocol);
+	new_candidate->type = g_strdup(candidate->type);
+
+	new_candidate->username = g_strdup(candidate->username);
+	new_candidate->password = g_strdup(candidate->password);
+
+	new_candidate->rem_known = candidate->rem_known;
+
+	return new_candidate;
+}
+
+static void
+jingle_iceudp_candidate_free(JingleIceUdpCandidate *candidate)
+{
+	g_free(candidate->foundation);
+	g_free(candidate->id);
+	g_free(candidate->ip);
+	g_free(candidate->protocol);
+	g_free(candidate->reladdr);
+	g_free(candidate->type);
+
+	g_free(candidate->username);
+	g_free(candidate->password);
+}
+
+G_DEFINE_BOXED_TYPE(JingleIceUdpCandidate, jingle_iceudp_candidate,
+		jingle_iceudp_candidate_copy, jingle_iceudp_candidate_free)
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+void
+jingle_iceudp_register(PurplePlugin *plugin) {
+	jingle_iceudp_register_type(G_TYPE_MODULE(plugin));
+}
+
+JingleIceUdpCandidate *
+jingle_iceudp_candidate_new(const gchar *id,
+		guint component, const gchar *foundation,
+		guint generation, const gchar *ip,
+		guint network, guint port, guint priority,
+		const gchar *protocol, const gchar *type,
+		const gchar *username, const gchar *password)
+{
+	JingleIceUdpCandidate *candidate = g_new0(JingleIceUdpCandidate, 1);
+	candidate->id = g_strdup(id);
+	candidate->component = component;
+	candidate->foundation = g_strdup(foundation);
+	candidate->generation = generation;
+	candidate->ip = g_strdup(ip);
+	candidate->network = network;
+	candidate->port = port;
+	candidate->priority = priority;
+	candidate->protocol = g_strdup(protocol);
+	candidate->type = g_strdup(type);
+
+	candidate->username = g_strdup(username);
+	candidate->password = g_strdup(password);
+
+	candidate->rem_known = FALSE;
+	return candidate;
+}
--- a/libpurple/protocols/jabber/jingle/iceudp.h	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/iceudp.h	Fri Mar 22 02:42:46 2019 +0000
@@ -33,7 +33,6 @@
 G_BEGIN_DECLS
 
 #define JINGLE_TYPE_ICEUDP            (jingle_iceudp_get_type())
-#define JINGLE_TYPE_ICEUDP_CANDIDATE  (jingle_iceudp_candidate_get_type())
 #define JINGLE_ICEUDP(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), JINGLE_TYPE_ICEUDP, JingleIceUdp))
 #define JINGLE_ICEUDP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), JINGLE_TYPE_ICEUDP, JingleIceUdpClass))
 #define JINGLE_IS_ICEUDP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), JINGLE_TYPE_ICEUDP))
@@ -44,8 +43,9 @@
 typedef struct _JingleIceUdp JingleIceUdp;
 /** @copydoc _JingleIceUdpClass */
 typedef struct _JingleIceUdpClass JingleIceUdpClass;
-/** @copydoc _JingleIceUdpPrivate */
-typedef struct _JingleIceUdpPrivate JingleIceUdpPrivate;
+
+#define JINGLE_TYPE_ICEUDP_CANDIDATE  (jingle_iceudp_candidate_get_type())
+
 /** @copydoc _JingleIceUdpCandidate */
 typedef struct _JingleIceUdpCandidate JingleIceUdpCandidate;
 
@@ -62,7 +62,6 @@
 struct _JingleIceUdp
 {
 	JingleTransport parent;                /**< The parent of this object. */
-	JingleIceUdpPrivate *priv;      /**< The private data of this object. */
 };
 
 struct _JingleIceUdpCandidate
@@ -99,7 +98,7 @@
 /**
  * Registers the JingleIceUdp type in the type system.
  */
-void jingle_iceudp_register_type(PurplePlugin *plugin);
+void jingle_iceudp_register(PurplePlugin *plugin);
 
 JingleIceUdpCandidate *jingle_iceudp_candidate_new(const gchar *id,
 		guint component, const gchar *foundation, guint generation,
--- a/libpurple/protocols/jabber/jingle/rawudp.c	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/rawudp.c	Fri Mar 22 02:42:46 2019 +0000
@@ -31,23 +31,11 @@
 
 #include <string.h>
 
-struct _JingleRawUdpPrivate
+typedef struct
 {
 	GList *local_candidates;
 	GList *remote_candidates;
-};
-
-#define JINGLE_RAWUDP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_RAWUDP, JingleRawUdpPrivate))
-
-static void jingle_rawudp_class_init (JingleRawUdpClass *klass);
-static void jingle_rawudp_init (JingleRawUdp *rawudp);
-static void jingle_rawudp_finalize (GObject *object);
-static void jingle_rawudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void jingle_rawudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static JingleTransport *jingle_rawudp_parse_internal(PurpleXmlNode *rawudp);
-static PurpleXmlNode *jingle_rawudp_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action);
-static void jingle_rawudp_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate);
-static GList *jingle_rawudp_get_remote_candidates(JingleTransport *transport);
+} JingleRawUdpPrivate;
 
 enum {
 	PROP_0,
@@ -55,190 +43,25 @@
 	PROP_REMOTE_CANDIDATES,
 	PROP_LAST
 };
-
-static JingleTransportClass *parent_class = NULL;
 static GParamSpec *properties[PROP_LAST];
 
-static JingleRawUdpCandidate *
-jingle_rawudp_candidate_copy(JingleRawUdpCandidate *candidate)
-{
-	JingleRawUdpCandidate *new_candidate = g_new0(JingleRawUdpCandidate, 1);
-	new_candidate->generation = candidate->generation;
-	new_candidate->component = candidate->component;
-	new_candidate->id = g_strdup(candidate->id);
-	new_candidate->ip = g_strdup(candidate->ip);
-	new_candidate->port = candidate->port;
-
-	new_candidate->rem_known = candidate->rem_known;
-	return new_candidate;
-}
-
-static void
-jingle_rawudp_candidate_free(JingleRawUdpCandidate *candidate)
-{
-	g_free(candidate->id);
-	g_free(candidate->ip);
-}
-
-G_DEFINE_BOXED_TYPE(JingleRawUdpCandidate, jingle_rawudp_candidate,
-		jingle_rawudp_candidate_copy, jingle_rawudp_candidate_free)
-
-JingleRawUdpCandidate *
-jingle_rawudp_candidate_new(const gchar *id, guint generation, guint component, const gchar *ip, guint port)
-{
-	JingleRawUdpCandidate *candidate = g_new0(JingleRawUdpCandidate, 1);
-	candidate->generation = generation;
-	candidate->component = component;
-	candidate->id = g_strdup(id);
-	candidate->ip = g_strdup(ip);
-	candidate->port = port;
-
-	candidate->rem_known = FALSE;
-	return candidate;
-}
-
-PURPLE_DEFINE_TYPE(JingleRawUdp, jingle_rawudp, JINGLE_TYPE_TRANSPORT);
-
-static void
-jingle_rawudp_class_init (JingleRawUdpClass *klass)
-{
-	GObjectClass *gobject_class = (GObjectClass*)klass;
-	parent_class = g_type_class_peek_parent(klass);
-
-	gobject_class->finalize = jingle_rawudp_finalize;
-	gobject_class->set_property = jingle_rawudp_set_property;
-	gobject_class->get_property = jingle_rawudp_get_property;
-	klass->parent_class.to_xml = jingle_rawudp_to_xml_internal;
-	klass->parent_class.parse = jingle_rawudp_parse_internal;
-	klass->parent_class.transport_type = JINGLE_TRANSPORT_RAWUDP;
-	klass->parent_class.add_local_candidate = jingle_rawudp_add_local_candidate;
-	klass->parent_class.get_remote_candidates = jingle_rawudp_get_remote_candidates;
-
-	g_type_class_add_private(klass, sizeof(JingleRawUdpPrivate));
-
-	properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
-			"Local candidates",
-			"The local candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
-			"Remote candidates",
-			"The remote candidates for this transport.",
-			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(gobject_class, PROP_LAST, properties);
-}
-
-static void
-jingle_rawudp_init (JingleRawUdp *rawudp)
-{
-	rawudp->priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp);
-	rawudp->priv->local_candidates = NULL;
-	rawudp->priv->remote_candidates = NULL;
-}
-
-static void
-jingle_rawudp_finalize (GObject *rawudp)
-{
-/*	JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp); */
-	purple_debug_info("jingle","jingle_rawudp_finalize\n");
-
-	G_OBJECT_CLASS(parent_class)->finalize(rawudp);
-}
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(
+	JingleRawUdp,
+	jingle_rawudp,
+	JINGLE_TYPE_TRANSPORT,
+	0,
+	G_ADD_PRIVATE_DYNAMIC(JingleRawUdp)
+);
 
-static void
-jingle_rawudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleRawUdp *rawudp;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_RAWUDP(object));
-
-	rawudp = JINGLE_RAWUDP(object);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			rawudp->priv->local_candidates =
-					g_value_get_pointer(value);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			rawudp->priv->remote_candidates =
-					g_value_get_pointer(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_rawudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleRawUdp *rawudp;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_RAWUDP(object));
-
-	rawudp = JINGLE_RAWUDP(object);
-
-	switch (prop_id) {
-		case PROP_LOCAL_CANDIDATES:
-			g_value_set_pointer(value, rawudp->priv->local_candidates);
-			break;
-		case PROP_REMOTE_CANDIDATES:
-			g_value_set_pointer(value, rawudp->priv->remote_candidates);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_rawudp_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate)
-{
-	JingleRawUdp *rawudp = JINGLE_RAWUDP(transport);
-	gchar *ip;
-	JingleRawUdpCandidate *rawudp_candidate;
-	GList *iter;
-
-	ip = purple_media_candidate_get_ip(candidate);
-	rawudp_candidate = jingle_rawudp_candidate_new(id, generation,
-			purple_media_candidate_get_component_id(candidate),
-			ip, purple_media_candidate_get_port(candidate));
-	g_free(ip);
-
-	for (iter = rawudp->priv->local_candidates; iter; iter = g_list_next(iter)) {
-		JingleRawUdpCandidate *c = iter->data;
-		if (purple_strequal(c->id, id)) {
-			generation = c->generation + 1;
-
-			g_boxed_free(JINGLE_TYPE_RAWUDP_CANDIDATE, c);
-			rawudp->priv->local_candidates = g_list_delete_link(
-					rawudp->priv->local_candidates, iter);
-
-			rawudp_candidate->generation = generation;
-
-			rawudp->priv->local_candidates = g_list_append(
-					rawudp->priv->local_candidates, rawudp_candidate);
-
-			g_object_notify_by_pspec(G_OBJECT(rawudp), properties[PROP_LOCAL_CANDIDATES]);
-
-			return;
-		}
-	}
-
-	rawudp->priv->local_candidates = g_list_append(
-			rawudp->priv->local_candidates, rawudp_candidate);
-
-	g_object_notify_by_pspec(G_OBJECT(rawudp), properties[PROP_LOCAL_CANDIDATES]);
-}
-
+/******************************************************************************
+ * JingleRawUdp Transport Implementation
+ *****************************************************************************/
 static GList *
 jingle_rawudp_get_remote_candidates(JingleTransport *transport)
 {
 	JingleRawUdp *rawudp = JINGLE_RAWUDP(transport);
-	GList *candidates = rawudp->priv->remote_candidates;
+	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
+	GList *candidates = priv->remote_candidates;
 	GList *ret = NULL;
 
 	for (; candidates; candidates = g_list_next(candidates)) {
@@ -256,7 +79,9 @@
 static JingleRawUdpCandidate *
 jingle_rawudp_get_remote_candidate_by_id(JingleRawUdp *rawudp, gchar *id)
 {
-	GList *iter = rawudp->priv->remote_candidates;
+	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
+
+	GList *iter = priv->remote_candidates;
 	for (; iter; iter = g_list_next(iter)) {
 		JingleRawUdpCandidate *candidate = iter->data;
 		if (purple_strequal(candidate->id, id)) {
@@ -269,7 +94,7 @@
 static void
 jingle_rawudp_add_remote_candidate(JingleRawUdp *rawudp, JingleRawUdpCandidate *candidate)
 {
-	JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp);
+	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
 	JingleRawUdpCandidate *rawudp_candidate =
 			jingle_rawudp_get_remote_candidate_by_id(rawudp, candidate->id);
 	if (rawudp_candidate != NULL) {
@@ -282,11 +107,50 @@
 	g_object_notify_by_pspec(G_OBJECT(rawudp), properties[PROP_REMOTE_CANDIDATES]);
 }
 
+static PurpleXmlNode *
+jingle_rawudp_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
+{
+	PurpleXmlNode *node = JINGLE_TRANSPORT_CLASS(jingle_rawudp_parent_class)->to_xml(transport, content, action);
+
+	if (action == JINGLE_SESSION_INITIATE ||
+			action == JINGLE_TRANSPORT_INFO ||
+			action == JINGLE_SESSION_ACCEPT) {
+		JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(JINGLE_RAWUDP(transport));
+		GList *iter = priv->local_candidates;
+
+		for (; iter; iter = g_list_next(iter)) {
+			JingleRawUdpCandidate *candidate = iter->data;
+			PurpleXmlNode *xmltransport;
+			gchar *generation, *component, *port;
+
+			if (candidate->rem_known == TRUE)
+				continue;
+			candidate->rem_known = TRUE;
+
+			xmltransport = purple_xmlnode_new_child(node, "candidate");
+			generation = g_strdup_printf("%d", candidate->generation);
+			component = g_strdup_printf("%d", candidate->component);
+			port = g_strdup_printf("%d", candidate->port);
+
+			purple_xmlnode_set_attrib(xmltransport, "generation", generation);
+			purple_xmlnode_set_attrib(xmltransport, "component", component);
+			purple_xmlnode_set_attrib(xmltransport, "id", candidate->id);
+			purple_xmlnode_set_attrib(xmltransport, "ip", candidate->ip);
+			purple_xmlnode_set_attrib(xmltransport, "port", port);
+
+			g_free(port);
+			g_free(generation);
+		}
+	}
+
+	return node;
+}
+
 static JingleTransport *
 jingle_rawudp_parse_internal(PurpleXmlNode *rawudp)
 {
-	JingleTransport *transport = parent_class->parse(rawudp);
-	JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(transport);
+	JingleTransport *transport = JINGLE_TRANSPORT_CLASS(jingle_rawudp_parent_class)->parse(rawudp);
+	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(JINGLE_RAWUDP(transport));
 	PurpleXmlNode *candidate = purple_xmlnode_get_child(rawudp, "candidate");
 	JingleRawUdpCandidate *rawudp_candidate = NULL;
 
@@ -323,42 +187,180 @@
 	return transport;
 }
 
-static PurpleXmlNode *
-jingle_rawudp_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
+static void
+jingle_rawudp_add_local_candidate(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate)
 {
-	PurpleXmlNode *node = parent_class->to_xml(transport, content, action);
+	JingleRawUdp *rawudp = JINGLE_RAWUDP(transport);
+	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
+	gchar *ip;
+	JingleRawUdpCandidate *rawudp_candidate;
+	GList *iter;
 
-	if (action == JINGLE_SESSION_INITIATE ||
-			action == JINGLE_TRANSPORT_INFO ||
-			action == JINGLE_SESSION_ACCEPT) {
-		JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(transport);
-		GList *iter = priv->local_candidates;
-
-		for (; iter; iter = g_list_next(iter)) {
-			JingleRawUdpCandidate *candidate = iter->data;
-			PurpleXmlNode *xmltransport;
-			gchar *generation, *component, *port;
+	ip = purple_media_candidate_get_ip(candidate);
+	rawudp_candidate = jingle_rawudp_candidate_new(id, generation,
+			purple_media_candidate_get_component_id(candidate),
+			ip, purple_media_candidate_get_port(candidate));
+	g_free(ip);
 
-			if (candidate->rem_known == TRUE)
-				continue;
-			candidate->rem_known = TRUE;
+	for (iter = priv->local_candidates; iter; iter = g_list_next(iter)) {
+		JingleRawUdpCandidate *c = iter->data;
+		if (purple_strequal(c->id, id)) {
+			generation = c->generation + 1;
 
-			xmltransport = purple_xmlnode_new_child(node, "candidate");
-			generation = g_strdup_printf("%d", candidate->generation);
-			component = g_strdup_printf("%d", candidate->component);
-			port = g_strdup_printf("%d", candidate->port);
+			g_boxed_free(JINGLE_TYPE_RAWUDP_CANDIDATE, c);
+			priv->local_candidates = g_list_delete_link(
+					priv->local_candidates, iter);
 
-			purple_xmlnode_set_attrib(xmltransport, "generation", generation);
-			purple_xmlnode_set_attrib(xmltransport, "component", component);
-			purple_xmlnode_set_attrib(xmltransport, "id", candidate->id);
-			purple_xmlnode_set_attrib(xmltransport, "ip", candidate->ip);
-			purple_xmlnode_set_attrib(xmltransport, "port", port);
+			rawudp_candidate->generation = generation;
 
-			g_free(port);
-			g_free(generation);
+			priv->local_candidates = g_list_append(
+					priv->local_candidates, rawudp_candidate);
+
+			g_object_notify_by_pspec(G_OBJECT(rawudp), properties[PROP_LOCAL_CANDIDATES]);
+
+			return;
 		}
 	}
 
-	return node;
+	priv->local_candidates = g_list_append(
+			priv->local_candidates, rawudp_candidate);
+
+	g_object_notify_by_pspec(G_OBJECT(rawudp), properties[PROP_LOCAL_CANDIDATES]);
+}
+
+/******************************************************************************
+ * JingleRawUdp GObject Stuff
+ *****************************************************************************/
+static void
+jingle_rawudp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	JingleRawUdp *rawudp = JINGLE_RAWUDP(object);
+	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
+
+	switch (prop_id) {
+		case PROP_LOCAL_CANDIDATES:
+			priv->local_candidates = g_value_get_pointer(value);
+			break;
+		case PROP_REMOTE_CANDIDATES:
+			priv->remote_candidates = g_value_get_pointer(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_rawudp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	JingleRawUdp *rawudp = JINGLE_RAWUDP(object);
+	JingleRawUdpPrivate *priv = jingle_rawudp_get_instance_private(rawudp);
+
+	switch (prop_id) {
+		case PROP_LOCAL_CANDIDATES:
+			g_value_set_pointer(value, priv->local_candidates);
+			break;
+		case PROP_REMOTE_CANDIDATES:
+			g_value_set_pointer(value, priv->remote_candidates);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_rawudp_init (JingleRawUdp *rawudp)
+{
+}
+
+static void
+jingle_rawudp_finalize (GObject *rawudp)
+{
+/*	JingleRawUdpPrivate *priv = JINGLE_RAWUDP_GET_PRIVATE(rawudp); */
+	purple_debug_info("jingle","jingle_rawudp_finalize\n");
+
+	G_OBJECT_CLASS(jingle_rawudp_parent_class)->finalize(rawudp);
+}
+
+static void
+jingle_rawudp_class_finalize(JingleRawUdpClass *klass) {
 }
 
+static void
+jingle_rawudp_class_init (JingleRawUdpClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	JingleTransportClass *transport_class = JINGLE_TRANSPORT_CLASS(klass);
+
+	obj_class->finalize = jingle_rawudp_finalize;
+	obj_class->set_property = jingle_rawudp_set_property;
+	obj_class->get_property = jingle_rawudp_get_property;
+
+	transport_class->to_xml = jingle_rawudp_to_xml_internal;
+	transport_class->parse = jingle_rawudp_parse_internal;
+	transport_class->transport_type = JINGLE_TRANSPORT_RAWUDP;
+	transport_class->add_local_candidate = jingle_rawudp_add_local_candidate;
+	transport_class->get_remote_candidates = jingle_rawudp_get_remote_candidates;
+
+	properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
+			"Local candidates",
+			"The local candidates for this transport.",
+			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
+			"Remote candidates",
+			"The remote candidates for this transport.",
+			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(obj_class, PROP_LAST, properties);
+}
+
+/******************************************************************************
+ * JingleRawUdpCandidate Boxed Type
+ *****************************************************************************/
+static JingleRawUdpCandidate *
+jingle_rawudp_candidate_copy(JingleRawUdpCandidate *candidate)
+{
+	JingleRawUdpCandidate *new_candidate = g_new0(JingleRawUdpCandidate, 1);
+	new_candidate->generation = candidate->generation;
+	new_candidate->component = candidate->component;
+	new_candidate->id = g_strdup(candidate->id);
+	new_candidate->ip = g_strdup(candidate->ip);
+	new_candidate->port = candidate->port;
+
+	new_candidate->rem_known = candidate->rem_known;
+	return new_candidate;
+}
+
+static void
+jingle_rawudp_candidate_free(JingleRawUdpCandidate *candidate)
+{
+	g_free(candidate->id);
+	g_free(candidate->ip);
+}
+
+G_DEFINE_BOXED_TYPE(JingleRawUdpCandidate, jingle_rawudp_candidate,
+		jingle_rawudp_candidate_copy, jingle_rawudp_candidate_free)
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+void
+jingle_rawudp_register(PurplePlugin *plugin) {
+	jingle_rawudp_register_type(G_TYPE_MODULE(plugin));
+}
+
+JingleRawUdpCandidate *
+jingle_rawudp_candidate_new(const gchar *id, guint generation, guint component, const gchar *ip, guint port)
+{
+	JingleRawUdpCandidate *candidate = g_new0(JingleRawUdpCandidate, 1);
+	candidate->generation = generation;
+	candidate->component = component;
+	candidate->id = g_strdup(id);
+	candidate->ip = g_strdup(ip);
+	candidate->port = port;
+
+	candidate->rem_known = FALSE;
+	return candidate;
+}
--- a/libpurple/protocols/jabber/jingle/rawudp.h	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/rawudp.h	Fri Mar 22 02:42:46 2019 +0000
@@ -33,7 +33,6 @@
 G_BEGIN_DECLS
 
 #define JINGLE_TYPE_RAWUDP            (jingle_rawudp_get_type())
-#define JINGLE_TYPE_RAWUDP_CANDIDATE  (jingle_rawudp_candidate_get_type())
 #define JINGLE_RAWUDP(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), JINGLE_TYPE_RAWUDP, JingleRawUdp))
 #define JINGLE_RAWUDP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), JINGLE_TYPE_RAWUDP, JingleRawUdpClass))
 #define JINGLE_IS_RAWUDP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), JINGLE_TYPE_RAWUDP))
@@ -44,8 +43,9 @@
 typedef struct _JingleRawUdp JingleRawUdp;
 /** @copydoc _JingleRawUdpClass */
 typedef struct _JingleRawUdpClass JingleRawUdpClass;
-/** @copydoc _JingleRawUdpPrivate */
-typedef struct _JingleRawUdpPrivate JingleRawUdpPrivate;
+
+#define JINGLE_TYPE_RAWUDP_CANDIDATE  (jingle_rawudp_candidate_get_type())
+
 /** @copydoc _JingleRawUdpCandidate */
 typedef struct _JingleRawUdpCandidate JingleRawUdpCandidate;
 
@@ -62,7 +62,6 @@
 struct _JingleRawUdp
 {
 	JingleTransport parent;                /**< The parent of this object. */
-	JingleRawUdpPrivate *priv;      /**< The private data of this object. */
 };
 
 struct _JingleRawUdpCandidate
@@ -89,7 +88,7 @@
 /**
  * Registers the JingleRawUdp type in the type system.
  */
-void jingle_rawudp_register_type(PurplePlugin *plugin);
+void jingle_rawudp_register(PurplePlugin *plugin);
 
 JingleRawUdpCandidate *jingle_rawudp_candidate_new(const gchar *id,
 		guint generation, guint component, const gchar *ip, guint port);
--- a/libpurple/protocols/jabber/jingle/rtp.c	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/rtp.c	Fri Mar 22 02:42:46 2019 +0000
@@ -40,19 +40,12 @@
 
 #include <string.h>
 
-struct _JingleRtpPrivate
+typedef struct
 {
 	gchar *media_type;
 	gchar *ssrc;
-};
-
-#define JINGLE_RTP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_RTP, JingleRtpPrivate))
+} JingleRtpPrivate;
 
-static void jingle_rtp_class_init (JingleRtpClass *klass);
-static void jingle_rtp_init (JingleRtp *rtp);
-static void jingle_rtp_finalize (GObject *object);
-static void jingle_rtp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void jingle_rtp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
 static JingleContent *jingle_rtp_parse_internal(PurpleXmlNode *rtp);
 static PurpleXmlNode *jingle_rtp_to_xml_internal(JingleContent *rtp, PurpleXmlNode *content, JingleActionType action);
 static void jingle_rtp_handle_action_internal(JingleContent *content, PurpleXmlNode *jingle, JingleActionType action);
@@ -66,144 +59,19 @@
 	PROP_LAST
 };
 
-static JingleContentClass *parent_class = NULL;
 static GParamSpec *properties[PROP_LAST];
 
-PURPLE_DEFINE_TYPE(JingleRtp, jingle_rtp, JINGLE_TYPE_CONTENT);
-
-static void
-jingle_rtp_class_init (JingleRtpClass *klass)
-{
-	GObjectClass *gobject_class = (GObjectClass*)klass;
-	parent_class = g_type_class_peek_parent(klass);
-
-	gobject_class->finalize = jingle_rtp_finalize;
-	gobject_class->set_property = jingle_rtp_set_property;
-	gobject_class->get_property = jingle_rtp_get_property;
-	klass->parent_class.to_xml = jingle_rtp_to_xml_internal;
-	klass->parent_class.parse = jingle_rtp_parse_internal;
-	klass->parent_class.description_type = JINGLE_APP_RTP;
-	klass->parent_class.handle_action = jingle_rtp_handle_action_internal;
-
-	g_type_class_add_private(klass, sizeof(JingleRtpPrivate));
-
-	properties[PROP_MEDIA_TYPE] = g_param_spec_string("media-type",
-			"Media Type",
-			"The media type (\"audio\" or \"video\") for this rtp session.",
-			NULL,
-			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	properties[PROP_SSRC] = g_param_spec_string("ssrc",
-			"ssrc",
-			"The ssrc for this rtp session.",
-			NULL,
-			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties(gobject_class, PROP_LAST, properties);
-}
-
-static void
-jingle_rtp_init (JingleRtp *rtp)
-{
-	rtp->priv = JINGLE_RTP_GET_PRIVATE(rtp);
-	memset(rtp->priv, 0, sizeof(*rtp->priv));
-}
-
-static void
-jingle_rtp_finalize (GObject *rtp)
-{
-	JingleRtpPrivate *priv = JINGLE_RTP_GET_PRIVATE(rtp);
-	purple_debug_info("jingle-rtp","jingle_rtp_finalize\n");
-
-	g_free(priv->media_type);
-	g_free(priv->ssrc);
-
-	G_OBJECT_CLASS(parent_class)->finalize(rtp);
-}
-
-static void
-jingle_rtp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleRtp *rtp;
-	g_return_if_fail(JINGLE_IS_RTP(object));
-
-	rtp = JINGLE_RTP(object);
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(
+	JingleRtp,
+	jingle_rtp,
+	JINGLE_TYPE_CONTENT,
+	0,
+	G_ADD_PRIVATE_DYNAMIC(JingleRtp)
+);
 
-	switch (prop_id) {
-		case PROP_MEDIA_TYPE:
-			g_free(rtp->priv->media_type);
-			rtp->priv->media_type = g_value_dup_string(value);
-			break;
-		case PROP_SSRC:
-			g_free(rtp->priv->ssrc);
-			rtp->priv->ssrc = g_value_dup_string(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_rtp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleRtp *rtp;
-	g_return_if_fail(JINGLE_IS_RTP(object));
-
-	rtp = JINGLE_RTP(object);
-
-	switch (prop_id) {
-		case PROP_MEDIA_TYPE:
-			g_value_set_string(value, rtp->priv->media_type);
-			break;
-		case PROP_SSRC:
-			g_value_set_string(value, rtp->priv->ssrc);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-gchar *
-jingle_rtp_get_media_type(JingleContent *content)
-{
-	gchar *media_type;
-	g_object_get(content, "media-type", &media_type, NULL);
-	return media_type;
-}
-
-gchar *
-jingle_rtp_get_ssrc(JingleContent *content)
-{
-	gchar *ssrc;
-	g_object_get(content, "ssrc", &ssrc, NULL);
-	return ssrc;
-}
-
-static PurpleMedia *
-jingle_rtp_get_media(JingleSession *session)
-{
-	JabberStream *js = jingle_session_get_js(session);
-	PurpleMedia *media = NULL;
-	GList *iter = purple_media_manager_get_media_by_account(
-			purple_media_manager_get(),
-			purple_connection_get_account(js->gc));
-
-	for (; iter; iter = g_list_delete_link(iter, iter)) {
-		JingleSession *media_session =
-				purple_media_get_protocol_data(iter->data);
-		if (media_session == session) {
-			media = iter->data;
-			break;
-		}
-	}
-	if (iter != NULL)
-		g_list_free(iter);
-
-	return media;
-}
-
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
 static JingleTransport *
 jingle_rtp_candidates_to_transport(JingleSession *session, const gchar *type, guint generation, GList *candidates)
 {
@@ -577,20 +445,6 @@
 	return codecs;
 }
 
-static JingleContent *
-jingle_rtp_parse_internal(PurpleXmlNode *rtp)
-{
-	JingleContent *content = parent_class->parse(rtp);
-	PurpleXmlNode *description = purple_xmlnode_get_child(rtp, "description");
-	const gchar *media_type = purple_xmlnode_get_attrib(description, "media");
-	const gchar *ssrc = purple_xmlnode_get_attrib(description, "ssrc");
-	purple_debug_info("jingle-rtp", "rtp parse\n");
-	g_object_set(content, "media-type", media_type, NULL);
-	if (ssrc != NULL)
-		g_object_set(content, "ssrc", ssrc, NULL);
-	return content;
-}
-
 static void
 jingle_rtp_add_payloads(PurpleXmlNode *description, GList *codecs)
 {
@@ -632,10 +486,13 @@
 	}
 }
 
+/******************************************************************************
+ * JingleContent Implementation
+ *****************************************************************************/
 static PurpleXmlNode *
 jingle_rtp_to_xml_internal(JingleContent *rtp, PurpleXmlNode *content, JingleActionType action)
 {
-	PurpleXmlNode *node = parent_class->to_xml(rtp, content, action);
+	PurpleXmlNode *node = JINGLE_CONTENT_CLASS(jingle_rtp_parent_class)->to_xml(rtp, content, action);
 	PurpleXmlNode *description = purple_xmlnode_get_child(node, "description");
 	if (description != NULL) {
 		JingleSession *session = jingle_content_get_session(rtp);
@@ -660,6 +517,20 @@
 	return node;
 }
 
+static JingleContent *
+jingle_rtp_parse_internal(PurpleXmlNode *rtp)
+{
+	JingleContent *content = JINGLE_CONTENT_CLASS(jingle_rtp_parent_class)->parse(rtp);
+	PurpleXmlNode *description = purple_xmlnode_get_child(rtp, "description");
+	const gchar *media_type = purple_xmlnode_get_attrib(description, "media");
+	const gchar *ssrc = purple_xmlnode_get_attrib(description, "ssrc");
+	purple_debug_info("jingle-rtp", "rtp parse\n");
+	g_object_set(content, "media-type", media_type, NULL);
+	if (ssrc != NULL)
+		g_object_set(content, "ssrc", ssrc, NULL);
+	return content;
+}
+
 static void
 jingle_rtp_handle_action_internal(JingleContent *content, PurpleXmlNode *xmlcontent, JingleActionType action)
 {
@@ -802,6 +673,149 @@
 	}
 }
 
+
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+static void
+jingle_rtp_init (JingleRtp *rtp)
+{
+}
+
+static void
+jingle_rtp_finalize (GObject *rtp)
+{
+	JingleRtpPrivate *priv = jingle_rtp_get_instance_private(JINGLE_RTP(rtp));
+	purple_debug_info("jingle-rtp","jingle_rtp_finalize\n");
+
+	g_free(priv->media_type);
+	g_free(priv->ssrc);
+
+	G_OBJECT_CLASS(jingle_rtp_parent_class)->finalize(rtp);
+}
+
+static void
+jingle_rtp_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	JingleRtp *rtp = JINGLE_RTP(object);
+	JingleRtpPrivate *priv = jingle_rtp_get_instance_private(rtp);
+
+	switch (prop_id) {
+		case PROP_MEDIA_TYPE:
+			g_free(priv->media_type);
+			priv->media_type = g_value_dup_string(value);
+			break;
+		case PROP_SSRC:
+			g_free(priv->ssrc);
+			priv->ssrc = g_value_dup_string(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_rtp_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	JingleRtp *rtp = JINGLE_RTP(object);
+	JingleRtpPrivate *priv = jingle_rtp_get_instance_private(rtp);
+
+	switch (prop_id) {
+		case PROP_MEDIA_TYPE:
+			g_value_set_string(value, priv->media_type);
+			break;
+		case PROP_SSRC:
+			g_value_set_string(value, priv->ssrc);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+
+static void
+jingle_rtp_class_finalize(JingleRtpClass *klass) {
+}
+
+static void
+jingle_rtp_class_init (JingleRtpClass *klass)
+{
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	JingleContentClass *content_class = JINGLE_CONTENT_CLASS(klass);
+
+	obj_class->finalize = jingle_rtp_finalize;
+	obj_class->set_property = jingle_rtp_set_property;
+	obj_class->get_property = jingle_rtp_get_property;
+
+	content_class->to_xml = jingle_rtp_to_xml_internal;
+	content_class->parse = jingle_rtp_parse_internal;
+	content_class->description_type = JINGLE_APP_RTP;
+	content_class->handle_action = jingle_rtp_handle_action_internal;
+
+	properties[PROP_MEDIA_TYPE] = g_param_spec_string("media-type",
+			"Media Type",
+			"The media type (\"audio\" or \"video\") for this rtp session.",
+			NULL,
+			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	properties[PROP_SSRC] = g_param_spec_string("ssrc",
+			"ssrc",
+			"The ssrc for this rtp session.",
+			NULL,
+			G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(obj_class, PROP_LAST, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+void
+jingle_rtp_register(PurplePlugin *plugin) {
+	jingle_rtp_register_type(G_TYPE_MODULE(plugin));
+}
+
+gchar *
+jingle_rtp_get_media_type(JingleContent *content)
+{
+	gchar *media_type;
+	g_object_get(content, "media-type", &media_type, NULL);
+	return media_type;
+}
+
+gchar *
+jingle_rtp_get_ssrc(JingleContent *content)
+{
+	gchar *ssrc;
+	g_object_get(content, "ssrc", &ssrc, NULL);
+	return ssrc;
+}
+
+static PurpleMedia *
+jingle_rtp_get_media(JingleSession *session)
+{
+	JabberStream *js = jingle_session_get_js(session);
+	PurpleMedia *media = NULL;
+	GList *iter = purple_media_manager_get_media_by_account(
+			purple_media_manager_get(),
+			purple_connection_get_account(js->gc));
+
+	for (; iter; iter = g_list_delete_link(iter, iter)) {
+		JingleSession *media_session =
+				purple_media_get_protocol_data(iter->data);
+		if (media_session == session) {
+			media = iter->data;
+			break;
+		}
+	}
+	if (iter != NULL)
+		g_list_free(iter);
+
+	return media;
+}
+
 gboolean
 jingle_rtp_initiate_media(JabberStream *js, const gchar *who,
 		      PurpleMediaSessionType type)
@@ -852,20 +866,30 @@
 
 
 	if (type & PURPLE_MEDIA_AUDIO) {
+		JingleRtpPrivate *priv = NULL;
+
 		transport = jingle_transport_create(transport_type);
 		content = jingle_content_create(JINGLE_APP_RTP, "initiator",
 				"session", "audio-session", "both", transport);
+
+		priv = jingle_rtp_get_instance_private(JINGLE_RTP(content));
+
 		jingle_session_add_content(session, content);
-		JINGLE_RTP(content)->priv->media_type = g_strdup("audio");
+		priv->media_type = g_strdup("audio");
 		jingle_rtp_init_media(content);
 		g_object_notify_by_pspec(G_OBJECT(content), properties[PROP_MEDIA_TYPE]);
 	}
 	if (type & PURPLE_MEDIA_VIDEO) {
+		JingleRtpPrivate *priv = NULL;
+
 		transport = jingle_transport_create(transport_type);
 		content = jingle_content_create(JINGLE_APP_RTP, "initiator",
 				"session", "video-session", "both", transport);
+
+		priv = jingle_rtp_get_instance_private(JINGLE_RTP(content));
+
 		jingle_session_add_content(session, content);
-		JINGLE_RTP(content)->priv->media_type = g_strdup("video");
+		priv->media_type = g_strdup("video");
 		jingle_rtp_init_media(content);
 		g_object_notify_by_pspec(G_OBJECT(content), properties[PROP_MEDIA_TYPE]);
 	}
@@ -902,4 +926,3 @@
 }
 
 #endif /* USE_VV */
-
--- a/libpurple/protocols/jabber/jingle/rtp.h	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/rtp.h	Fri Mar 22 02:42:46 2019 +0000
@@ -49,8 +49,6 @@
 typedef struct _JingleRtp JingleRtp;
 /** @copydoc _JingleRtpClass */
 typedef struct _JingleRtpClass JingleRtpClass;
-/** @copydoc _JingleRtpPrivate */
-typedef struct _JingleRtpPrivate JingleRtpPrivate;
 
 /** The rtp class */
 struct _JingleRtpClass
@@ -62,7 +60,6 @@
 struct _JingleRtp
 {
 	JingleContent parent;                /**< The parent of this object. */
-	JingleRtpPrivate *priv;      /**< The private data of this object. */
 };
 
 /**
@@ -75,7 +72,7 @@
 /**
  * Registers the JingleRtp type in the type system.
  */
-void jingle_rtp_register_type(PurplePlugin *plugin);
+void jingle_rtp_register(PurplePlugin *plugin);
 
 gchar *jingle_rtp_get_media_type(JingleContent *content);
 gchar *jingle_rtp_get_ssrc(JingleContent *content);
--- a/libpurple/protocols/jabber/jingle/session.c	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/session.c	Fri Mar 22 02:42:46 2019 +0000
@@ -32,7 +32,7 @@
 
 #include <string.h>
 
-struct _JingleSessionPrivate
+typedef struct
 {
 	gchar *sid;
 	JabberStream *js;
@@ -42,15 +42,7 @@
 	gboolean state;
 	GList *contents;
 	GList *pending_contents;
-};
-
-#define JINGLE_SESSION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_SESSION, JingleSessionPrivate))
-
-static void jingle_session_class_init (JingleSessionClass *klass);
-static void jingle_session_init (JingleSession *session);
-static void jingle_session_finalize (GObject *object);
-static void jingle_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void jingle_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+} JingleSessionPrivate;
 
 enum {
 	PROP_0,
@@ -65,22 +57,207 @@
 	PROP_LAST
 };
 
-static GObjectClass *parent_class = NULL;
 static GParamSpec *properties[PROP_LAST];
 
-PURPLE_DEFINE_TYPE(JingleSession, jingle_session, G_TYPE_OBJECT);
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(
+	JingleSession,
+	jingle_session,
+	G_TYPE_OBJECT,
+	0,
+	G_ADD_PRIVATE_DYNAMIC(JingleSession)
+);
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static gboolean find_by_jid_ghr(gpointer key,
+		gpointer value, gpointer user_data)
+{
+	JingleSession *session = (JingleSession *)value;
+	const gchar *jid = user_data;
+	gboolean use_bare = strchr(jid, '/') == NULL;
+	gchar *remote_jid = jingle_session_get_remote_jid(session);
+	gchar *cmp_jid = use_bare ? jabber_get_bare_jid(remote_jid)
+				  : g_strdup(remote_jid);
+	g_free(remote_jid);
+	if (purple_strequal(jid, cmp_jid)) {
+		g_free(cmp_jid);
+		return TRUE;
+	}
+	g_free(cmp_jid);
+
+	return FALSE;
+}
+
+static PurpleXmlNode *
+jingle_add_jingle_packet(JingleSession *session,
+			 JabberIq *iq, JingleActionType action)
+{
+	PurpleXmlNode *jingle = iq ?
+			purple_xmlnode_new_child(iq->node, "jingle") :
+			purple_xmlnode_new("jingle");
+	gchar *local_jid = jingle_session_get_local_jid(session);
+	gchar *remote_jid = jingle_session_get_remote_jid(session);
+	gchar *sid = jingle_session_get_sid(session);
+
+	purple_xmlnode_set_namespace(jingle, JINGLE);
+	purple_xmlnode_set_attrib(jingle, "action", jingle_get_action_name(action));
+
+	if (jingle_session_is_initiator(session)) {
+		purple_xmlnode_set_attrib(jingle, "initiator", local_jid);
+		purple_xmlnode_set_attrib(jingle, "responder", remote_jid);
+	} else {
+		purple_xmlnode_set_attrib(jingle, "initiator", remote_jid);
+		purple_xmlnode_set_attrib(jingle, "responder", local_jid);
+	}
+
+	purple_xmlnode_set_attrib(jingle, "sid", sid);
+
+	g_free(local_jid);
+	g_free(remote_jid);
+	g_free(sid);
+
+	return jingle;
+}
+
+static JabberIq *
+jingle_create_iq(JingleSession *session)
+{
+	JabberStream *js = jingle_session_get_js(session);
+	JabberIq *result = jabber_iq_new(js, JABBER_IQ_SET);
+	gchar *from = jingle_session_get_local_jid(session);
+	gchar *to = jingle_session_get_remote_jid(session);
+
+	purple_xmlnode_set_attrib(result->node, "from", from);
+	purple_xmlnode_set_attrib(result->node, "to", to);
+
+	g_free(from);
+	g_free(to);
+	return result;
+}
+
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+static void
+jingle_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	JingleSession *session = JINGLE_SESSION(object);
+	JingleSessionPrivate *priv = jingle_session_get_instance_private(session);
+
+	switch (prop_id) {
+		case PROP_SID:
+			g_free(priv->sid);
+			priv->sid = g_value_dup_string(value);
+			break;
+		case PROP_JS:
+			priv->js = g_value_get_pointer(value);
+			break;
+		case PROP_REMOTE_JID:
+			g_free(priv->remote_jid);
+			priv->remote_jid = g_value_dup_string(value);
+			break;
+		case PROP_LOCAL_JID:
+			g_free(priv->local_jid);
+			priv->local_jid = g_value_dup_string(value);
+			break;
+		case PROP_IS_INITIATOR:
+			priv->is_initiator = g_value_get_boolean(value);
+			break;
+		case PROP_STATE:
+			priv->state = g_value_get_boolean(value);
+			break;
+		case PROP_CONTENTS:
+			priv->contents = g_value_get_pointer(value);
+			break;
+		case PROP_PENDING_CONTENTS:
+			priv->pending_contents = g_value_get_pointer(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	JingleSession *session = JINGLE_SESSION(object);
+	JingleSessionPrivate *priv = jingle_session_get_instance_private(session);
+
+	switch (prop_id) {
+		case PROP_SID:
+			g_value_set_string(value, priv->sid);
+			break;
+		case PROP_JS:
+			g_value_set_pointer(value, priv->js);
+			break;
+		case PROP_REMOTE_JID:
+			g_value_set_string(value, priv->remote_jid);
+			break;
+		case PROP_LOCAL_JID:
+			g_value_set_string(value, priv->local_jid);
+			break;
+		case PROP_IS_INITIATOR:
+			g_value_set_boolean(value, priv->is_initiator);
+			break;
+		case PROP_STATE:
+			g_value_set_boolean(value, priv->state);
+			break;
+		case PROP_CONTENTS:
+			g_value_set_pointer(value, priv->contents);
+			break;
+		case PROP_PENDING_CONTENTS:
+			g_value_set_pointer(value, priv->pending_contents);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+jingle_session_init (JingleSession *session)
+{
+}
+
+static void
+jingle_session_finalize (GObject *session)
+{
+	JingleSessionPrivate *priv = jingle_session_get_instance_private(JINGLE_SESSION(session));
+	purple_debug_info("jingle","jingle_session_finalize\n");
+
+	g_hash_table_remove(priv->js->sessions, priv->sid);
+
+	g_free(priv->sid);
+	g_free(priv->remote_jid);
+	g_free(priv->local_jid);
+
+	for (; priv->contents; priv->contents =
+			g_list_delete_link(priv->contents, priv->contents)) {
+		g_object_unref(priv->contents->data);
+	}
+	for (; priv->pending_contents; priv->pending_contents =
+			g_list_delete_link(priv->pending_contents, priv->pending_contents)) {
+		g_object_unref(priv->pending_contents->data);
+	}
+
+	G_OBJECT_CLASS(jingle_session_parent_class)->finalize(session);
+}
+
+static void
+jingle_session_class_finalize (JingleSessionClass *klass)
+{
+}
 
 static void
 jingle_session_class_init (JingleSessionClass *klass)
 {
-	GObjectClass *gobject_class = (GObjectClass*)klass;
-	parent_class = g_type_class_peek_parent(klass);
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
-	gobject_class->finalize = jingle_session_finalize;
-	gobject_class->set_property = jingle_session_set_property;
-	gobject_class->get_property = jingle_session_get_property;
-
-	g_type_class_add_private(klass, sizeof(JingleSessionPrivate));
+	obj_class->finalize = jingle_session_finalize;
+	obj_class->set_property = jingle_session_set_property;
+	obj_class->get_property = jingle_session_get_property;
 
 	properties[PROP_SID] = g_param_spec_string("sid",
 			"Session ID",
@@ -127,126 +304,17 @@
 			"The pending contents contained within this session",
 			G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
-	g_object_class_install_properties(gobject_class, PROP_LAST, properties);
-}
-
-static void
-jingle_session_init (JingleSession *session)
-{
-	session->priv = JINGLE_SESSION_GET_PRIVATE(session);
-	memset(session->priv, 0, sizeof(*session->priv));
-}
-
-static void
-jingle_session_finalize (GObject *session)
-{
-	JingleSessionPrivate *priv = JINGLE_SESSION_GET_PRIVATE(session);
-	purple_debug_info("jingle","jingle_session_finalize\n");
-
-	g_hash_table_remove(priv->js->sessions, priv->sid);
-
-	g_free(priv->sid);
-	g_free(priv->remote_jid);
-	g_free(priv->local_jid);
-
-	for (; priv->contents; priv->contents =
-			g_list_delete_link(priv->contents, priv->contents)) {
-		g_object_unref(priv->contents->data);
-	}
-	for (; priv->pending_contents; priv->pending_contents =
-			g_list_delete_link(priv->pending_contents, priv->pending_contents)) {
-		g_object_unref(priv->pending_contents->data);
-	}
-
-	parent_class->finalize(session);
+	g_object_class_install_properties(obj_class, PROP_LAST, properties);
 }
 
-static void
-jingle_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	JingleSession *session;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_SESSION(object));
-
-	session = JINGLE_SESSION(object);
-
-	switch (prop_id) {
-		case PROP_SID:
-			g_free(session->priv->sid);
-			session->priv->sid = g_value_dup_string(value);
-			break;
-		case PROP_JS:
-			session->priv->js = g_value_get_pointer(value);
-			break;
-		case PROP_REMOTE_JID:
-			g_free(session->priv->remote_jid);
-			session->priv->remote_jid = g_value_dup_string(value);
-			break;
-		case PROP_LOCAL_JID:
-			g_free(session->priv->local_jid);
-			session->priv->local_jid = g_value_dup_string(value);
-			break;
-		case PROP_IS_INITIATOR:
-			session->priv->is_initiator = g_value_get_boolean(value);
-			break;
-		case PROP_STATE:
-			session->priv->state = g_value_get_boolean(value);
-			break;
-		case PROP_CONTENTS:
-			session->priv->contents = g_value_get_pointer(value);
-			break;
-		case PROP_PENDING_CONTENTS:
-			session->priv->pending_contents = g_value_get_pointer(value);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+void
+jingle_session_register(PurplePlugin *plugin) {
+	jingle_session_register_type(G_TYPE_MODULE(plugin));
 }
 
-static void
-jingle_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	JingleSession *session;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(JINGLE_IS_SESSION(object));
-
-	session = JINGLE_SESSION(object);
-
-	switch (prop_id) {
-		case PROP_SID:
-			g_value_set_string(value, session->priv->sid);
-			break;
-		case PROP_JS:
-			g_value_set_pointer(value, session->priv->js);
-			break;
-		case PROP_REMOTE_JID:
-			g_value_set_string(value, session->priv->remote_jid);
-			break;
-		case PROP_LOCAL_JID:
-			g_value_set_string(value, session->priv->local_jid);
-			break;
-		case PROP_IS_INITIATOR:
-			g_value_set_boolean(value, session->priv->is_initiator);
-			break;
-		case PROP_STATE:
-			g_value_set_boolean(value, session->priv->state);
-			break;
-		case PROP_CONTENTS:
-			g_value_set_pointer(value, session->priv->contents);
-			break;
-		case PROP_PENDING_CONTENTS:
-			g_value_set_pointer(value, session->priv->pending_contents);
-			break;
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-
 JingleSession *
 jingle_session_create(JabberStream *js, const gchar *sid,
 			const gchar *local_jid, const gchar *remote_jid,
@@ -351,25 +419,6 @@
 	return session;
 }
 
-static gboolean find_by_jid_ghr(gpointer key,
-		gpointer value, gpointer user_data)
-{
-	JingleSession *session = (JingleSession *)value;
-	const gchar *jid = user_data;
-	gboolean use_bare = strchr(jid, '/') == NULL;
-	gchar *remote_jid = jingle_session_get_remote_jid(session);
-	gchar *cmp_jid = use_bare ? jabber_get_bare_jid(remote_jid)
-				  : g_strdup(remote_jid);
-	g_free(remote_jid);
-	if (purple_strequal(jid, cmp_jid)) {
-		g_free(cmp_jid);
-		return TRUE;
-	}
-	g_free(cmp_jid);
-
-	return FALSE;
-}
-
 JingleSession *
 jingle_session_find_by_jid(JabberStream *js, const gchar *jid)
 {
@@ -378,37 +427,6 @@
 			find_by_jid_ghr, (gpointer)jid) : NULL;
 }
 
-static PurpleXmlNode *
-jingle_add_jingle_packet(JingleSession *session,
-			 JabberIq *iq, JingleActionType action)
-{
-	PurpleXmlNode *jingle = iq ?
-			purple_xmlnode_new_child(iq->node, "jingle") :
-			purple_xmlnode_new("jingle");
-	gchar *local_jid = jingle_session_get_local_jid(session);
-	gchar *remote_jid = jingle_session_get_remote_jid(session);
-	gchar *sid = jingle_session_get_sid(session);
-
-	purple_xmlnode_set_namespace(jingle, JINGLE);
-	purple_xmlnode_set_attrib(jingle, "action", jingle_get_action_name(action));
-
-	if (jingle_session_is_initiator(session)) {
-		purple_xmlnode_set_attrib(jingle, "initiator", local_jid);
-		purple_xmlnode_set_attrib(jingle, "responder", remote_jid);
-	} else {
-		purple_xmlnode_set_attrib(jingle, "initiator", remote_jid);
-		purple_xmlnode_set_attrib(jingle, "responder", local_jid);
-	}
-
-	purple_xmlnode_set_attrib(jingle, "sid", sid);
-
-	g_free(local_jid);
-	g_free(remote_jid);
-	g_free(sid);
-
-	return jingle;
-}
-
 JabberIq *
 jingle_session_create_ack(JingleSession *session, const PurpleXmlNode *jingle)
 {
@@ -422,22 +440,6 @@
 	return result;
 }
 
-static JabberIq *
-jingle_create_iq(JingleSession *session)
-{
-	JabberStream *js = jingle_session_get_js(session);
-	JabberIq *result = jabber_iq_new(js, JABBER_IQ_SET);
-	gchar *from = jingle_session_get_local_jid(session);
-	gchar *to = jingle_session_get_remote_jid(session);
-
-	purple_xmlnode_set_attrib(result->node, "from", from);
-	purple_xmlnode_set_attrib(result->node, "to", to);
-
-	g_free(from);
-	g_free(to);
-	return result;
-}
-
 PurpleXmlNode *
 jingle_session_to_xml(JingleSession *session, PurpleXmlNode *jingle, JingleActionType action)
 {
@@ -482,12 +484,17 @@
 JingleContent *
 jingle_session_find_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
+	JingleSessionPrivate *priv = NULL;
 	GList *iter;
 
+	g_return_val_if_fail(JINGLE_IS_SESSION(session), NULL);
+
 	if (name == NULL)
 		return NULL;
 
-	iter = session->priv->contents;
+	priv = jingle_session_get_instance_private(session);
+
+	iter = priv->contents;
 	for (; iter; iter = g_list_next(iter)) {
 		JingleContent *content = iter->data;
 		gchar *cname = jingle_content_get_name(content);
@@ -509,12 +516,17 @@
 JingleContent *
 jingle_session_find_pending_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
+	JingleSessionPrivate *priv = NULL;
 	GList *iter;
 
+	g_return_val_if_fail(JINGLE_IS_SESSION(session), NULL);
+
 	if (name == NULL)
 		return NULL;
 
-	iter = session->priv->pending_contents;
+	priv = jingle_session_get_instance_private(session);
+
+	iter = priv->pending_contents;
 	for (; iter; iter = g_list_next(iter)) {
 		JingleContent *content = iter->data;
 		gchar *cname = jingle_content_get_name(content);
@@ -536,8 +548,13 @@
 void
 jingle_session_add_content(JingleSession *session, JingleContent* content)
 {
-	session->priv->contents =
-			g_list_append(session->priv->contents, content);
+	JingleSessionPrivate *priv = NULL;
+
+	g_return_if_fail(JINGLE_IS_SESSION(session));
+
+	priv = jingle_session_get_instance_private(session);
+
+	priv->contents = g_list_append(priv->contents, content);
 	jingle_content_set_session(content, session);
 
 	g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_CONTENTS]);
@@ -546,12 +563,16 @@
 void
 jingle_session_remove_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
-	JingleContent *content =
-			jingle_session_find_content(session, name, creator);
+	JingleSessionPrivate *priv = NULL;
+	JingleContent *content = NULL;
+
+	g_return_if_fail(JINGLE_IS_SESSION(session));
+
+	priv = jingle_session_get_instance_private(session);
+	content = jingle_session_find_content(session, name, creator);
 
 	if (content) {
-		session->priv->contents =
-				g_list_remove(session->priv->contents, content);
+		priv->contents = g_list_remove(priv->contents, content);
 		g_object_unref(content);
 
 		g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_CONTENTS]);
@@ -561,8 +582,13 @@
 void
 jingle_session_add_pending_content(JingleSession *session, JingleContent* content)
 {
-	session->priv->pending_contents =
-			g_list_append(session->priv->pending_contents, content);
+	JingleSessionPrivate *priv = NULL;
+
+	g_return_if_fail(JINGLE_IS_SESSION(session));
+
+	priv = jingle_session_get_instance_private(session);
+
+	priv->pending_contents = g_list_append(priv->pending_contents, content);
 	jingle_content_set_session(content, session);
 
 	g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_PENDING_CONTENTS]);
@@ -571,11 +597,16 @@
 void
 jingle_session_remove_pending_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
-	JingleContent *content = jingle_session_find_pending_content(session, name, creator);
+	JingleSessionPrivate *priv = NULL;
+	JingleContent *content = NULL;
+
+	g_return_if_fail(JINGLE_IS_SESSION(session));
+
+	priv = jingle_session_get_instance_private(session);
+	content = jingle_session_find_pending_content(session, name, creator);
 
 	if (content) {
-		session->priv->pending_contents =
-				g_list_remove(session->priv->pending_contents, content);
+		priv->pending_contents = g_list_remove(priv->pending_contents, content);
 		g_object_unref(content);
 
 		g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_PENDING_CONTENTS]);
@@ -585,8 +616,11 @@
 void
 jingle_session_accept_content(JingleSession *session, const gchar *name, const gchar *creator)
 {
-	JingleContent *content = jingle_session_find_pending_content(session, name, creator);
+	JingleContent *content = NULL;
 
+	g_return_if_fail(JINGLE_IS_SESSION(session));
+
+	content = jingle_session_find_pending_content(session, name, creator);
 	if (content) {
 		g_object_ref(content);
 		jingle_session_remove_pending_content(session, name, creator);
@@ -597,7 +631,13 @@
 void
 jingle_session_accept_session(JingleSession *session)
 {
-	session->priv->state = TRUE;
+	JingleSessionPrivate *priv = NULL;
+
+	g_return_if_fail(JINGLE_IS_SESSION(session));
+
+	priv = jingle_session_get_instance_private(session);
+
+	priv->state = TRUE;
 
 	g_object_notify_by_pspec(G_OBJECT(session), properties[PROP_STATE]);
 }
@@ -605,25 +645,32 @@
 JabberIq *
 jingle_session_terminate_packet(JingleSession *session, const gchar *reason)
 {
-	JabberIq *iq = jingle_session_to_packet(session,
-			JINGLE_SESSION_TERMINATE);
-	PurpleXmlNode *jingle = purple_xmlnode_get_child(iq->node, "jingle");
+	JabberIq *iq = NULL;
+
+	g_return_val_if_fail(JINGLE_IS_SESSION(session), NULL);
+
+	iq = jingle_session_to_packet(session, JINGLE_SESSION_TERMINATE);
 
 	if (reason != NULL) {
 		PurpleXmlNode *reason_node;
+		PurpleXmlNode *jingle = purple_xmlnode_get_child(iq->node, "jingle");
 		reason_node = purple_xmlnode_new_child(jingle, "reason");
 		purple_xmlnode_new_child(reason_node, reason);
 	}
+
 	return iq;
 }
 
 JabberIq *
 jingle_session_redirect_packet(JingleSession *session, const gchar *sid)
 {
-	JabberIq *iq = jingle_session_terminate_packet(session,
-			"alternative-session");
+	JabberIq *iq = NULL;
 	PurpleXmlNode *alt_session;
 
+	g_return_val_if_fail(JINGLE_IS_SESSION(session), NULL);
+
+	iq = jingle_session_terminate_packet(session, "alternative-session");
+
 	if (sid == NULL)
 		return iq;
 
@@ -634,6 +681,6 @@
 		PurpleXmlNode *sid_node = purple_xmlnode_new_child(alt_session, "sid");
 		purple_xmlnode_insert_data(sid_node, sid, -1);
 	}
+
 	return iq;
 }
-
--- a/libpurple/protocols/jabber/jingle/session.h	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/session.h	Fri Mar 22 02:42:46 2019 +0000
@@ -44,8 +44,6 @@
 typedef struct _JingleSession JingleSession;
 /** @copydoc _JingleSessionClass */
 typedef struct _JingleSessionClass JingleSessionClass;
-/** @copydoc _JingleSessionPrivate */
-typedef struct _JingleSessionPrivate JingleSessionPrivate;
 
 /** The session class */
 struct _JingleSessionClass
@@ -57,7 +55,6 @@
 struct _JingleSession
 {
 	GObject parent;                /**< The parent of this object. */
-	JingleSessionPrivate *priv;      /**< The private data of this object. */
 };
 
 struct _JingleContent;
@@ -72,7 +69,7 @@
 /**
  * Registers the JingleSession type in the type system.
  */
-void jingle_session_register_type(PurplePlugin *plugin);
+void jingle_session_register(PurplePlugin *plugin);
 
 JingleSession *jingle_session_create(JabberStream *js, const gchar *sid,
 				     const gchar *local_jid, const gchar *remote_jid,
--- a/libpurple/protocols/jabber/jingle/transport.c	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/transport.c	Fri Mar 22 02:42:46 2019 +0000
@@ -30,88 +30,66 @@
 
 #include <string.h>
 
-struct _JingleTransportPrivate
+G_DEFINE_DYNAMIC_TYPE(JingleTransport, jingle_transport, G_TYPE_OBJECT);
+
+/******************************************************************************
+ * Transport Implementation
+ *****************************************************************************/
+static JingleTransport *
+jingle_transport_parse_internal(PurpleXmlNode *transport)
 {
-	void *dummy;
-};
+	const gchar *type = purple_xmlnode_get_namespace(transport);
+	return jingle_transport_create(type);
+}
 
-#define JINGLE_TRANSPORT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_TRANSPORT, JingleTransportPrivate))
+static void
+jingle_transport_add_local_candidate_internal(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate)
+{
+	/* Nothing to do */
+}
 
-static void jingle_transport_class_init (JingleTransportClass *klass);
-static void jingle_transport_init (JingleTransport *transport);
-static void jingle_transport_finalize (GObject *object);
-static void jingle_transport_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
-static void jingle_transport_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-JingleTransport *jingle_transport_parse_internal(PurpleXmlNode *transport);
-PurpleXmlNode *jingle_transport_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action);
-static void jingle_transport_add_local_candidate_internal(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate);
-static GList *jingle_transport_get_remote_candidates_internal(JingleTransport *transport);
+static PurpleXmlNode *
+jingle_transport_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
+{
+	PurpleXmlNode *node = purple_xmlnode_new_child(content, "transport");
+	purple_xmlnode_set_namespace(node, jingle_transport_get_transport_type(transport));
+	return node;
+}
 
-static GObjectClass *parent_class = NULL;
+static GList *
+jingle_transport_get_remote_candidates_internal(JingleTransport *transport)
+{
+	return NULL;
+}
 
-enum {
-	PROP_0,
-};
+/******************************************************************************
+ * GObject Stuff
+ *****************************************************************************/
+static void
+jingle_transport_init (JingleTransport *transport)
+{
+}
 
-PURPLE_DEFINE_TYPE(JingleTransport, jingle_transport, G_TYPE_OBJECT);
+static void
+jingle_transport_class_finalize (JingleTransportClass *klass)
+{
+}
 
 static void
 jingle_transport_class_init (JingleTransportClass *klass)
 {
-	GObjectClass *gobject_class = (GObjectClass*)klass;
-	parent_class = g_type_class_peek_parent(klass);
-
-	gobject_class->finalize = jingle_transport_finalize;
-	gobject_class->set_property = jingle_transport_set_property;
-	gobject_class->get_property = jingle_transport_get_property;
 	klass->to_xml = jingle_transport_to_xml_internal;
 	klass->parse = jingle_transport_parse_internal;
 	klass->add_local_candidate = jingle_transport_add_local_candidate_internal;
 	klass->get_remote_candidates = jingle_transport_get_remote_candidates_internal;
-
-	g_type_class_add_private(klass, sizeof(JingleTransportPrivate));
-}
-
-static void
-jingle_transport_init (JingleTransport *transport)
-{
-	transport->priv = JINGLE_TRANSPORT_GET_PRIVATE(transport);
-	transport->priv->dummy = NULL;
-}
-
-static void
-jingle_transport_finalize (GObject *transport)
-{
-	/* JingleTransportPrivate *priv = JINGLE_TRANSPORT_GET_PRIVATE(transport); */
-	purple_debug_info("jingle","jingle_transport_finalize\n");
-
-	parent_class->finalize(transport);
 }
 
-static void
-jingle_transport_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	g_return_if_fail(G_IS_OBJECT(object));
-	g_return_if_fail(JINGLE_IS_TRANSPORT(object));
-
-	switch (prop_id) {
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
-}
-
-static void
-jingle_transport_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	g_return_if_fail(G_IS_OBJECT(object));
-	g_return_if_fail(JINGLE_IS_TRANSPORT(object));
-
-	switch (prop_id) {
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-			break;
-	}
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+void
+jingle_transport_register(PurplePlugin *plugin) {
+	jingle_transport_register_type(G_TYPE_MODULE(plugin));
 }
 
 JingleTransport *
@@ -134,39 +112,12 @@
 	                                                           generation, candidate);
 }
 
-void
-jingle_transport_add_local_candidate_internal(JingleTransport *transport, const gchar *id, guint generation, PurpleMediaCandidate *candidate)
-{
-	/* Nothing to do */
-}
-
 GList *
 jingle_transport_get_remote_candidates(JingleTransport *transport)
 {
 	return JINGLE_TRANSPORT_GET_CLASS(transport)->get_remote_candidates(transport);
 }
 
-static GList *
-jingle_transport_get_remote_candidates_internal(JingleTransport *transport)
-{
-	return NULL;
-}
-
-JingleTransport *
-jingle_transport_parse_internal(PurpleXmlNode *transport)
-{
-	const gchar *type = purple_xmlnode_get_namespace(transport);
-	return jingle_transport_create(type);
-}
-
-PurpleXmlNode *
-jingle_transport_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
-{
-	PurpleXmlNode *node = purple_xmlnode_new_child(content, "transport");
-	purple_xmlnode_set_namespace(node, jingle_transport_get_transport_type(transport));
-	return node;
-}
-
 JingleTransport *
 jingle_transport_parse(PurpleXmlNode *transport)
 {
@@ -174,7 +125,7 @@
 	GType type = jingle_get_type(type_name);
 	if (type == G_TYPE_NONE)
 		return NULL;
-	
+
 	return JINGLE_TRANSPORT_CLASS(g_type_class_ref(type))->parse(transport);
 }
 
@@ -185,4 +136,3 @@
 	g_return_val_if_fail(JINGLE_IS_TRANSPORT(transport), NULL);
 	return JINGLE_TRANSPORT_GET_CLASS(transport)->to_xml(transport, content, action);
 }
-
--- a/libpurple/protocols/jabber/jingle/transport.h	Fri Mar 22 01:54:47 2019 +0000
+++ b/libpurple/protocols/jabber/jingle/transport.h	Fri Mar 22 02:42:46 2019 +0000
@@ -44,8 +44,6 @@
 typedef struct _JingleTransport JingleTransport;
 /** @copydoc _JingleTransportClass */
 typedef struct _JingleTransportClass JingleTransportClass;
-/** @copydoc _JingleTransportPrivate */
-typedef struct _JingleTransportPrivate JingleTransportPrivate;
 
 /** The transport class */
 struct _JingleTransportClass
@@ -63,7 +61,6 @@
 struct _JingleTransport
 {
 	GObject parent;                /**< The parent of this object. */
-	JingleTransportPrivate *priv;      /**< The private data of this object. */
 };
 
 /**
@@ -76,7 +73,7 @@
 /**
  * Registers the JingleTransport type in the type system.
  */
-void jingle_transport_register_type(PurplePlugin *plugin);
+void jingle_transport_register(PurplePlugin *plugin);
 
 JingleTransport *jingle_transport_create(const gchar *type);
 const gchar *jingle_transport_get_transport_type(JingleTransport *transport);

mercurial