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); } }
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; }
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); }
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); }
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; }
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; }
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); }
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)++; } }
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); }
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; } }
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); } }