static void
google_session_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
		gchar *sid, gchar *name, gboolean local,
		GoogleSession *session)
{
	if (sid != NULL || name != NULL)
		return;

	if (type == PURPLE_MEDIA_INFO_HANGUP) {
		PurpleXmlNode *sess;
		JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);

		purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
		sess = google_session_create_xmlnode(session, "terminate");
		purple_xmlnode_insert_child(iq->node, sess);

		jabber_iq_send(iq);
	} else if (type == PURPLE_MEDIA_INFO_REJECT) {
		PurpleXmlNode *sess;
		JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);

		purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
		sess = google_session_create_xmlnode(session, "reject");
		purple_xmlnode_insert_child(iq->node, sess);

		jabber_iq_send(iq);
	} else if (type == PURPLE_MEDIA_INFO_ACCEPT && local == TRUE) {
		google_session_ready(session);
	}
}
Esempio n. 2
0
PurpleXmlNode *
purple_xmlnode_new_child(PurpleXmlNode *parent, const char *name)
{
    PurpleXmlNode *node;

    g_return_val_if_fail(parent != NULL, NULL);
    g_return_val_if_fail(name != NULL && *name != '\0', NULL);

    node = new_node(name, PURPLE_XMLNODE_TYPE_TAG);

    purple_xmlnode_insert_child(parent, node);
#if 0
    /* This would give PurpleXmlNodes more appropriate namespacing
     * when creating them.  Otherwise, unless an explicit namespace
     * is set, purple_xmlnode_get_namespace() will return NULL, when
     * there may be a default namespace.
     *
     * I'm unconvinced that it's useful, and concerned it may break things.
     *
     * _insert_child would need the same thing, probably (assuming
     * xmlns->node == NULL)
     */
    purple_xmlnode_set_namespace(node, purple_xmlnode_get_default_namespace(node))
#endif

    return node;
}
Esempio n. 3
0
static void
jabber_ibb_send_error_response(JabberStream *js, const char *to, const char *id)
{
	JabberIq *result = jabber_iq_new(js, JABBER_IQ_ERROR);
	PurpleXmlNode *error = purple_xmlnode_new("error");
	PurpleXmlNode *item_not_found = purple_xmlnode_new("item-not-found");

	purple_xmlnode_set_namespace(item_not_found, NS_XMPP_STANZAS);
	purple_xmlnode_set_attrib(error, "code", "440");
	purple_xmlnode_set_attrib(error, "type", "cancel");
	jabber_iq_set_id(result, id);
	purple_xmlnode_set_attrib(result->node, "to", to);
	purple_xmlnode_insert_child(error, item_not_found);
	purple_xmlnode_insert_child(result->node, error);

	jabber_iq_send(result);
}
Esempio n. 4
0
static void
add_smiley_to_main_node(gpointer key, gpointer value, gpointer user_data)
{
	PurpleXmlNode *child_node;

	child_node = smiley_to_xmlnode(value);
	purple_xmlnode_insert_child((PurpleXmlNode*)user_data, child_node);
}
Esempio n. 5
0
static PurpleXmlNode *
smileys_to_xmlnode(void)
{
	PurpleXmlNode *root_node, *profile_node, *smileyset_node;

	root_node = purple_xmlnode_new(XML_ROOT_TAG);
	purple_xmlnode_set_attrib(root_node, "version", "1.0");

	/* See the top comments above to understand why initial tag elements
	 * are not being considered by now. */
	profile_node = purple_xmlnode_new(XML_PROFILE_TAG);
	if (profile_node) {
		purple_xmlnode_set_attrib(profile_node, XML_PROFILE_NAME_ATTRIB_TAG, "Default");
		purple_xmlnode_insert_child(root_node, profile_node);

		smileyset_node = purple_xmlnode_new(XML_SMILEY_SET_TAG);
		if (smileyset_node) {
			purple_xmlnode_insert_child(profile_node, smileyset_node);
			g_hash_table_foreach(smiley_shortcut_index, add_smiley_to_main_node, smileyset_node);
		}
	}

	return root_node;
}
Esempio n. 6
0
static PurpleXmlNode *
pounces_to_xmlnode(void)
{
	PurpleXmlNode *node, *child;
	GList *cur;

	node = purple_xmlnode_new("pounces");
	purple_xmlnode_set_attrib(node, "version", "1.0");

	for (cur = purple_pounces_get_all(); cur != NULL; cur = cur->next)
	{
		child = pounce_to_xmlnode(cur->data);
		purple_xmlnode_insert_child(node, child);
	}

	return node;
}
Esempio n. 7
0
void
purple_xmlnode_set_attrib_full(PurpleXmlNode *node, const char *attr, const char *xmlns, const char *prefix, const char *value)
{
    PurpleXmlNode *attrib_node;

    g_return_if_fail(node != NULL);
    g_return_if_fail(attr != NULL);
    g_return_if_fail(value != NULL);

    purple_xmlnode_remove_attrib_with_namespace(node, attr, xmlns);
    attrib_node = new_node(attr, PURPLE_XMLNODE_TYPE_ATTRIB);

    attrib_node->data = g_strdup(value);
    attrib_node->xmlns = g_strdup(xmlns);
    attrib_node->prefix = g_strdup(prefix);

    purple_xmlnode_insert_child(node, attrib_node);
}
Esempio n. 8
0
void
jabber_ibb_session_send_data(JabberIBBSession *sess, gconstpointer data,
                             gsize size)
{
	JabberIBBSessionState state = jabber_ibb_session_get_state(sess);

	purple_debug_info("jabber", "sending data block of %" G_GSIZE_FORMAT " bytes on IBB stream\n",
		size);

	if (state != JABBER_IBB_SESSION_OPENED) {
		purple_debug_error("jabber",
			"trying to send data on a non-open IBB session\n");
	} else if (size > jabber_ibb_session_get_max_data_size(sess)) {
		purple_debug_error("jabber",
			"trying to send a too large packet in the IBB session\n");
	} else {
		JabberIq *set = jabber_iq_new(jabber_ibb_session_get_js(sess),
			JABBER_IQ_SET);
		PurpleXmlNode *data_element = purple_xmlnode_new("data");
		char *base64 = purple_base64_encode(data, size);
		char seq[10];
		g_snprintf(seq, sizeof(seq), "%u", jabber_ibb_session_get_send_seq(sess));

		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
		purple_xmlnode_set_namespace(data_element, NS_IBB);
		purple_xmlnode_set_attrib(data_element, "sid", jabber_ibb_session_get_sid(sess));
		purple_xmlnode_set_attrib(data_element, "seq", seq);
		purple_xmlnode_insert_data(data_element, base64, -1);

		purple_xmlnode_insert_child(set->node, data_element);

		purple_debug_info("jabber",
			"IBB: setting send <iq/> callback for session %p %s\n", sess,
			sess->sid);
		jabber_iq_set_callback(set, jabber_ibb_session_send_acknowledge_cb, sess);
		sess->last_iq_id = g_strdup(purple_xmlnode_get_attrib(set->node, "id"));
		purple_debug_info("jabber", "IBB: set sess->last_iq_id: %s\n",
			sess->last_iq_id);
		jabber_iq_send(set);

		g_free(base64);
		(sess->send_seq)++;
	}
}
Esempio n. 9
0
void
purple_xmlnode_insert_data(PurpleXmlNode *node, const char *data, gssize size)
{
    PurpleXmlNode *child;
    gsize real_size;

    g_return_if_fail(node != NULL);
    g_return_if_fail(data != NULL);
    g_return_if_fail(size != 0);

    real_size = size == -1 ? strlen(data) : (gsize)size;

    child = new_node(NULL, PURPLE_XMLNODE_TYPE_DATA);

    child->data = g_memdup(data, real_size);
    child->data_sz = real_size;

    purple_xmlnode_insert_child(node, child);
}
Esempio n. 10
0
void
jabber_ibb_session_close(JabberIBBSession *sess)
{
	JabberIBBSessionState state = jabber_ibb_session_get_state(sess);

	if (state != JABBER_IBB_SESSION_OPENED && state != JABBER_IBB_SESSION_ERROR) {
		purple_debug_error("jabber",
			"jabber_ibb_session_close called on a session that has not been"
			"opened\n");
	} else {
		JabberIq *set = jabber_iq_new(jabber_ibb_session_get_js(sess),
			JABBER_IQ_SET);
		PurpleXmlNode *close = purple_xmlnode_new("close");

		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
		purple_xmlnode_set_namespace(close, NS_IBB);
		purple_xmlnode_set_attrib(close, "sid", jabber_ibb_session_get_sid(sess));
		purple_xmlnode_insert_child(set->node, close);
		jabber_iq_send(set);
		sess->state = JABBER_IBB_SESSION_CLOSED;
	}
}
Esempio n. 11
0
void
jabber_ibb_session_open(JabberIBBSession *sess)
{
	if (jabber_ibb_session_get_state(sess) != JABBER_IBB_SESSION_NOT_OPENED) {
		purple_debug_error("jabber",
			"jabber_ibb_session called on an already open stream\n");
	} else {
		JabberIq *set = jabber_iq_new(sess->js, JABBER_IQ_SET);
		PurpleXmlNode *open = purple_xmlnode_new("open");
		gchar block_size[10];

		purple_xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
		purple_xmlnode_set_namespace(open, NS_IBB);
		purple_xmlnode_set_attrib(open, "sid", jabber_ibb_session_get_sid(sess));
		g_snprintf(block_size, sizeof(block_size), "%" G_GSIZE_FORMAT,
			jabber_ibb_session_get_block_size(sess));
		purple_xmlnode_set_attrib(open, "block-size", block_size);
		purple_xmlnode_insert_child(set->node, open);

		jabber_iq_set_callback(set, jabber_ibb_session_opened_cb, sess);

		jabber_iq_send(set);
	}
}
static void
google_session_send_candidates(PurpleMedia *media, gchar *session_id,
		gchar *participant, GoogleSession *session)
{
	PurpleMedia *session_media =
		((GoogleAVSessionData *) session->session_data)->media;
	GList *candidates =
		purple_media_get_local_candidates(session_media, session_id,
		    session->remote_jid);
	GList *iter;
	PurpleMediaCandidate *transport;
	gboolean video = FALSE;

	if (!strcmp(session_id, "google-video"))
		video = TRUE;

	for (iter = candidates; iter; iter = iter->next) {
		JabberIq *iq;
		gchar *ip, *port, *username, *password;
		gchar pref[16];
		PurpleMediaCandidateType type;
		PurpleXmlNode *sess;
		PurpleXmlNode *candidate;
		guint component_id;
		transport = PURPLE_MEDIA_CANDIDATE(iter->data);
		component_id = purple_media_candidate_get_component_id(
				transport);

		iq = jabber_iq_new(session->js, JABBER_IQ_SET);
		sess = google_session_create_xmlnode(session, "candidates");
		purple_xmlnode_insert_child(iq->node, sess);
		purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);

		candidate = purple_xmlnode_new("candidate");

		ip = purple_media_candidate_get_ip(transport);
		port = g_strdup_printf("%d",
				purple_media_candidate_get_port(transport));
		g_ascii_dtostr(pref, 16,
			purple_media_candidate_get_priority(transport) / 1000.0);
		username = purple_media_candidate_get_username(transport);
		password = purple_media_candidate_get_password(transport);
		type = purple_media_candidate_get_candidate_type(transport);

		purple_xmlnode_set_attrib(candidate, "address", ip);
		purple_xmlnode_set_attrib(candidate, "port", port);
		purple_xmlnode_set_attrib(candidate, "name",
				component_id == PURPLE_MEDIA_COMPONENT_RTP ?
				video ? "video_rtp" : "rtp" :
				component_id == PURPLE_MEDIA_COMPONENT_RTCP ?
				video ? "video_rtcp" : "rtcp" : "none");
		purple_xmlnode_set_attrib(candidate, "username", username);
		/*
		 * As of this writing, Farsight 2 in Google compatibility
		 * mode doesn't provide a password. The Gmail client
		 * requires this to be set.
		 */
		purple_xmlnode_set_attrib(candidate, "password",
				password != NULL ? password : "");
		purple_xmlnode_set_attrib(candidate, "preference", pref);
		purple_xmlnode_set_attrib(candidate, "protocol",
				purple_media_candidate_get_protocol(transport)
				== PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ?
				"udp" : "tcp");
		purple_xmlnode_set_attrib(candidate, "type", type ==
				PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "local" :
						      type ==
				PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "stun" :
					       	      type ==
				PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
				NULL);
		purple_xmlnode_set_attrib(candidate, "generation", "0");
		purple_xmlnode_set_attrib(candidate, "network", "0");
		purple_xmlnode_insert_child(sess, candidate);

		g_free(ip);
		g_free(port);
		g_free(username);
		g_free(password);

		jabber_iq_send(iq);
	}
	purple_media_candidate_list_free(candidates);
}
static void
google_session_ready(GoogleSession *session)
{
	PurpleMedia *media =
		((GoogleAVSessionData *)session->session_data)->media;
	gboolean video =
		((GoogleAVSessionData *)session->session_data)->video;
	if (purple_media_codecs_ready(media, NULL) &&
			purple_media_candidates_prepared(media, NULL, NULL)) {
		gchar *me = g_strdup_printf("%s@%s/%s",
				session->js->user->node,
				session->js->user->domain,
				session->js->user->resource);
		JabberIq *iq;
		PurpleXmlNode *sess, *desc, *payload;
		GList *codecs, *iter;
		gboolean is_initiator = !strcmp(session->id.initiator, me);

		if (!is_initiator &&
				!purple_media_accepted(media, NULL, NULL)) {
			g_free(me);
			return;
		}

		iq = jabber_iq_new(session->js, JABBER_IQ_SET);

		if (is_initiator) {
			purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
			purple_xmlnode_set_attrib(iq->node, "from", session->id.initiator);
			sess = google_session_create_xmlnode(session, "initiate");
		} else {
			google_session_send_candidates(media,
					"google-voice", session->remote_jid,
					session);
			google_session_send_candidates(media,
					"google-video", session->remote_jid,
					session);
			purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
			purple_xmlnode_set_attrib(iq->node, "from", me);
			sess = google_session_create_xmlnode(session, "accept");
		}
		purple_xmlnode_insert_child(iq->node, sess);
		desc = purple_xmlnode_new_child(sess, "description");
		if (video)
			purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_VIDEO);
		else
			purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_PHONE);

		codecs = purple_media_get_codecs(media, "google-video");

		for (iter = codecs; iter; iter = g_list_next(iter)) {
			PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
			gchar *id = g_strdup_printf("%d",
					purple_media_codec_get_id(codec));
			gchar *encoding_name =
					purple_media_codec_get_encoding_name(codec);
			payload = purple_xmlnode_new_child(desc, "payload-type");
			purple_xmlnode_set_attrib(payload, "id", id);
			purple_xmlnode_set_attrib(payload, "name", encoding_name);
			purple_xmlnode_set_attrib(payload, "width", "320");
			purple_xmlnode_set_attrib(payload, "height", "200");
			purple_xmlnode_set_attrib(payload, "framerate", "30");
			g_free(encoding_name);
			g_free(id);
		}
		purple_media_codec_list_free(codecs);

		codecs = purple_media_get_codecs(media, "google-voice");

		for (iter = codecs; iter; iter = g_list_next(iter)) {
			PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
			gchar *id = g_strdup_printf("%d",
					purple_media_codec_get_id(codec));
			gchar *encoding_name =
					purple_media_codec_get_encoding_name(codec);
			gchar *clock_rate = g_strdup_printf("%d",
					purple_media_codec_get_clock_rate(codec));
			payload = purple_xmlnode_new_child(desc, "payload-type");
			if (video)
				purple_xmlnode_set_namespace(payload, NS_GOOGLE_SESSION_PHONE);
			purple_xmlnode_set_attrib(payload, "id", id);
			/*
			 * Hack to make Gmail accept speex as the codec.
			 * It shouldn't have to be case sensitive.
			 */
			if (purple_strequal(encoding_name, "SPEEX"))
				purple_xmlnode_set_attrib(payload, "name", "speex");
			else
				purple_xmlnode_set_attrib(payload, "name", encoding_name);
			purple_xmlnode_set_attrib(payload, "clockrate", clock_rate);
			g_free(clock_rate);
			g_free(encoding_name);
			g_free(id);
		}
		purple_media_codec_list_free(codecs);

		jabber_iq_send(iq);

		if (is_initiator) {
			google_session_send_candidates(media,
					"google-voice", session->remote_jid,
					session);
			google_session_send_candidates(media,
					"google-video", session->remote_jid,
					session);
		}

		g_signal_handlers_disconnect_by_func(G_OBJECT(media),
				G_CALLBACK(google_session_ready), session);
	}
}