Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- comparing with ../main/
- diff --git a/.hgignore b/.hgignore
- --- a/.hgignore
- +++ b/.hgignore
- @@ -120,5 +120,6 @@
- po/pidgin.pot
- po/stamp-it
- stamp-h1
- +\#.*\#
- test-driver
- win32-install-dir(\.release)?
- diff --git a/configure.ac b/configure.ac
- --- a/configure.ac
- +++ b/configure.ac
- @@ -1029,6 +1029,25 @@
- AM_CONDITIONAL(USE_VV, test "x$enable_vv" != "xno")
- dnl #######################################################################
- +dnl # Check for libnice
- +dnl #######################################################################
- +PKG_CHECK_MODULES(LIBNICE, nice, , [
- + AC_MSG_RESULT(no)
- + enable_libnice="no"
- + if test "x$force_deps" = "xyes" ; then
- + AC_MSG_ERROR([
- +libnice development headers not found.
- +Use --disable-libnice if you do not need it.
- +])
- + fi])
- +if test "x$enable_libnice" = "xyes" ; then
- + AC_DEFINE(USE_LIBNICE, 1, [Define if we're using libnice])
- + AC_SUBST(LIBNICE_CFLAGS)
- + AC_SUBST(LIBNICE_LIBS)
- +fi
- +
- +
- +dnl #######################################################################
- dnl # Check for Internationalized Domain Name support
- dnl #######################################################################
- diff --git a/libpurple/protocols/jabber/Makefile.am b/libpurple/protocols/jabber/Makefile.am
- --- a/libpurple/protocols/jabber/Makefile.am
- +++ b/libpurple/protocols/jabber/Makefile.am
- @@ -39,6 +39,8 @@
- google/google_roster.h \
- google/google_session.c \
- google/google_session.h \
- + google/google_share.c \
- + google/google_share.h \
- google/jingleinfo.c \
- google/jingleinfo.h \
- google/relay.c \
- @@ -115,8 +117,8 @@
- libjabber_la_SOURCES = $(JABBERSOURCES)
- libjabber_la_LIBADD = $(GLIB_LIBS) $(SASL_LIBS) $(LIBXML_LIBS) $(IDN_LIBS)\
- $(FARSTREAM_LIBS) \
- - $(GSTREAMER_LIBS)
- -
- + $(GSTREAMER_LIBS) \
- + $(LIBNICE_LIBS)
- libfacebook_la_SOURCES = libfacebook.c
- libfacebook_la_LIBADD = libjabber.la
- @@ -134,6 +136,7 @@
- $(DEBUG_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(IDN_CFLAGS) \
- + $(LIBNICE_CFLAGS) \
- $(LIBXML_CFLAGS) \
- $(FARSTREAM_CFLAGS) \
- $(GSTREAMER_CFLAGS)
- diff --git a/libpurple/protocols/jabber/caps.c b/libpurple/protocols/jabber/caps.c
- --- a/libpurple/protocols/jabber/caps.c
- +++ b/libpurple/protocols/jabber/caps.c
- @@ -359,8 +359,14 @@
- for (i = 0; exts[i]; ++i) {
- /* Hack since we advertise the ext along with v1.5 caps but don't
- * store any exts */
- - if (g_str_equal(exts[i], "voice-v1") && !info->exts)
- + if (g_str_equal(exts[i], "voice-v1") && !info->exts) {
- + purple_debug_info("caps","voice-v1 detected.");
- continue;
- + }
- + if (g_str_equal(exts[i], "share-v1") && !info->exts) {
- + purple_debug_info("caps","share-v1 detected.");
- + continue;
- + }
- if (!info->exts ||
- !g_hash_table_lookup(info->exts->exts, exts[i]))
- return FALSE;
- diff --git a/libpurple/protocols/jabber/disco.c b/libpurple/protocols/jabber/disco.c
- --- a/libpurple/protocols/jabber/disco.c
- +++ b/libpurple/protocols/jabber/disco.c
- @@ -142,6 +142,10 @@
- purple_xmlnode_set_attrib(feature, "var", feat->namespace);
- }
- }
- + } else if (g_str_equal(node, CAPS0115_NODE "#" "share-v1")) {
- +
- + PurpleXmlNode *feature = purple_xmlnode_new_child(query, "feature");
- + purple_xmlnode_set_attrib(feature, "var", NS_GOOGLE_SHARE);
- #ifdef USE_VV
- } else if (g_str_equal(node, CAPS0115_NODE "#" "voice-v1")) {
- /*
- diff --git a/libpurple/protocols/jabber/google/google_session.c b/libpurple/protocols/jabber/google/google_session.c
- --- a/libpurple/protocols/jabber/google/google_session.c
- +++ b/libpurple/protocols/jabber/google/google_session.c
- @@ -24,6 +24,7 @@
- #include "relay.h"
- #include "jingle/jingle.h"
- +#include <nice/agent.h>
- #ifdef USE_VV
- @@ -45,21 +46,93 @@
- return !strcmp(c->id, d->id) && !strcmp(c->initiator, d->initiator);
- }
- -static void
- +void
- google_session_destroy(GoogleSession *session)
- {
- - GoogleAVSessionData *session_data =
- - (GoogleAVSessionData *) session->session_data;
- + JabberStream *js = session->js;
- + session->state = TERMINATED;
- +
- + if(session->share) {
- +
- + GoogleXferSessionData *share_session = session->session_data;
- + GSList *temp = NULL;
- +
- + if(share_session->xfer) {
- + if(purple_xfer_get_status(share_session->xfer) ==
- + PURPLE_XFER_STATUS_CANCEL_REMOTE) {
- + purple_xfer_cancel_remote(share_session->xfer);
- + }
- + else if (purple_xfer_get_status(share_session->xfer)
- + != PURPLE_XFER_STATUS_CANCEL_LOCAL &&
- + purple_xfer_get_status(share_session->xfer)
- + != PURPLE_XFER_STATUS_DONE) {
- + purple_xfer_cancel_local(share_session->xfer);
- + }
- + }
- +
- + if(share_session->file_to_send)
- + fclose(share_session->file_to_send);
- +
- + share_session->xfer = NULL;
- + g_free(share_session->filename);
- + g_free(share_session->preview_url);
- + g_free(share_session->source_url);
- + g_free(share_session->file_buf);
- + g_free(share_session->channel_name);
- +
- + if(share_session->share_agent) {
- + g_signal_handlers_disconnect_by_func(
- + G_OBJECT(share_session->share_agent),
- + G_CALLBACK(cb_candidate_gathering_done),
- + session);
- +
- + g_signal_handlers_disconnect_by_func(
- + G_OBJECT(share_session->share_agent),
- + G_CALLBACK (cb_new_selected_pair), NULL);
- +
- + g_signal_handlers_disconnect_by_func(
- + G_OBJECT(share_session->share_agent),
- + G_CALLBACK (cb_nice_component_state_changed),
- + session);
- +
- + g_signal_handlers_disconnect_by_func(
- + G_OBJECT(share_session->share_agent),
- + G_CALLBACK (cb_nice_component_writable),
- + share_session);
- + g_object_unref(share_session->share_agent);
- + }
- +
- + purple_circ_buffer_destroy(share_session->buffer);
- +
- + for (temp = share_session->remote_share_candidates; temp; temp =
- + g_slist_delete_link(temp, temp)) {
- + nice_candidate_free(temp->data);
- + }
- +
- + for (temp = share_session->local_share_candidates; temp; temp =
- + g_slist_delete_link(temp, temp)) {
- + nice_candidate_free(temp->data);
- + }
- +
- + g_free(temp);
- + }
- + else { /*If it is an AV session*/
- + GoogleAVSessionData *session_data = session->session_data;
- + if (session_data->remote_audio_candidates)
- + purple_media_candidate_list_free(
- + session_data->remote_audio_candidates);
- +
- + if (session_data->remote_video_candidates)
- + purple_media_candidate_list_free(
- + session_data->remote_video_candidates);
- + }
- +
- + js->google_share_sessions = g_list_remove(js->google_share_sessions,session);
- +
- g_free(session->id.id);
- g_free(session->id.initiator);
- g_free(session->remote_jid);
- - if (session_data->remote_audio_candidates)
- - purple_media_candidate_list_free(session_data->remote_audio_candidates);
- -
- - if (session_data->remote_video_candidates)
- - purple_media_candidate_list_free(session_data->remote_video_candidates);
- -
- if (session->description)
- purple_xmlnode_free(session->description);
- @@ -67,7 +140,7 @@
- g_free(session);
- }
- -static PurpleXmlNode *
- +PurpleXmlNode *
- google_session_create_xmlnode(GoogleSession *session, const char *type)
- {
- PurpleXmlNode *node = purple_xmlnode_new("session");
- @@ -170,6 +243,7 @@
- ((GoogleAVSessionData *)session->session_data)->media;
- gboolean video =
- ((GoogleAVSessionData *)session->session_data)->video;
- + gboolean share = session->share;
- if (purple_media_codecs_ready(media, NULL) &&
- purple_media_candidates_prepared(media, NULL, NULL)) {
- gchar *me = g_strdup_printf("%s@%s/%s",
- @@ -206,7 +280,9 @@
- }
- purple_xmlnode_insert_child(iq->node, sess);
- desc = purple_xmlnode_new_child(sess, "description");
- - if (video)
- + if (share)
- + purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_SHARE);
- + else if (video)
- purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_VIDEO);
- else
- purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_PHONE);
- @@ -340,56 +416,107 @@
- return new_params;
- }
- -
- -static void
- +void
- jabber_google_relay_response_session_initiate_cb(GoogleSession *session,
- const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
- const gchar *relay_username, const gchar *relay_password)
- {
- - GParameter *params;
- - guint num_params;
- - JabberStream *js = session->js;
- - GoogleAVSessionData *session_data =
- - (GoogleAVSessionData *) session->session_data;
- + JabberStream *js = session->js;
- - session_data->media = purple_media_manager_create_media(
- + if(session->share) {
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- + gint stream_id = share_session->stream_id;
- + NiceAgent *agent = share_session->share_agent;
- +
- + purple_debug_info("Google_session", "Here\n\n\n\n");
- +
- + if(!agent) {
- +/* if(purple_xfer_get_type(share_session->xfer) == PURPLE_XFER_RECEIVE)
- + purple_xfer_request(share_session->xfer);
- +*/ /*if xfer is of type PURPLE_XFER_SEND, We've already requested it*/
- +
- + stream_id = gtalk_xfer_init_agent(session);
- + agent = share_session->share_agent;
- +
- + purple_debug_info("google_session", "share_agent created with stream id : %d!\n", stream_id);
- +
- + if(js->stun_ip) {
- + g_object_set(G_OBJECT (agent), "stun-server", js->stun_ip, NULL);
- + g_object_set(G_OBJECT (agent), "stun-server-port", js->stun_port, NULL);
- + }
- + }
- + else
- + purple_debug_info("google_session", "share_agent is already initialized!..\n");
- +
- + if (relay_ip) {
- + if (relay_udp)
- + nice_agent_set_relay_info(agent, share_session->stream_id, 1, relay_ip, relay_udp,
- + relay_username, relay_password, NICE_RELAY_TYPE_TURN_UDP);
- + if (relay_tcp)
- + nice_agent_set_relay_info(agent, share_session->stream_id, 1, relay_ip, relay_tcp,
- + relay_username, relay_password, NICE_RELAY_TYPE_TURN_TCP);
- + if (relay_ssltcp)
- + nice_agent_set_relay_info(agent, share_session->stream_id, 1, relay_ip, relay_ssltcp,
- + relay_username, relay_password, NICE_RELAY_TYPE_TURN_TLS);
- + }
- +
- + session->relay_processing = FALSE;
- +
- + if(session->session_should_die) {
- + purple_debug_info("google_session","Detected session_should_die as 1.\n");
- + google_session_destroy(session);
- + return;
- + }
- + return;
- + }
- + else {
- +
- + GParameter *params;
- + guint num_params;
- +
- + GoogleAVSessionData *session_data =
- + (GoogleAVSessionData *) session->session_data;
- +
- + session_data->media = purple_media_manager_create_media(
- purple_media_manager_get(),
- purple_connection_get_account(js->gc),
- "fsrtpconference", session->remote_jid, TRUE);
- +
- + purple_media_set_prpl_data(session_data->media, session);
- +
- + g_signal_connect_swapped(G_OBJECT(session_data->media),
- + "candidates-prepared",
- + G_CALLBACK(google_session_ready), session);
- + g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
- + G_CALLBACK(google_session_ready), session);
- + g_signal_connect(G_OBJECT(session_data->media), "state-changed",
- + G_CALLBACK(google_session_state_changed_cb), session);
- + g_signal_connect(G_OBJECT(session_data->media), "stream-info",
- + G_CALLBACK(google_session_stream_info_cb), session);
- - purple_media_set_prpl_data(session_data->media, session);
- -
- - g_signal_connect_swapped(G_OBJECT(session_data->media),
- - "candidates-prepared",
- - G_CALLBACK(google_session_ready), session);
- - g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
- - G_CALLBACK(google_session_ready), session);
- - g_signal_connect(G_OBJECT(session_data->media), "state-changed",
- - G_CALLBACK(google_session_state_changed_cb), session);
- - g_signal_connect(G_OBJECT(session_data->media), "stream-info",
- - G_CALLBACK(google_session_stream_info_cb), session);
- -
- - params =
- - jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp,
- - relay_ssltcp, relay_username, relay_password, &num_params);
- -
- - if (purple_media_add_stream(session_data->media, "google-voice",
- - session->remote_jid, PURPLE_MEDIA_AUDIO,
- - TRUE, "nice", num_params, params) == FALSE ||
- - (session_data->video && purple_media_add_stream(
- - session_data->media, "google-video",
- - session->remote_jid, PURPLE_MEDIA_VIDEO,
- - TRUE, "nice", num_params, params) == FALSE)) {
- - purple_media_error(session_data->media, "Error adding stream.");
- - purple_media_end(session_data->media, NULL, NULL);
- - } else {
- - session_data->added_streams = TRUE;
- + params =
- + jabber_google_session_get_params(js, relay_ip, relay_udp,
- + relay_tcp, relay_ssltcp,
- + relay_username, relay_password,
- + &num_params);
- +
- + if (purple_media_add_stream(session_data->media, "google-voice",
- + session->remote_jid, PURPLE_MEDIA_AUDIO,
- + TRUE, "nice", num_params, params) == FALSE ||
- + (session_data->video && purple_media_add_stream(
- + session_data->media, "google-video",
- + session->remote_jid, PURPLE_MEDIA_VIDEO,
- + TRUE, "nice", num_params, params) == FALSE)) {
- + purple_media_error(session_data->media, "Error adding stream.");
- + purple_media_end(session_data->media, NULL, NULL);
- + } else
- + session_data->added_streams = TRUE;
- +
- + g_free(params);
- }
- -
- - g_free(params);
- }
- -
- gboolean
- jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSessionType type)
- {
- @@ -568,61 +695,145 @@
- session->description = purple_xmlnode_copy(purple_xmlnode_get_child(sess, "description"));
- xmlns = purple_xmlnode_get_namespace(session->description);
- + session->share = FALSE;
- if (purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
- - session_data->video = FALSE;
- + video = FALSE;
- else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_VIDEO))
- - session_data->video = TRUE;
- + video = TRUE;
- + else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_SHARE))
- + session->share = TRUE;
- else {
- purple_debug_error("jabber", "Received initiate with "
- "invalid namespace %s.\n", xmlns);
- return FALSE;
- }
- - session_data->media = purple_media_manager_create_media(
- + if (!session->share) {
- + GoogleAVSessionData *session_data =
- + (GoogleAVSessionData *) session->session_data;
- + session_data = g_new0(GoogleAVSessionData, 1);
- +
- + session_data->video = video;
- + session_data->media = purple_media_manager_create_media(
- purple_media_manager_get(),
- purple_connection_get_account(js->gc),
- "fsrtpconference", session->remote_jid, FALSE);
- - purple_media_set_prpl_data(session_data->media, session);
- + purple_media_set_prpl_data(session_data->media, session);
- - g_signal_connect_swapped(G_OBJECT(session_data->media),
- - "candidates-prepared",
- - G_CALLBACK(google_session_ready), session);
- - g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
- - G_CALLBACK(google_session_ready), session);
- - g_signal_connect(G_OBJECT(session_data->media), "state-changed",
- - G_CALLBACK(google_session_state_changed_cb), session);
- - g_signal_connect(G_OBJECT(session_data->media), "stream-info",
- - G_CALLBACK(google_session_stream_info_cb), session);
- + g_signal_connect_swapped(G_OBJECT(session_data->media),
- + "candidates-prepared",
- + G_CALLBACK(google_session_ready), session);
- + g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
- + G_CALLBACK(google_session_ready), session);
- + g_signal_connect(G_OBJECT(session_data->media), "state-changed",
- + G_CALLBACK(google_session_state_changed_cb), session);
- + g_signal_connect(G_OBJECT(session_data->media), "stream-info",
- + G_CALLBACK(google_session_stream_info_cb), session);
- - session->iq_id = g_strdup(iq_id);
- + session->iq_id = g_strdup(iq_id);
- - if (js->google_relay_host && js->google_relay_token) {
- - jabber_google_do_relay_request(js, session,
- - jabber_google_relay_response_session_handle_initiate_cb);
- - } else {
- - jabber_google_relay_response_session_handle_initiate_cb(session, NULL,
- - 0, 0, 0, NULL, NULL);
- + if (js->google_relay_host && js->google_relay_token) {
- + jabber_google_do_relay_request(js, session,
- + jabber_google_relay_response_session_handle_initiate_cb);
- + } else {
- + jabber_google_relay_response_session_handle_initiate_cb(session, NULL,
- + 0, 0, 0, NULL, NULL);
- + }
- }
- -
- + else
- + gtalk_xfer_handle_initiate(js, session, sess, iq_id);
- +
- return TRUE;
- }
- -
- static void
- google_session_handle_candidates(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
- {
- JabberIq *result;
- GList *list = NULL, *video_list = NULL;
- - PurpleXmlNode *cand;
- + PurpleXmlNode *cand, *transport, *cand_parent;
- static int name = 0;
- char n[4];
- GoogleAVSessionData *session_data =
- (GoogleAVSessionData *) session->session_data;
- - for (cand = purple_xmlnode_get_child(sess, "candidate"); cand;
- - cand = purple_xmlnode_get_next_twin(cand)) {
- + cand_parent = sess;
- +
- + if(session->share) {
- + /* TODO : Optimize this block for SHARE only!.
- + * Multimedia is being handled elsewhere
- + */
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- + transport = purple_xmlnode_get_child(sess, "transport");
- + cand_parent = transport;
- +
- + for (cand = purple_xmlnode_get_child(cand_parent, "candidate"); cand;
- + cand = purple_xmlnode_get_next_twin(cand)) {
- + PurpleMediaCandidate *info;
- + const gchar *cname = purple_xmlnode_get_attrib(cand, "name");
- + const gchar *type = purple_xmlnode_get_attrib(cand, "type");
- + const gchar *protocol = purple_xmlnode_get_attrib(cand, "protocol");
- + const gchar *address = purple_xmlnode_get_attrib(cand, "address");
- + const gchar *port = purple_xmlnode_get_attrib(cand, "port");
- + const gchar *preference = purple_xmlnode_get_attrib(cand, "preference");
- + guint component_id;
- +
- + if (cname && type && address && port) {
- + PurpleMediaCandidateType candidate_type;
- + guint prio =
- + preference ?
- + g_ascii_strtod(preference, NULL) * 1000 :
- + 0;
- +
- + g_snprintf(n, sizeof(n), "S%d", name++);
- +
- + if (g_str_equal(type, "local"))
- + candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
- + else if (g_str_equal(type, "stun"))
- + candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX;
- + else if (g_str_equal(type, "relay"))
- + candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;
- + else
- + candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
- +
- + if (purple_strequal(cname, "rtcp") ||
- + purple_strequal(cname, "video_rtcp"))
- + component_id = PURPLE_MEDIA_COMPONENT_RTCP;
- + else
- + component_id = PURPLE_MEDIA_COMPONENT_RTP;
- +
- + info = purple_media_candidate_new(n, component_id,
- + candidate_type,
- + purple_strequal(protocol, "udp") ?
- + PURPLE_MEDIA_NETWORK_PROTOCOL_UDP :
- + PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
- + address,
- + atoi(port));
- + g_object_set(info, "username", xmlnode_get_attrib(cand, "username"),
- + "password", xmlnode_get_attrib(cand, "password"),
- + "priority", prio, NULL);
- +
- + /*It's a share session*/
- + share_session->remote_share_candidates =
- + g_slist_append(share_session->remote_share_candidates,
- + info);
- + purple_debug_info("google_session", "Added candidate to sharelist\n");
- +
- + }
- +
- + }
- + result = jabber_iq_new(js, JABBER_IQ_RESULT);
- + jabber_iq_set_id(result, iq_id);
- + xmlnode_set_attrib(result->node, "to", session->remote_jid);
- + jabber_iq_send(result);
- + return;
- + }
- +
- + for (cand = purple_xmlnode_get_child(cand_parent, "candidate"); cand;
- + cand = purple_xmlnode_get_next_twin(cand)) {
- PurpleMediaCandidate *info;
- const gchar *cname = purple_xmlnode_get_attrib(cand, "name");
- const gchar *type = purple_xmlnode_get_attrib(cand, "type");
- @@ -663,26 +874,35 @@
- g_object_set(info, "username", purple_xmlnode_get_attrib(cand, "username"),
- "password", purple_xmlnode_get_attrib(cand, "password"),
- "priority", prio, NULL);
- - if (!strncmp(cname, "video_", 6)) {
- - if (session_data->added_streams) {
- - video_list = g_list_append(video_list, info);
- +
- + if(!session->share) {
- + if (!strncmp(cname, "video_", 6)) {
- + if (session_data->added_streams) {
- + video_list = g_list_append(video_list, info);
- + } else {
- + session_data->remote_video_candidates =
- + g_list_append(session_data->remote_video_candidates,
- + info);
- + }
- } else {
- - session_data->remote_video_candidates =
- - g_list_append(session_data->remote_video_candidates,
- - info);
- - }
- - } else {
- - if (session_data->added_streams) {
- - list = g_list_append(list, info);
- - } else {
- - session_data->remote_audio_candidates =
- - g_list_append(session_data->remote_audio_candidates,
- - info);
- + if (session_data->added_streams) {
- + list = g_list_append(list, info);
- + } else {
- + session_data->remote_audio_candidates =
- + g_list_append(session_data->remote_audio_candidates,
- + info);
- + }
- }
- }
- }
- + else {
- + purple_debug_info("google_session",
- + "cname && port && address && type FAILED!\n");
- + }
- }
- + /*if session was share, list and video_list are NULL*/
- +
- if (list) {
- purple_media_add_remote_candidates(session_data->media, "google-voice",
- session->remote_jid, list);
- @@ -701,6 +921,30 @@
- }
- static void
- +google_session_handle_transport_accept(JabberStream *js, GoogleSession *session,
- + PurpleXmlNode *sess, const char *iq_id)
- +{
- + JabberIq *result_iq = jabber_iq_new(js,JABBER_IQ_RESULT);
- +
- + xmlnode_set_attrib(result_iq->node, "to", session->remote_jid);
- + jabber_iq_set_id(result_iq, iq_id);
- + jabber_iq_send(result_iq);
- + session->state = IN_PROGRESS;
- +}
- +
- +static void
- +google_session_handle_transport_info(JabberStream *js, GoogleSession *session,
- + PurpleXmlNode *sess, const char *iq_id)
- +{
- + purple_debug_info("google_session", "Inside handle_transport_info..\n");
- +
- + if(session->share)
- + gtalk_xfer_handle_candidates(js, session, sess, iq_id);
- + else
- + google_session_handle_candidates(js, session, sess, iq_id);
- +}
- +
- +static void
- google_session_handle_accept(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
- {
- PurpleXmlNode *desc_element = purple_xmlnode_get_child(sess, "description");
- @@ -778,9 +1022,31 @@
- static void
- google_session_handle_terminate(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess)
- {
- - GoogleAVSessionData *session_data =
- - (GoogleAVSessionData *) session->session_data;
- - purple_media_end(session_data->media, NULL, NULL);
- + JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
- + jabber_iq_set_id(result, iq_id);
- + purple_xmlnode_set_attrib(result->node, "to", session->remote_jid);
- + jabber_iq_send(result);
- +
- + purple_debug_info("google_session","Setting session_should_die to 1 \n");
- + session->session_should_die = 1;
- +
- + if(session->share) {
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- + share_session->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
- +
- + if(session->relay_processing)
- + return;
- +
- + session->state = TERMINATED;
- + google_session_destroy(session);
- + }
- + else {
- + GoogleAVSessionData *session_data =
- + (GoogleAVSessionData *) session->session_data;
- +
- + purple_media_end(session_data->media, NULL, NULL);
- + }
- }
- static void
- @@ -790,14 +1056,38 @@
- if (!strcmp(type, "initiate")) {
- google_session_handle_initiate(js, session, sess, iq_id);
- - } else if (!strcmp(type, "accept")) {
- - google_session_handle_accept(js, session, sess, iq_id);
- - } else if (!strcmp(type, "reject")) {
- - google_session_handle_reject(js, session, sess);
- +
- + } else if (!strcmp(type, "accept")) {
- + if(session->share)
- + gtalk_xfer_handle_accept(js, session, iq_id);
- + else
- + google_session_handle_accept(js, session, sess, iq_id);
- +
- + } else if (!strcmp(type, "info")) { /*Only useful for share sessions*/
- + gtalk_xfer_handle_info(js, session, sess, iq_id);
- +
- + } else if (!strcmp(type, "reject")) {
- + if(session->share)
- + gtalk_xfer_handle_reject(js, session, iq_id);
- + else
- + google_session_handle_reject(js, session, sess);
- +
- } else if (!strcmp(type, "terminate")) {
- - google_session_handle_terminate(js, session, sess);
- + google_session_handle_terminate(js, session, sess, iq_id);
- +
- } else if (!strcmp(type, "candidates")) {
- google_session_handle_candidates(js, session, sess, iq_id);
- +
- + } else if (!strcmp(type, "transport-accept")) {
- + google_session_handle_transport_accept(js, session, sess, iq_id);
- +
- + } else if (!strcmp(type, "transport-info")) {
- + google_session_handle_transport_info(js, session, sess, iq_id);
- +
- + }
- + else {
- + purple_debug_info("google_session",
- + "No suitable IQ Parse Handler Found..\n");
- }
- }
- @@ -808,7 +1098,7 @@
- {
- GoogleSession *session = NULL;
- GoogleSessionId id;
- -
- + GoogleAVSessionData *session_data;
- PurpleXmlNode *desc_node;
- GList *iter = NULL;
- @@ -843,11 +1133,43 @@
- google_session_parse_iq(js, session, session_node, iq_id);
- return;
- }
- + else {
- + if(js->google_share_sessions) {
- + GList *iter = js->google_share_sessions;
- + for(; iter; iter=iter->next) {
- + GoogleSession *gsession =
- + (GoogleSession *)(iter->data);
- +
- + if(!gsession) {
- + purple_debug_info
- + ("google_session",
- + "Fatal Error. gsession is NULL.\n");
- + /*TODO: Remove the exit(0) line once gtalk xfer support is complete*/
- + exit(0);
- + }
- +
- + if (google_session_id_equal(&id, &(gsession->id))) {
- + session = gsession;
- + break;
- + /*TODO: Ensure this works. Found a GoogleSession*/
- + }
- + }
- + }
- +
- + /*if session!=NULL, it's a Share Session*/
- + if(session) {
- + google_session_parse_iq(js, session,
- + session_node, iq_id);
- + return;
- + }
- + }
- /* If the session doesn't exist, this has to be an initiate message */
- if (strcmp(purple_xmlnode_get_attrib(session_node, "type"), "initiate"))
- return;
- - desc_node = purple_xmlnode_get_child(session_node, "description");
- + }
- +
- + desc_node = xmlnode_get_child(session_node, "description");
- if (!desc_node)
- return;
- session = g_new0(GoogleSession, 1);
- diff --git a/libpurple/protocols/jabber/google/google_session.h b/libpurple/protocols/jabber/google/google_session.h
- --- a/libpurple/protocols/jabber/google/google_session.h
- +++ b/libpurple/protocols/jabber/google/google_session.h
- @@ -22,6 +22,48 @@
- #define PURPLE_JABBER_GOOGLE_SESSION_H_
- #include "jabber.h"
- +#include <nice/agent.h>
- +
- +typedef enum {
- + GTALK_XFER_CHANNEL_INITIALIZED = 0,
- + GTALK_XFER_CHANNEL_HTTP_GET_NOT_SENT,
- + GTALK_XFER_CHANNEL_SENT_HTTP_GET,
- + GTALK_XFER_CHANNEL_HTTP_GET_RECEIVED,
- + GTALK_XFER_CHANNEL_HTTP_OK_SENT,
- + GTALK_XFER_CHANNEL_HTTP_SENDING,
- + GTALK_XFER_CHANNEL_HTTP_RECEIVING,
- + GTALK_XFER_CHANNEL_HTTP_TRANSFERRING,
- + GTALK_XFER_CHANNEL_HTTP_SENDING_COMPLETE,
- + GTALK_XFER_CHANNEL_HTTP_RECEIVING_COMPLETE,
- + GTALK_XFER_CHANNEL_PARSED_HTTP_RESPONSE_HEADER
- +} GoogleXferChannelState;
- +
- +typedef struct {
- + gchar *filename; /*File Details*/
- + guint64 filesize;
- + gchar *preview_url;
- + gchar *source_url;
- + PurpleXfer *xfer;
- + NiceAgent *share_agent; /*Needs to have a manifest
- + Entry for Folder Sharing: TODO*/
- + gchar *channel_name;
- + NiceComponentState agent_state;
- + PurpleCircBuffer *buffer;
- + GoogleXferChannelState channel_state;
- + gint stream_id;
- + gboolean candidates_gathered;
- + gboolean file_opened; /* Stuff for using file buffer
- + for sending Gtalk Files.. */
- + FILE *file_to_send;
- + char *file_buf;
- + int file_buf_current_size;
- + int file_buf_sent;
- +
- + GSList *remote_share_candidates; /* lists of
- + NiceCandidates */
- + GSList *local_share_candidates;
- +
- +} GoogleXferSessionData;
- typedef struct {
- char *id;
- @@ -32,7 +74,7 @@
- UNINIT,
- SENT_INITIATE,
- RECEIVED_INITIATE,
- - IN_PRORESS,
- + IN_PROGRESS,
- TERMINATED
- } GoogleSessionState;
- @@ -44,13 +86,60 @@
- char *iq_id;
- PurpleXmlNode *description; /* store incoming description through
- relay credential fetching */
- + gboolean relay_processing;
- + gboolean share; /*for indicating whether it's a
- + fileXfer session*/
- + gboolean session_should_die;
- gpointer session_data;
- } GoogleSession;
- +void
- +cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
- + gchar *lfoundation, gchar *rfoundation, gpointer user_data);
- +
- +void
- +cb_nice_component_state_changed(NiceAgent *agent,guint stream_id, guint component_id,
- + guint state, gpointer user_data);
- +
- +void
- +cb_nice_component_writable(NiceAgent *agent, guint stream_id, guint component_id,
- + gpointer user_data);
- +
- +void
- +gtalk_xfer_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *sess,
- + const char *iq_id);
- +
- +void
- +gtalk_xfer_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id);
- +void
- +gtalk_xfer_handle_info(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id);
- +void
- +gtalk_xfer_handle_accept(JabberStream *js, GoogleSession *session, const char *iq_id);
- +void
- +gtalk_xfer_handle_reject(JabberStream *js, GoogleSession *session, const char *iq_id);
- +gint
- +gtalk_xfer_init_agent(GoogleSession *session);
- +
- +void
- +jabber_google_relay_response_session_initiate_cb(GoogleSession *session, const gchar *relay_ip,
- + guint relay_udp, guint relay_tcp, guint relay_ssltcp,
- + const gchar *relay_username, const gchar *relay_password);
- +xmlnode *
- +google_session_create_xmlnode(GoogleSession *session, const char *type);
- +
- +void
- +gtalk_xfer_send(PurpleConnection *gc, const char *who, const char *file);
- +
- +void
- +cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer user_data);
- +
- gboolean jabber_google_session_initiate(JabberStream *js, const gchar *who,
- - PurpleMediaSessionType type);
- + PurpleMediaSessionType type);
- void jabber_google_session_parse(JabberStream *js, const char *from,
- - JabberIqType type, const char *iq, PurpleXmlNode *session);
- + JabberIqType type, const char *iq,
- + PurpleXmlNode *session);
- -#endif /* PURPLE_JABBER_GOOGLE_SESSION_H_ */
- \ No newline at end of file
- +void google_session_destroy(GoogleSession *session);
- +
- +#endif /* PURPLE_JABBER_GOOGLE_SESSION_H_ */
- diff --git a/libpurple/protocols/jabber/google/google_share.c b/libpurple/protocols/jabber/google/google_share.c
- new file mode 100644
- --- /dev/null
- +++ b/libpurple/protocols/jabber/google/google_share.c
- @@ -0,0 +1,1377 @@
- +/**
- + * Purple is the legal property of its developers, wohse names are too numerous
- + * to list here. Please refer to the COPYRIGHT file distributed with this
- + * source distribution.
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- + */
- +
- +#include "internal.h"
- +#include "debug.h"
- +#include "google_session.h"
- +#include "relay.h"
- +#include "jingle/jingle.h"
- +#include "jingle/transport.h"
- +#include "network.h"
- +#include "stun.h"
- +#include "media.h"
- +#include "relay.h"
- +#include <nice/agent.h>
- +
- +static char*
- +gtalk_get_temporary_url(void)
- +{
- + /*According to GTalk data, the length of temporary URL must be 44.*/
- + static int z = - 1;
- + char *temporary_url = g_malloc(45);
- + int i = 11;
- + char *alpha = "abcdefghijklmnopqrstuvwxyz";
- + char *num = "0123456789";
- + srandom(time(NULL));
- +
- + if(z==10)
- + z = 1;
- + z++;
- +
- + strcpy(temporary_url, "/temporary/");
- + for(;i<43;i++) {
- + int j=random()%2;
- +
- + if(j==0)
- + temporary_url[i] = alpha[random()%(26-z)];
- + else
- + temporary_url[i] = num[random()%(10-z)];
- + }
- + temporary_url[i]='/';
- + ++i;
- + temporary_url[i]='\0';
- +
- + return temporary_url;
- +}
- +
- +static void
- +gtalk_xfer_send_reject(PurpleXfer *xfer)
- +{
- + GoogleSession *session = (GoogleSession *) xfer->data;
- + JabberStream *js = session->js;
- + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
- + xmlnode *session_node;
- +
- + if(purple_xfer_get_type(xfer) != PURPLE_XFER_RECEIVE)
- + return;
- +
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- + session_node = xmlnode_new_child(iq->node, "session");
- + xmlnode_set_attrib(session_node, "type", "reject");
- + xmlnode_set_attrib(session_node, "id", session->id.id);
- + xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
- + xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
- + jabber_iq_send(iq);
- +}
- +
- +static void
- +gtalk_xfer_request_denied(PurpleXfer *xfer)
- +{
- + purple_debug_info("google_session", "Request denied by user..\n");
- + gtalk_xfer_send_reject(xfer);
- +}
- +
- +/* If buffer contains a line ending, 0-terminate the first line and
- + * return a pointer to the beginning of the next line. Otherwise
- + * return NULL. */
- +
- +static gchar *
- +http_read_line(gchar *buffer, guint len) {
- +
- + gchar *p = memchr(buffer, '\n', len);
- +
- + /* Looking for a CRLF basically */
- +
- + if (p != NULL) {
- + *p = 0;
- + if (p > buffer && *(p-1) == '\r')
- + *(p-1) = '\0';
- + p++;
- + }
- +
- + return p;
- +}
- +
- +static void
- +cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id,
- + guint len, gchar *buf, gpointer data)
- +{
- + GoogleXferSessionData *share_session = (GoogleXferSessionData *)data;
- + PurpleXfer *xfer = share_session->xfer;
- + gchar *curr = buf;
- +
- + if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
- + /*TODO: Maybe Add a parser to make sure it's not bad data?*/
- +
- + /*We should send back a 200 OK now*/
- +
- + int send_ret;
- + gchar *response = g_strdup_printf( "HTTP/1.1 200\r\n"
- + "Connection: Keep-Alive\r\n"
- + "Content-Length: %" G_GSIZE_FORMAT "\r\n"
- + "Content-Type: application/octet-stream\r\n\r\n",
- + xfer->size);
- +
- + share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_GET_RECEIVED;
- + send_ret = nice_agent_send(share_session->share_agent,
- + share_session->stream_id, 1,
- + strlen(response), response);
- +
- + purple_debug_info("google_session", "Sending response : %s\n", response);
- + purple_debug_info("google_session", "For sending 200 OK, send_ret is : %d\n",send_ret);
- + purple_debug_info("google_session", "Filesize is : %" G_GSIZE_FORMAT "\n", xfer->size);
- +
- + share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_OK_SENT;
- +
- + share_session->file_to_send = fopen(share_session->xfer->local_filename, "rb");
- +
- + if(share_session->agent_state == NICE_COMPONENT_STATE_READY) {
- + share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_SENDING;
- +
- + cb_nice_component_writable(share_session->share_agent, share_session->stream_id,
- + 1, share_session);
- + }
- + }
- + else if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
- + if (share_session->channel_state ==
- + GTALK_XFER_CHANNEL_SENT_HTTP_GET) {
- + gchar *tmp;
- + gsize read_len;
- +
- + do {
- + tmp = http_read_line(curr, len);
- + read_len = tmp - curr;
- +
- + purple_debug_info(
- + "google_session",
- + "HTTP response header received: %s\n", curr);
- +
- + if(curr[0] == '\0') {
- + break;
- + }
- +
- + len -= read_len;
- + curr += read_len;
- +
- + if (g_ascii_strncasecmp(curr, "HTTP/1.1", 8)) {
- + if (purple_strequal(curr + 9, "404")) {
- + /* got a 404 (file not found) stop... */
- + }
- + }
- + /* TODO: check Content-Length and other headers too? */
- +
- + } while (curr[0] != '\0' && len > 0);
- +
- + if (curr[0] == '\0') {
- + /* we found the end of the headers */
- + purple_debug_info("google_session",
- + "Headers End here..(Blank Line)\n");
- +
- + share_session->channel_state =
- + GTALK_XFER_CHANNEL_PARSED_HTTP_RESPONSE_HEADER;
- +
- + share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_RECEIVING;
- + purple_xfer_start(xfer, -1, NULL, 0);
- + }
- + /* otherwise the remaining headers would come in the next package
- + not sure if this will ever happen */
- + } else if (share_session->channel_state ==
- + GTALK_XFER_CHANNEL_HTTP_RECEIVING) {
- + static int curlen = 0;
- + /* write data to transfer */
- + curlen+=len;
- +
- +/* purple_debug_info("google-session",
- + "got %d bytes to write to transfer, CURLEN: %d\n", len, curlen);
- +*/
- + if (len <= purple_xfer_get_bytes_remaining(xfer)) {
- + purple_circ_buffer_append(share_session->buffer, curr, len);
- + purple_xfer_prpl_ready(xfer);
- + } else {
- + purple_debug_error("google-share",
- + "trying to write past end of file\n");
- +
- + if(purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_CANCEL_REMOTE &&
- + purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_CANCEL_LOCAL) {
- + purple_debug_info(
- + "google_session",
- + "Calling purple_xfer_cancel_remote from cb_nice_recv()\n");
- + purple_xfer_cancel_remote(xfer);
- + }
- + }
- + }
- + }
- +}
- +
- +static void
- +gtalk_xfer_channel_cb(JabberStream *js, const gchar *from, JabberIqType type,
- + const gchar *id, xmlnode *sess, gpointer data)
- +{
- + purple_debug_info("google_session", "GTalk responded to our channel send out!\n");
- +
- + if (type == JABBER_IQ_RESULT) {
- + GoogleSession *session = (GoogleSession *) data;
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- +
- + /* start agent */
- + nice_agent_gather_candidates(share_session->share_agent, share_session->stream_id);
- + }
- +}
- +
- +static void
- +gtalk_xfer_accept_cb(JabberStream *js, const gchar *from, JabberIqType type,
- + const gchar *id, xmlnode *sess, gpointer data)
- +{
- + GoogleSession *session = (GoogleSession *) data;
- + GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
- +
- + if (type != JABBER_IQ_RESULT) {
- + share_session->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
- + google_session_destroy(share_session->xfer->data);
- + /*TODO: Make the session terminate gracefully here. session_destroy does that,*/
- + }
- + else {
- + /*Send a channel*/
- +
- + gchar *me = g_strdup_printf("%s@%s/%s",
- + session->js->user->node,
- + session->js->user->domain,
- + session->js->user->resource);
- +
- + JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
- + xmlnode *sess = google_session_create_xmlnode(session, "info");
- + xmlnode *channel = xmlnode_new_child(sess, "channel");
- +
- + share_session->channel_name = jabber_get_next_id(session->js);
- +
- + xmlnode_set_namespace(channel, NS_GOOGLE_SESSION_SHARE);
- + xmlnode_set_attrib(channel, "name", share_session->channel_name);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- + xmlnode_set_attrib(iq->node, "from", me);
- + xmlnode_insert_child(iq->node, sess);
- + jabber_iq_set_callback(iq, gtalk_xfer_channel_cb, session);
- + jabber_iq_send(iq);
- + }
- +}
- +
- +static void
- +gtalk_xfer_send_accept(JabberStream *js, GoogleSession *session)
- +{
- + JabberIq *iq;
- + xmlnode *session_node, *description_node, *protocol_node;
- +
- + purple_debug_info("google_session", "Inside google_xfer_send__accept()\n");
- + iq = jabber_iq_new(js, JABBER_IQ_SET);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- +
- + session_node = xmlnode_new_child(iq->node, "session");
- + description_node = xmlnode_new_child(session_node, "description");
- +
- + xmlnode_set_attrib(session_node, "type", "accept");
- + xmlnode_set_attrib(session_node, "id", session->id.id);
- + xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
- + xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
- +
- + xmlnode_new_child(description_node, "manifest");
- + protocol_node = xmlnode_new_child(description_node, "protocol");
- + xmlnode_new_child(protocol_node, "http");
- +
- + xmlnode_set_namespace(description_node, NS_GOOGLE_SESSION_SHARE);
- + jabber_iq_set_callback(iq, gtalk_xfer_accept_cb, session);
- + jabber_iq_send(iq);
- +}
- +
- +static void
- +gtalk_xfer_transport_accept_cb(JabberStream *js, const gchar *from,
- + JabberIqType type, const gchar *id, xmlnode *packet, gpointer data)
- +{
- + gtalk_xfer_send_accept(js, (GoogleSession *)data);
- +}
- +
- +static void
- +gtalk_xfer_send_initiate_cb(JabberStream *js, const gchar *from, JabberIqType type,
- + const gchar *id, xmlnode *sess, gpointer data)
- +{
- + GoogleSession *session = (GoogleSession *)data;
- +
- + if(type == JABBER_IQ_ERROR) {
- + google_session_destroy(session);
- + return;
- + }
- +
- + if (js->google_relay_host && js->google_relay_token) {
- + jabber_google_do_relay_request(js, session,
- + jabber_google_relay_response_session_initiate_cb);
- + } else {
- + jabber_google_relay_response_session_initiate_cb(session, NULL, 0, 0, 0,
- + NULL, NULL);
- + }
- +
- +}
- +
- +static void
- +gtalk_xfer_send_session_initiate(PurpleXfer *xfer)
- +{
- + GoogleSession *session = xfer->data;
- + JabberStream *js = session->js;
- + JabberIq *iq;
- + xmlnode *session_node, *description_node, *file_node, *manifest_node, *transport_node;
- + xmlnode *name_node, *protocol_node, *http_node, *url_source_node, *url_preview_node;
- + gchar *me = g_strdup_printf("%s@%s/%s",
- + js->user->node,
- + js->user->domain,
- + js->user->resource);
- +
- + purple_debug_info("google_session", "Inside gtalk_xfer_send_session_initiate()\n");
- + iq = jabber_iq_new(js, JABBER_IQ_SET);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- +
- + session_node = xmlnode_new_child(iq->node, "session");
- +
- + xmlnode_set_attrib(session_node, "type", "initiate");
- + xmlnode_set_attrib(session_node, "id", session->id.id);
- +
- + xmlnode_set_attrib(session_node, "initiator", me);
- + xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
- +
- + description_node = xmlnode_new_child(session_node, "description");
- + xmlnode_set_namespace(description_node, NS_GOOGLE_SESSION_SHARE);
- +
- + manifest_node = xmlnode_new_child(description_node, "manifest");
- + file_node = xmlnode_new_child(manifest_node, "file");
- + xmlnode_set_attrib(file_node, "size", g_strdup_printf("%" G_GSIZE_FORMAT,xfer->size));
- +
- + name_node = xmlnode_new_child(file_node, "name");
- + xmlnode_insert_data(name_node,xfer->filename,strlen(xfer->filename));
- +
- + protocol_node = xmlnode_new_child(description_node, "protocol");
- + http_node = xmlnode_new_child(protocol_node, "http");
- + url_source_node = xmlnode_new_child(http_node, "url");
- + xmlnode_set_attrib(url_source_node, "name", "source-path");
- + xmlnode_insert_data(url_source_node, gtalk_get_temporary_url(), -1);
- +
- + url_preview_node = xmlnode_new_child(http_node, "url");
- + xmlnode_set_attrib(url_preview_node, "name", "preview-path");
- + xmlnode_insert_data(url_preview_node, gtalk_get_temporary_url(), -1);
- +
- + transport_node = xmlnode_new_child(session_node, "transport");
- + xmlnode_set_namespace(transport_node, NS_GOOGLE_TRANSPORT_P2P);
- +
- + jabber_iq_set_callback(iq, gtalk_xfer_send_initiate_cb, session);
- + jabber_iq_send(iq);
- + session->state = SENT_INITIATE;
- +}
- +
- +static void
- +gtalk_xfer_send_transport_accept(JabberStream *js, GoogleSession *session)
- +{
- + JabberIq *iq;
- + xmlnode *session_node, *transport_node;
- +
- + purple_debug_info("google_session", "Inside google_xfer_send_transport_accept()\n");
- + iq = jabber_iq_new(js, JABBER_IQ_SET);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- +
- + session_node = xmlnode_new_child(iq->node, "session");
- + transport_node = xmlnode_new_child(session_node, "transport");
- +
- + xmlnode_set_attrib(session_node, "type", "transport-accept");
- + xmlnode_set_attrib(session_node, "id", session->id.id);
- + xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
- + xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
- +
- + xmlnode_set_namespace(transport_node, NS_GOOGLE_TRANSPORT_P2P);
- + jabber_iq_set_callback(iq, gtalk_xfer_transport_accept_cb, session);
- + jabber_iq_send(iq);
- + session->state = IN_PROGRESS;
- +}
- +
- +static void
- +gtalk_xfer_send_terminate(PurpleXfer *xfer)
- +{
- + GoogleSession *session = (GoogleSession *) xfer->data;
- + JabberStream *js = session->js;
- + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
- + xmlnode *session_node;
- +
- + if(session->state < IN_PROGRESS) {
- + google_session_destroy(session);
- + }
- + else {
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- + session_node = xmlnode_new_child(iq->node, "session");
- + xmlnode_set_attrib(session_node, "type", "terminate");
- + xmlnode_set_attrib(session_node, "id", session->id.id);
- + xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
- + xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
- + purple_debug_info("google_session", "Sending google_s_dest as callback..Sending IQ\n");
- + jabber_iq_send(iq);
- + google_session_destroy(session);
- + }
- +}
- +
- +static void
- +gtalk_xfer_cancel_xfer(PurpleXfer *xfer)
- +{
- + GoogleSession *session = (GoogleSession *)xfer->data;
- +
- + purple_debug_info("gs", "Inside gtalk_xfer_cancel_xfer...\n");
- +
- + if(session->state == TERMINATED)
- + return;
- +
- + gtalk_xfer_send_terminate(xfer);
- +}
- +
- +static void
- +gtalk_xfer_init(PurpleXfer *xfer)
- +{
- + GoogleSession *session = (GoogleSession *)(xfer->data);
- + JabberStream *js = session->js;
- +
- + purple_debug_info("google_session", "Inside gtalk_xfer_init\n");
- +
- + js->google_share_sessions = g_list_prepend(js->google_share_sessions, session);
- +
- + if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE)
- + gtalk_xfer_send_transport_accept(js, session);
- +
- + if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
- + gtalk_xfer_send_session_initiate(xfer);
- +}
- +
- +gint
- +gtalk_xfer_init_agent(GoogleSession *session)
- +{
- + gint stream_id;
- + NiceAgent *agent;
- + GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
- +
- + purple_debug_info("google_session", "Inside gtalk_xfer_init_agent\n");
- + if(!share_session)
- + return -1;
- +
- + if(share_session->share_agent)
- + return share_session->stream_id;
- +
- + agent = share_session->share_agent;
- +
- + agent = nice_agent_new_reliable (g_main_context_default(), NICE_COMPATIBILITY_GOOGLE);
- + stream_id = nice_agent_add_stream(agent, 1);
- + share_session->share_agent = agent;
- +
- + nice_agent_attach_recv (share_session->share_agent, stream_id, 1, g_main_context_default(),
- + cb_nice_recv, share_session);
- +
- + g_signal_connect (G_OBJECT (share_session->share_agent), "candidate-gathering-done",
- + G_CALLBACK (cb_candidate_gathering_done), session);
- +
- + g_signal_connect (G_OBJECT (share_session->share_agent), "new-selected-pair",
- + G_CALLBACK (cb_new_selected_pair), NULL);
- +
- + g_signal_connect (G_OBJECT (share_session->share_agent), "component-state-changed",
- + G_CALLBACK (cb_nice_component_state_changed), session);
- +
- + g_signal_connect (G_OBJECT (share_session->share_agent), "reliable-transport-writable",
- + G_CALLBACK (cb_nice_component_writable), share_session);
- +
- + share_session->share_agent = agent;
- + share_session->stream_id = stream_id;
- + return stream_id;
- +}
- +
- +
- +void
- +gtalk_xfer_handle_info(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
- +{
- + JabberIq *iq;
- + xmlnode *channel = xmlnode_get_child(sess, "channel");
- + xmlnode *complete = xmlnode_get_child(sess, "complete");
- + GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
- +
- + purple_debug_info("google_session", "Inside gtalk_xfer_handle_info\n");
- +
- + if(complete) {
- + iq = jabber_iq_new(js, JABBER_IQ_RESULT);
- + jabber_iq_set_id(iq, iq_id);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- + jabber_iq_send(iq);
- + /*Maybe this call to session_destroy shouldn't occur and we should trigger the destroy when
- + GTalk sends us the terminate message,(which ideally should be immediately following
- + the "complete" message), but that would be depending on Google Talk for killing
- + this session. Need to resolve this and this comment should go away ASAP. TODO*/
- + google_session_destroy(session);
- + return;
- + }
- +
- + if(channel)
- + share_session->channel_name = g_strdup(xmlnode_get_attrib(channel, "name"));
- +
- + iq = jabber_iq_new(js, JABBER_IQ_RESULT);
- + jabber_iq_set_id(iq, iq_id);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- + jabber_iq_send(iq);
- +
- + purple_debug_info("google_session", "Starting candidate cathering with nice agent..\n");
- +
- + nice_agent_gather_candidates(share_session->share_agent, share_session->stream_id);
- +}
- +
- +
- +static NiceCandidate *
- +nice_candidate_from_xml(const xmlnode *candidate,
- + guint stream_id)
- +{
- + NiceCandidate *cand = NULL;
- + const gchar *name = xmlnode_get_attrib(candidate, "name");
- + const gchar *type = xmlnode_get_attrib(candidate, "type");
- + const gchar *address = xmlnode_get_attrib(candidate, "address");
- + guint port = atoi(xmlnode_get_attrib(candidate, "port"));
- + const gchar *preference = xmlnode_get_attrib(candidate, "preference");
- +
- + if (name && type && address && port != 0) {
- + guint prio = preference ? g_ascii_strtod(preference, NULL) * 1000 : 0;
- + cand = nice_candidate_new(purple_strequal(type, "host") ?
- + NICE_CANDIDATE_TYPE_HOST :
- + purple_strequal(type, "stun") ? NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE :
- + purple_strequal(type, "relay") ? NICE_CANDIDATE_TYPE_RELAYED :
- + NICE_CANDIDATE_TYPE_HOST);
- +
- + nice_address_init(&cand->addr);
- +
- + if (!nice_address_set_from_string(&cand->addr, address)) {
- + purple_debug_error("google_session",
- + "Invalid NiceAddress in NiceCandidate.\n");
- + nice_candidate_free(cand);
- + return NULL;
- + }
- +
- + nice_address_set_port(&cand->addr, port);
- + cand->priority = prio;
- + cand->stream_id = stream_id;
- + cand->username = g_strdup(xmlnode_get_attrib(candidate, "username"));
- + cand->password = g_strdup(xmlnode_get_attrib(candidate, "password"));
- + } else {
- + purple_debug_error("google_session", "received invalid candidate!\n");
- + }
- +
- + return cand;
- +}
- +
- +void
- +gtalk_xfer_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
- +{
- + GSList *candidate_list = NULL;
- + xmlnode *candidate_node, *transport_node;
- + GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
- + JabberIq *result;
- + transport_node = NULL;
- +
- + purple_debug_info("google_session", "Inside gtalk_xfer_handle_candidates..\n");
- +
- + /*Sending IQ_RESULT first and then processing the candidate*/
- +/*Modifying this to handle multiple candidates inside a single transport message*/
- +
- + if(sess)
- + transport_node = xmlnode_get_child(sess, "transport");
- +
- + if(transport_node) {
- +
- + for (candidate_node = xmlnode_get_child(transport_node, "candidate");
- + candidate_node; candidate_node = xmlnode_get_next_twin(candidate_node)) {
- + NiceCandidate *cand =
- + nice_candidate_from_xml(candidate_node,
- + share_session->stream_id);
- +
- + if (cand) {
- + candidate_list = g_slist_append(candidate_list, cand);
- + }
- + }
- +
- + if (share_session->candidates_gathered) {
- + nice_agent_set_remote_candidates(share_session->share_agent, share_session->stream_id,
- + 1, candidate_list);
- + while(candidate_list) {
- + NiceCandidate *c = (NiceCandidate *) candidate_list->data;
- + nice_candidate_free(c);
- + candidate_list = g_slist_delete_link(candidate_list, candidate_list);
- + }
- +
- + } else {
- + share_session->remote_share_candidates =
- + g_slist_concat(share_session->remote_share_candidates, candidate_list);
- + }
- + }
- + purple_debug_info("google_session", "Added remote candidate to Nice Agent!.\n");
- +
- + result = jabber_iq_new(js, JABBER_IQ_RESULT);
- + jabber_iq_set_id(result, iq_id);
- + xmlnode_set_attrib(result->node, "to", session->remote_jid);
- + jabber_iq_send(result);
- +}
- +
- +void
- +gtalk_xfer_handle_accept(JabberStream *js, GoogleSession *session, const char *iq_id)
- +{
- + JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
- + jabber_iq_set_id(result, iq_id);
- + xmlnode_set_attrib(result->node, "to", session->remote_jid);
- + jabber_iq_send(result);
- +}
- +
- +
- +void
- +gtalk_xfer_handle_reject(JabberStream *js, GoogleSession *session, const char *iq_id)
- +{
- + GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
- + JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
- + jabber_iq_set_id(result, iq_id);
- + xmlnode_set_attrib(result->node, "to", session->remote_jid);
- + jabber_iq_send(result);
- +
- + purple_debug_info("google_session", "The remote user Rejected the Xfer request..\n");
- +
- + share_session->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
- + session->state = TERMINATED;
- + google_session_destroy(session);
- +}
- +
- +/*TODO: NEVER USED??*/
- +static void
- +gtalk_xfer_send_candidates(GoogleSession *session)
- +{
- + GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
- + GSList *candidates = share_session->local_share_candidates;
- + GSList *iter;
- + purple_debug_info("google_session", "inside gtalk_xfer_send_candidates()\n");
- +
- + for(iter = candidates; iter; iter = iter->next) {
- + JabberIq *iq;
- + gchar *ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
- + gchar *port;
- + gchar *username, *password;
- + xmlnode *sess;
- + xmlnode *candidate, *transport;
- + NiceCandidate *nice_candid = (NiceCandidate *)iter->data;
- + NiceCandidateType type;
- +
- + iq = jabber_iq_new(session->js, JABBER_IQ_SET);
- + sess = google_session_create_xmlnode(session, "transport-info");
- + xmlnode_insert_child(iq->node, sess);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- +
- + transport = xmlnode_new("transport");
- + xmlnode_set_namespace(transport, NS_GOOGLE_TRANSPORT_P2P);
- + xmlnode_insert_child(sess, transport);
- +
- + candidate = xmlnode_new("candidate");
- +
- + nice_address_to_string(&nice_candid->addr, ip);
- + port = g_strdup_printf("%u",nice_address_get_port(&nice_candid->addr));
- +
- + purple_debug_info("google_session", "IP and port : %s:%s\n",ip,port);
- +
- + type = nice_candid->type;
- +
- + xmlnode_set_attrib(candidate, "address", ip);
- + xmlnode_set_attrib(candidate, "port", port);
- + xmlnode_set_attrib(candidate, "name", "private-1");
- +
- + username = g_strdup(nice_candid->username);
- + password = g_strdup(nice_candid->password);
- +
- + xmlnode_set_attrib(candidate, "username", username != NULL ? username : "");
- +/*TODO: Fix preference*/
- + xmlnode_set_attrib(candidate, "preference", type == NICE_CANDIDATE_TYPE_HOST ? "0.000015":
- + "0.000000");
- +
- + xmlnode_set_attrib(candidate, "protocol", "udp");
- + /*CHECK THIS : TODO Type*/
- +
- + xmlnode_set_attrib(candidate, "type",
- + type == NICE_CANDIDATE_TYPE_HOST ? "local":
- + type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ? "stun":
- + type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE ? "prflx":
- + type == NICE_CANDIDATE_TYPE_RELAYED ? "relay"
- + : "local");
- +
- + if(type == NICE_CANDIDATE_TYPE_RELAYED) {
- + if(nice_candid->turn) {
- + gchar *turn_ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
- + nice_address_to_string(&nice_candid->turn->server, turn_ip);
- + purple_debug_info("google_session", "turn IP for NiceCandidate: %s\n", turn_ip);
- + }
- + else
- + purple_debug_info("google_session", "TURN is NULL for candidate..\n");
- + }
- +
- +
- + xmlnode_set_attrib(candidate, "generation", "0");
- + xmlnode_set_attrib(candidate, "network", "0");
- + xmlnode_insert_child(transport, candidate);
- +
- + g_free(ip);
- + g_free(port);
- + g_free(username);
- + g_free(password);
- + jabber_iq_send(iq);
- + }
- +}
- +
- +/*Thanks for this, malu :D*/
- +static xmlnode *
- +nice_candidate_to_xml(const NiceCandidate *cand,
- + GoogleXferSessionData *share_session)
- +{
- + xmlnode *candidate = xmlnode_new("candidate");
- + gchar address[NICE_ADDRESS_STRING_LEN];
- + gchar pref[16];
- + gchar *local_ufrag, *local_password;
- +
- + nice_address_to_string(&cand->addr, address);
- + xmlnode_set_attrib(candidate, "address", address);
- + xmlnode_set_attrib(candidate, "port",
- + g_strdup_printf("%d", nice_address_get_port(&cand->addr)));
- + xmlnode_set_attrib(candidate, "name", share_session->channel_name);
- +
- + if(!cand->username) {
- + nice_agent_get_local_credentials(share_session->share_agent,
- + share_session->stream_id,
- + &local_ufrag, &local_password);
- + xmlnode_set_attrib(candidate, "username", local_ufrag);
- + }
- + else
- + xmlnode_set_attrib(candidate, "username", cand->username);
- +
- + xmlnode_set_attrib(candidate, "password",
- + cand->password != NULL ? cand->password : "");
- + g_ascii_dtostr(pref, 16, cand->priority / 1000.0);
- + xmlnode_set_attrib(candidate, "preference", pref);
- + xmlnode_set_attrib(candidate, "protocol",
- + cand->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "udp" : "tcp");
- + xmlnode_set_attrib(candidate, "type",
- + cand->type == NICE_CANDIDATE_TYPE_HOST ? "host" :
- + cand->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ? "stun" :
- + cand->type == NICE_CANDIDATE_TYPE_RELAYED ? "relay" : "host");
- + xmlnode_set_attrib(candidate, "generation", "0");
- + xmlnode_set_attrib(candidate, "network", "0");
- +
- + return candidate;
- +}
- +
- +void
- +cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer user_data)
- +{
- + GoogleSession *session = (GoogleSession *)user_data;
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- + GSList *local_candidates = nice_agent_get_local_candidates(agent, stream_id, 1);
- +
- + purple_debug_info("google_session", "candidate gathering done!\n");
- + share_session->candidates_gathered = TRUE;
- +
- + /* add remote candidates received while gathering local candidates */
- + nice_agent_set_remote_candidates(agent, share_session->stream_id, 1,
- + share_session->remote_share_candidates);
- +
- +
- + while (share_session->remote_share_candidates) {
- + NiceCandidate *c =
- + (NiceCandidate *) share_session->remote_share_candidates->data;
- + nice_candidate_free(c);
- + share_session->remote_share_candidates =
- + g_slist_delete_link(share_session->remote_share_candidates,
- + share_session->remote_share_candidates);
- + }
- +
- + /* Time to send local candidates. */
- + if (local_candidates) {
- + NiceCandidate *candidate = (NiceCandidate *) local_candidates->data;
- + JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
- + gchar *me = g_strdup_printf("%s@%s/%s",
- + session->js->user->node,
- + session->js->user->domain,
- + session->js->user->resource);
- +
- + /*Preparing the xml nodes for sending out candidates to gtalk*/
- + xmlnode *sess = google_session_create_xmlnode(session, "transport-info");
- + xmlnode *transport = xmlnode_new_child(sess, "transport");
- +
- + xmlnode_insert_child(transport, nice_candidate_to_xml(candidate, share_session));
- + xmlnode_set_namespace(transport, NS_GOOGLE_TRANSPORT_P2P);
- +
- + xmlnode_insert_child(iq->node, sess);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- + xmlnode_set_attrib(iq->node, "from", me);
- + jabber_iq_send(iq);
- +
- + nice_candidate_free(candidate);
- + local_candidates = g_slist_delete_link(local_candidates, local_candidates);
- + }
- +}
- +
- +static void
- +gtalk_xfer_end(PurpleXfer *xfer)
- +{
- + GoogleSession *session = (GoogleSession *) xfer->data;
- + JabberStream *js = session->js;
- + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
- + xmlnode *complete_node, *session_node;
- +
- + if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- + session_node = xmlnode_new_child(iq->node, "session");
- + xmlnode_set_attrib(session_node, "type", "info");
- + xmlnode_set_attrib(session_node, "id", session->id.id);
- + xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
- + xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
- +
- + complete_node = xmlnode_new_child(session_node, "complete");
- + xmlnode_set_namespace(complete_node, NS_GOOGLE_SESSION_SHARE);
- + jabber_iq_send(iq);
- +
- + gtalk_xfer_send_terminate(xfer);
- + }
- + else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
- + purple_debug_info("google_session", "XFER_SEND Ended..in gtalk_xfer_end\n");
- + }
- +}
- +
- +
- +static gssize
- +gtalk_xfer_read(guchar **out_buffer, PurpleXfer *xfer)
- +{
- + GoogleSession *session = (GoogleSession *) xfer->data;
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- +
- + guchar *buffer;
- + gsize size;
- + gsize tmp;
- +
- + size = share_session->buffer->bufused;
- +
- + *out_buffer = buffer = g_malloc(size);
- + while ((tmp = purple_circ_buffer_get_max_read(share_session->buffer))) {
- + memcpy(buffer, share_session->buffer->outptr, tmp);
- + buffer += tmp;
- + purple_circ_buffer_mark_read(share_session->buffer, tmp);
- + }
- +
- + return size;
- +}
- +
- +static char *
- +nice_component_state_to_str(guint state)
- +{
- + switch(state) {
- +
- + case NICE_COMPONENT_STATE_DISCONNECTED : return "NICE_COMPONENT_STATE_DISCONNECTED";
- +
- + case NICE_COMPONENT_STATE_GATHERING : return "NICE_COMPONENT_STATE_GATHERING";
- +
- + case NICE_COMPONENT_STATE_CONNECTING : return "NICE_COMPONENT_STATE_CONNECTING";
- +
- + case NICE_COMPONENT_STATE_CONNECTED : return "NICE_COMPONENT_STATE_CONNECTED";
- +
- + case NICE_COMPONENT_STATE_READY : return "NICE_COMPONENT_STATE_READY";
- +
- + case NICE_COMPONENT_STATE_FAILED : return "NICE_COMPONENT_STATE_FAILED";
- +
- + case NICE_COMPONENT_STATE_LAST : return "NICE_COMPONENT_STATE_LAST";
- +
- + default: return "UNKOWN STATE";
- + }
- +}
- +
- +void cb_nice_component_state_changed(NiceAgent *agent,guint stream_id,
- + guint component_id,
- + guint state, gpointer user_data)
- +{
- + GoogleSession *session = (GoogleSession *)user_data;
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- + GSList *remote_candids =
- + nice_agent_get_remote_candidates(agent, stream_id, component_id);
- + GSList *local_candids =
- + nice_agent_get_local_candidates(agent, stream_id, component_id);
- + NiceCandidate *rcand, *lcand;
- + gchar *temp = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
- + gboolean selected_pair;
- +
- + share_session->agent_state = state;
- +
- + purple_debug_info("google_session",
- + "State of NiceAgent Changed : [%d]%s.Stream ID: %d\n",
- + state, nice_component_state_to_str(state), stream_id);
- +
- + if(state != NICE_COMPONENT_STATE_READY) {
- + return;
- + }
- +
- + selected_pair = nice_agent_get_selected_pair(share_session->share_agent,
- + share_session->stream_id, 1,
- + &lcand, &rcand);
- + if(selected_pair) {
- + purple_debug_info("google_session", "Selected Candidates : n");
- + nice_address_to_string(&lcand->addr, temp);
- + purple_debug_info("google_session", "LOCAL CAND : IP: %s, Port:%u\n"
- + ,temp, nice_address_get_port(&lcand->addr));
- + nice_address_to_string(&rcand->addr, temp);
- + purple_debug_info("google_session", "REMOTE CAN : IP: %s, Port:%u\n",
- + temp, nice_address_get_port(&rcand->addr));
- + }
- + else
- + purple_debug_info("google_session", "GETTING selected pair failed..\n");
- +
- + g_free(temp);
- +
- + purple_debug_info("google_session", "List of remote candidates : \n");
- +
- + while(remote_candids) {
- + gchar *ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
- + NiceCandidate *c = (NiceCandidate *)remote_candids->data;
- + nice_address_to_string(&c->addr, ip);
- +
- + purple_debug_info("google_session", "IP: %s, Port:%u\n",
- + ip, nice_address_get_port(&c->addr));
- + remote_candids = remote_candids->next;
- + }
- + purple_debug_info("google_session", "***********\n");
- +
- + purple_debug_info("google_session", "List of local candidates : \n");
- + while(local_candids) {
- + gchar *ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
- + NiceCandidate *c = (NiceCandidate *)local_candids->data;
- + nice_address_to_string(&c->addr, ip);
- +
- + purple_debug_info("google_session", "IP: %s, Port:%u\n",
- + ip, nice_address_get_port(&c->addr));
- + local_candids = local_candids->next;
- + }
- + purple_debug_info("google_session", "***********\n");
- +
- +
- + if(purple_xfer_get_type(share_session->xfer) == PURPLE_XFER_SEND &&
- + share_session->channel_state == GTALK_XFER_CHANNEL_HTTP_OK_SENT) {
- + share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_SENDING;
- + cb_nice_component_writable(share_session->share_agent,
- + share_session->stream_id,
- + 1, share_session);
- + }
- +
- + if(state == NICE_COMPONENT_STATE_READY &&
- + purple_xfer_get_type(share_session->xfer) == PURPLE_XFER_RECEIVE) {
- +
- + gint send_ret;
- + gchar *raw_filename = purple_strreplace(share_session->filename,
- + " ","%20");
- + gchar *url = g_strdup_printf("%s%s", share_session->source_url,
- + raw_filename);
- + gchar *request = g_strdup_printf("GET %s HTTP/1.1\r\n"
- + "Connection: Keep-Alive\r\n"
- + "Content-Length: 0\r\n"
- + "Host: %s:0\r\n"
- + "User-Agent: %s\r\n\r\n",
- + url, session->remote_jid,
- + "Google Talk");
- +
- + purple_debug_info("google_session", "READY!\n");
- +
- + send_ret = nice_agent_send(share_session->share_agent,
- + share_session->stream_id, 1,
- + strlen(request), request);
- +
- + if(send_ret > 0) {
- + share_session->channel_state = GTALK_XFER_CHANNEL_SENT_HTTP_GET;
- + purple_debug_info("google_session",
- + "send_ret is %d, \nRequest is : \n%s\n",
- + send_ret, request);
- + }
- + else {
- + share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_GET_NOT_SENT;
- + purple_debug_info("google_session",
- + "GET Request not sent. Waiting for writable.\n");
- + }
- +
- + }
- +}
- +
- +static void
- +gtalk_xfer_get_next_block(GoogleXferSessionData *share_session)
- +{
- + int fread_ret;
- +
- + if(!share_session)
- + return;
- +
- + share_session->file_buf = malloc(1200);
- + fread_ret = fread(share_session->file_buf, 1, 1200, share_session->file_to_send);
- + share_session->file_buf_current_size = fread_ret;
- + share_session->file_buf_sent = 0;
- +}
- +
- +void cb_nice_component_writable(NiceAgent *agent, guint stream_id,
- + guint component_id, gpointer user_data)
- +{
- + GoogleXferSessionData *share_session = (GoogleXferSessionData *)user_data;
- + PurpleXfer *xfer = share_session->xfer;
- +
- + char *file_buf = share_session->file_buf;
- + int send_ret;
- +
- + if(share_session->channel_state == GTALK_XFER_CHANNEL_HTTP_GET_NOT_SENT) {
- + gint send_ret;
- + GoogleSession *session = (GoogleSession *)xfer->data;
- + gchar *raw_filename = purple_strreplace(share_session->filename,
- + " ","%20");
- + gchar *url = g_strdup_printf("%s%s",
- + share_session->source_url,
- + raw_filename);
- +
- + gchar *request = g_strdup_printf("GET %s HTTP/1.1\r\n"
- + "Connection: Keep-Alive\r\n"
- + "Content-Length: 0\r\n"
- + "Host: %s:0\r\n"
- + "User-Agent: %s\r\n\r\n",
- + url, session->remote_jid,
- + "Google Talk");
- +
- + send_ret = nice_agent_send(share_session->share_agent,
- + share_session->stream_id, 1,
- + strlen(request), request);
- + purple_debug_info("google_session", "send_ret is %d, \nRequest is : \n%s\n",
- + send_ret, request);
- +
- + if(send_ret > 0) { /*Considering this to be successful. Maybe add a check for response?*/
- + share_session->channel_state = GTALK_XFER_CHANNEL_SENT_HTTP_GET;
- + purple_debug_info("google_session",
- + "Request is : %s with length %" G_GSIZE_FORMAT "\n",
- + request, strlen(request));
- + }
- + else {
- + share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_GET_NOT_SENT;
- + purple_debug_info("google_session",
- + "GET Request not sent. Will wait for writable.\n");
- + }
- + }
- +
- + if(share_session->channel_state == GTALK_XFER_CHANNEL_HTTP_SENDING) {
- + if(share_session->file_buf == NULL) { /*This means that we should read the buffer*/
- + gtalk_xfer_get_next_block(share_session);
- + file_buf = share_session->file_buf;
- + }
- +
- + while (1) {
- +
- + send_ret = nice_agent_send(share_session->share_agent,
- + share_session->stream_id, 1,
- + share_session->file_buf_current_size -
- + share_session->file_buf_sent,
- + file_buf+share_session->file_buf_sent);
- +
- + if(send_ret<=0) {
- + break;
- + }
- + else { //proper send_ret value
- + xfer->bytes_sent += send_ret;
- + xfer->bytes_remaining -= send_ret;
- + purple_xfer_update_progress(xfer);
- + share_session->file_buf_sent += send_ret;
- + }
- +
- + if(purple_xfer_get_bytes_remaining(xfer) <= 0) {
- + purple_debug_info("google_session",
- + "File Successfully sent to GTalk!\n");
- + purple_xfer_set_completed(xfer, 1);
- + return;
- + }
- +
- + /*The following is equivalent to checking if send_ret is less
- + *than the no of bytes we wanted to send..
- + */
- + if(share_session->file_buf_current_size != share_session->file_buf_sent)
- + break;
- +
- + if(share_session->file_buf_sent >= share_session->file_buf_current_size) {
- + free(file_buf);
- + share_session->file_buf = NULL;
- + share_session->file_buf_sent = 0;
- + share_session-> file_buf_current_size = 0;
- + gtalk_xfer_get_next_block(share_session);
- + file_buf = share_session->file_buf;
- + }
- + }
- + }
- +}
- +
- +void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
- + gchar *lfoundation, gchar *rfoundation, gpointer user_data)
- +{
- + purple_debug_info("google_session",
- + "Got a new selected pair with foundations : %s:%s\n",
- + lfoundation,
- + rfoundation);
- +}
- +
- +static void
- +gtalk_xfer_start(PurpleXfer *xfer)
- +{
- + purple_debug_info("google_session", "Inside gtalk_xfer_start()\n");
- +
- + if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
- + guchar *buffer = g_malloc( xfer->bytes_remaining );
- + int wrote = purple_xfer_write( xfer, buffer, xfer->bytes_remaining );
- +
- + if ( wrote > 0 )
- + purple_xfer_set_bytes_sent( xfer, wrote );
- +
- + /* free the buffer */
- + g_free( buffer );
- + buffer = NULL;
- + }
- +}
- +
- +static GoogleSession *
- +gtalk_xfer_new_session(JabberStream *js, const char *who)
- +{
- + GoogleSession *session = g_new0(GoogleSession, 1);
- + GoogleXferSessionData *share_session = g_new0(GoogleXferSessionData, 1);
- + gchar *me = g_strdup_printf("%s@%s/%s",
- + js->user->node,
- + js->user->domain,
- + js->user->resource);
- +
- +
- + JabberBuddy *jb = jabber_buddy_find(js, who, FALSE);
- + JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, NULL);
- + gchar *jid;
- +
- + if (!jbr) {
- + purple_debug_error("google_session",
- + "Could not find buddy's resource\n");
- + }
- +
- + if ((strchr(who, '/') == NULL) && jbr && (jbr->name != NULL)) {
- + jid = g_strdup_printf("%s/%s", who, jbr->name);
- + } else {
- + jid = g_strdup(who);
- + }
- +
- + share_session->buffer = purple_circ_buffer_new(65536);
- + session->id.id = jabber_get_next_id(js);
- + session->id.initiator = me;
- + session->share = 1;
- + session->session_data = share_session;
- +
- + session->state = UNINIT; /*TODO: Add similar state changes in the
- + code for GoogleSession*/
- + session->js = js;
- + session->remote_jid = g_strdup(jid);
- +
- + return session;
- +}
- +
- +void
- +gtalk_xfer_send(PurpleConnection *gc, const char *who, const char *file)
- +{
- + PurpleXfer *xfer = NULL;
- + JabberStream *js = purple_connection_get_protocol_data(gc);
- +
- + purple_debug_info("google_session", "INSIDE GTALK_XFER_SEND\n");
- +
- + if (file) {
- + purple_debug_info("google_session", "file is not NULL, %s\n", file);
- + purple_xfer_request_accepted(xfer, file);
- + }
- + else {
- + GoogleSession *session = gtalk_xfer_new_session(js, who);
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- + session->state = SENT_INITIATE;
- +
- + purple_debug_info("google_session", "File is NULL!\n");
- + session->share = TRUE;
- +
- + xfer = purple_xfer_new(purple_connection_get_account(gc),
- + PURPLE_XFER_SEND,
- + session->remote_jid);
- + js->gtalk_xfer_list = g_list_prepend(js->gtalk_xfer_list,
- + share_session->xfer);
- +
- + /*Setting up Stuff for XFER_SEND*/
- + purple_xfer_set_init_fnc(xfer, gtalk_xfer_init);
- + purple_xfer_set_request_denied_fnc(xfer,
- + gtalk_xfer_request_denied);
- + purple_xfer_set_cancel_send_fnc(xfer, gtalk_xfer_cancel_xfer);
- +/* purple_xfer_set_write_fnc(xfer, gtalk_xfer_write);*/
- +
- + xfer->data = session;
- + share_session->xfer = xfer;
- + purple_debug_info("google_session","xfer status : %d\n",
- + purple_xfer_get_status(xfer));
- +
- + xfer->status = PURPLE_XFER_STATUS_NOT_STARTED;
- + purple_xfer_request(xfer);
- + }
- +
- +}
- +
- +static void
- +gtalk_xfer_send_info(JabberStream *js, GoogleSession *session, xmlnode *sess)
- +{
- +
- + JabberIq *iq;
- + xmlnode *session_node, *channel_node;
- +
- + purple_debug_info("google_session", "Inside google_xfer_send__accept\n");
- + iq = jabber_iq_new(js, JABBER_IQ_SET);
- + xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- +
- + session_node = xmlnode_new_child(iq->node, "session");
- + xmlnode_set_attrib(session_node, "type", "info");
- + xmlnode_set_attrib(session_node, "id", xmlnode_get_attrib(sess, "id"));
- + xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
- + xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
- +
- + channel_node = xmlnode_new_child(session_node, "channel");
- + xmlnode_set_attrib(channel_node, "name", "private-1");
- + xmlnode_set_namespace(channel_node, NS_GOOGLE_SESSION_SHARE);
- +
- + jabber_iq_send(iq);
- +}
- +
- +void
- +gtalk_xfer_handle_initiate(JabberStream *js, GoogleSession *session,
- + xmlnode *sess, const char *iq_id)
- +{
- + GoogleXferSessionData *share_session =
- + (GoogleXferSessionData *)session->session_data;
- + xmlnode *description = xmlnode_get_child(sess, "description");
- + xmlnode *manifest,*file,*filename = NULL,*protocol,*http;
- + xmlnode *url_source_path,*url_preview_path,*transport;
- + guint filesize = 0;
- + JabberIq *result;
- +
- + share_session = g_new0(GoogleXferSessionData, 1);
- +
- + if( description ) {
- + manifest = xmlnode_get_child(description, "manifest");
- + if( manifest ) {
- + file = xmlnode_get_child(manifest, "file");
- + if( file ) {
- + filename = xmlnode_get_child(file,
- + "name");
- + filesize = atoi(xmlnode_get_attrib(file,
- + "size"));
- + purple_debug_info("google_session",
- + "File size : %d",filesize);
- + share_session->filesize =
- + g_ascii_strtoull(
- + (gchar *)xmlnode_get_attrib(file, "size"),
- + NULL,10);
- + if( filename ) {
- + purple_debug_info("google_session",
- + "Filename : %s",
- + xmlnode_get_data_unescaped(filename));
- +
- + share_session->filename =
- + xmlnode_get_data_unescaped(filename);
- + }
- + else
- + purple_debug_info("google_session",
- + "Filename is NULL");
- + }
- + }
- +
- + protocol = xmlnode_get_child(description, "protocol");
- + if( protocol ) {
- + http = xmlnode_get_child(protocol, "http");
- + if( http ) {
- + url_source_path = xmlnode_get_child(http, "url");
- + if( url_source_path ) {
- + purple_debug_info(
- + "google_session",
- + "url_source_path is not NULL. Name : %s",
- + xmlnode_get_data_unescaped(url_source_path));
- +
- + share_session->source_url =
- + xmlnode_get_data_unescaped(url_source_path);
- + }
- + url_preview_path = xmlnode_get_next_twin(url_source_path);
- + if(url_preview_path) {
- + purple_debug_info(
- + "google_session",
- + "url_source_preview is not NULL. Data : %s",
- + xmlnode_get_data_unescaped(url_preview_path));
- +
- + share_session->preview_url =
- + xmlnode_get_data_unescaped(url_preview_path);
- + }
- + }
- + }
- +
- + transport = xmlnode_get_child(sess, "transport");
- + }
- + /*Add the GoogleSession *session to the GList*/
- +
- + share_session->xfer = purple_xfer_new(purple_connection_get_account(js->gc),
- + PURPLE_XFER_RECEIVE,
- + session->remote_jid);
- +
- + js->gtalk_xfer_list = g_list_prepend(js->gtalk_xfer_list,
- + share_session->xfer);
- +
- + if(filename)
- + purple_xfer_set_filename(share_session->xfer,
- + xmlnode_get_data_unescaped(filename));
- +
- + purple_xfer_set_size(share_session->xfer, filesize);
- + /*Setting up stuff for XFER_RECEIVE*/
- + purple_xfer_set_init_fnc(share_session->xfer, gtalk_xfer_init);
- + purple_xfer_set_request_denied_fnc(share_session->xfer,
- + gtalk_xfer_request_denied);
- + purple_xfer_set_cancel_recv_fnc(share_session->xfer,
- + gtalk_xfer_cancel_xfer);
- + purple_xfer_set_read_fnc(share_session->xfer, gtalk_xfer_read);
- + purple_xfer_set_end_fnc(share_session->xfer, gtalk_xfer_end);
- +
- + share_session->xfer->data = session;
- + share_session->buffer = purple_circ_buffer_new(65536);
- +
- + session->session_data = share_session;
- +
- + result = jabber_iq_new(js,JABBER_IQ_RESULT);
- + xmlnode_set_attrib(result->node, "to", session->remote_jid);
- + jabber_iq_set_id(result, iq_id);
- + jabber_iq_send(result);
- +
- + if (js->google_relay_host && js->google_relay_token) {
- + jabber_google_do_relay_request(js, session,
- + jabber_google_relay_response_session_initiate_cb);
- + } else {
- + jabber_google_relay_response_session_initiate_cb(session, NULL, 0, 0, 0,
- + NULL, NULL);
- + }
- + /*Ask the user to accept the file transfer*/
- + purple_xfer_request(share_session->xfer);
- + session->state = RECEIVED_INITIATE;
- +}
- diff --git a/libpurple/protocols/jabber/google/relay.c b/libpurple/protocols/jabber/google/relay.c
- --- a/libpurple/protocols/jabber/google/relay.c
- +++ b/libpurple/protocols/jabber/google/relay.c
- @@ -104,6 +104,7 @@
- {
- PurpleHttpRequest *req;
- JabberGoogleRelayCallbackData *data = g_new0(JabberGoogleRelayCallbackData, 1);
- + session->relay_processing = TRUE;
- data->session = session;
- data->cb = cb;
- diff --git a/libpurple/protocols/jabber/iq.c b/libpurple/protocols/jabber/iq.c
- --- a/libpurple/protocols/jabber/iq.c
- +++ b/libpurple/protocols/jabber/iq.c
- @@ -572,10 +572,8 @@
- jabber_roster_parse);
- jabber_iq_register_handler("query", "jabber:iq:version",
- jabber_iq_version_parse);
- -#ifdef USE_VV
- jabber_iq_register_handler("session", NS_GOOGLE_SESSION,
- jabber_google_session_parse);
- -#endif
- jabber_iq_register_handler("block", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
- jabber_iq_register_handler("unblock", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
- jabber_iq_register_handler("time", NS_ENTITY_TIME, jabber_time_parse);
- diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
- --- a/libpurple/protocols/jabber/jabber.c
- +++ b/libpurple/protocols/jabber/jabber.c
- @@ -669,7 +669,7 @@
- else {
- gchar *tmp;
- if (len == 0)
- - tmp = g_strdup(_("Server closed the connection"));
- + tmp = g_strdup_printf(_("Server closed the connection"));
- else
- tmp = g_strdup_printf(_("Lost connection with server: %s"),
- g_strerror(errno));
- @@ -727,7 +727,7 @@
- } else {
- gchar *tmp;
- if (len == 0)
- - tmp = g_strdup(_("Server closed the connection"));
- + tmp = g_strdup_printf(_("Server closed the connection"));
- else
- tmp = g_strdup_printf(_("Lost connection with server: %s"),
- g_strerror(errno));
- @@ -3536,7 +3536,11 @@
- when actually trying */
- if (jb == NULL)
- return TRUE;
- -
- + /* If the client on the other side is GoogleTalk, js->googletalk will be TRUE
- + We know for a fact it can receive file, so return TRUE
- + */
- + if (js->googletalk)
- + return TRUE;
- /* find out if there is any resources without caps */
- for (iter = jb->resources; iter ; iter = g_list_next(iter)) {
- JabberBuddyResource *jbr = (JabberBuddyResource *) iter->data;
- @@ -3887,7 +3891,13 @@
- /* Jingle features! */
- jabber_add_feature(JINGLE, 0);
- -
- + jabber_add_feature(JINGLE_APP_FT, 0);
- + jabber_add_feature(JINGLE_TRANSPORT_S5B, 0);
- + jabber_add_feature(JINGLE_TRANSPORT_IBB, 0);
- +
- + /* Google Talk File Transfer*/
- + jabber_add_feature(NS_GOOGLE_SHARE,0);
- +
- #ifdef USE_VV
- jabber_add_feature(NS_GOOGLE_PROTOCOL_SESSION, jabber_audio_enabled);
- jabber_add_feature(NS_GOOGLE_VOICE, jabber_audio_enabled);
- diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h
- --- a/libpurple/protocols/jabber/jabber.h
- +++ b/libpurple/protocols/jabber/jabber.h
- @@ -198,6 +198,9 @@
- JabberCapabilities server_caps;
- gboolean googletalk;
- + GList *google_share_sessions;
- + GList *gtalk_xfer_list;
- +
- char *server_name;
- char *gmail_last_time;
- diff --git a/libpurple/protocols/jabber/namespaces.h b/libpurple/protocols/jabber/namespaces.h
- --- a/libpurple/protocols/jabber/namespaces.h
- +++ b/libpurple/protocols/jabber/namespaces.h
- @@ -99,6 +99,7 @@
- #define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
- #define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
- #define NS_GOOGLE_VOICE "http://www.google.com/xmpp/protocol/voice/v1"
- +#define NS_GOOGLE_SHARE "http://www.google.com/xmpp/protocol/share/v1"
- #define NS_GOOGLE_JINGLE_INFO "google:jingleinfo"
- #define NS_GOOGLE_MAIL_NOTIFY "google:mail:notify"
- @@ -108,7 +109,7 @@
- #define NS_GOOGLE_SESSION "http://www.google.com/session"
- #define NS_GOOGLE_SESSION_PHONE "http://www.google.com/session/phone"
- #define NS_GOOGLE_SESSION_VIDEO "http://www.google.com/session/video"
- -
- +#define NS_GOOGLE_SESSION_SHARE "http://www.google.com/session/share"
- #define NS_GOOGLE_TRANSPORT_P2P "http://www.google.com/transport/p2p"
- /* Apple extension(s) */
- diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c
- --- a/libpurple/protocols/jabber/presence.c
- +++ b/libpurple/protocols/jabber/presence.c
- @@ -353,6 +353,7 @@
- purple_xmlnode_set_attrib(c, "hash", "sha-1");
- purple_xmlnode_set_attrib(c, "ver", jabber_caps_get_own_hash(js));
- + purple_xmlnode_set_attrib(c, "ext", "share-v1");
- #ifdef USE_VV
- /*
- * MASSIVE HUGE DISGUSTING HACK
- @@ -363,16 +364,18 @@
- * calls.
- *
- * Ditto for 'video-v1'.
- + *
- + * Ditto for 'share-v1' for supporting file transfers.
- */
- audio_enabled = jabber_audio_enabled(js, NULL /* unused */);
- video_enabled = jabber_video_enabled(js, NULL /* unused */);
- if (audio_enabled && video_enabled)
- - purple_xmlnode_set_attrib(c, "ext", "voice-v1 camera-v1 video-v1");
- + purple_xmlnode_set_attrib(c, "ext", "voice-v1 camera-v1 video-v1 share-v1");
- else if (audio_enabled)
- - purple_xmlnode_set_attrib(c, "ext", "voice-v1");
- + purple_xmlnode_set_attrib(c, "ext", "voice-v1 share-v1");
- else if (video_enabled)
- - purple_xmlnode_set_attrib(c, "ext", "camera-v1 video-v1");
- + purple_xmlnode_set_attrib(c, "ext", "camera-v1 video-v1 share-v1");
- #endif
- return presence;
- diff --git a/libpurple/protocols/jabber/si.c b/libpurple/protocols/jabber/si.c
- --- a/libpurple/protocols/jabber/si.c
- +++ b/libpurple/protocols/jabber/si.c
- @@ -38,6 +38,7 @@
- #include "ibb.h"
- #include "iq.h"
- #include "si.h"
- +#include "google/google_session.h"
- #define STREAMHOST_CONNECT_TIMEOUT 15
- #define ENABLE_FT_THUMBNAILS 0
- @@ -1654,6 +1655,16 @@
- void jabber_si_xfer_send(PurpleConnection *gc, const char *who, const char *file)
- {
- PurpleXfer *xfer;
- + JabberStream *js = purple_connection_get_protocol_data(gc);
- +
- + if(js->googletalk) {
- + purple_debug_info("jabber", "Found Google Talk. Try to Send File Now..");
- + /*TODO: Rename the gtalk_xfer_send function most probably ALSO, isn't file always NULL for googletalk?*/
- + gtalk_xfer_send(gc, who, file);
- + return;
- + }
- + else
- + purple_debug_info("Jabber", "Not Google Talk..Something is Broken..\n");
- xfer = jabber_si_new_xfer(gc, who);
- diff --git a/libpurple/protocols/yahoo/yahoo_filexfer.c b/libpurple/protocols/yahoo/yahoo_filexfer.c
- --- a/libpurple/protocols/yahoo/yahoo_filexfer.c
- +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c
- @@ -482,10 +482,10 @@
- {
- gchar *ans;
- int i,j;
- - ans = g_strnfill(24, ' ');
- - ans[23] = '$';
- - ans[22] = '$';
- - for(i = 0; i < 22; i++)
- + ans = g_strnfill(44, ' ');
- + ans[43] = '=';
- +
- + for(i = 0; i < 43; i++)
- {
- j = g_random_int_range (0,61);
- if(j < 26)
- diff --git a/libpurple/xfer.c b/libpurple/xfer.c
- --- a/libpurple/xfer.c
- +++ b/libpurple/xfer.c
- @@ -1586,7 +1586,8 @@
- return;
- }
- - purple_debug_misc("xfer", "Prpl (and UI) ready on ft %p, so proceeding\n", xfer);
- + /*purple_debug_misc("xfer", "Prpl (and UI) ready on ft %p, so proceeding\n", xfer);*/
- + /*Commented out as this gives many messages while transferring a file from Gtalk to pidgin*/
- priv->ready = PURPLE_XFER_READY_NONE;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement