Advertisement
tomkiewicz

soc-ft-diff

Feb 2nd, 2014
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 90.78 KB | None | 0 0
  1. comparing with ../main/
  2. searching for changes
  3. diff --git a/.hgignore b/.hgignore
  4. --- a/.hgignore
  5. +++ b/.hgignore
  6. @@ -122,3 +122,5 @@
  7.  stamp-h1
  8.  test-driver
  9.  win32-install-dir(\.release)?
  10. +\#.*\#
  11. +test-driver
  12. diff --git a/configure.ac b/configure.ac
  13. --- a/configure.ac
  14. +++ b/configure.ac
  15. @@ -1029,6 +1029,25 @@
  16.  AM_CONDITIONAL(USE_VV, test "x$enable_vv" != "xno")
  17.  
  18.  dnl #######################################################################
  19. +dnl # Check for libnice
  20. +dnl #######################################################################
  21. +PKG_CHECK_MODULES(LIBNICE, nice, , [
  22. +   AC_MSG_RESULT(no)
  23. +   enable_libnice="no"
  24. +   if test "x$force_deps" = "xyes" ; then
  25. +       AC_MSG_ERROR([
  26. +libnice development headers not found.
  27. +Use --disable-libnice if you do not need it.
  28. +])
  29. +   fi])
  30. +if test "x$enable_libnice" = "xyes" ; then
  31. +   AC_DEFINE(USE_LIBNICE, 1, [Define if we're using libnice])
  32. +   AC_SUBST(LIBNICE_CFLAGS)
  33. +   AC_SUBST(LIBNICE_LIBS)
  34. +fi
  35. +
  36. +
  37. +dnl #######################################################################
  38.  dnl # Check for Internationalized Domain Name support
  39.  dnl #######################################################################
  40.  
  41. diff --git a/libpurple/protocols/jabber/Makefile.am b/libpurple/protocols/jabber/Makefile.am
  42. --- a/libpurple/protocols/jabber/Makefile.am
  43. +++ b/libpurple/protocols/jabber/Makefile.am
  44. @@ -39,6 +39,8 @@
  45.               google/google_roster.h \
  46.               google/google_session.c \
  47.               google/google_session.h \
  48. +             google/google_share.c \
  49. +             google/google_share.h \
  50.               google/jingleinfo.c \
  51.               google/jingleinfo.h \
  52.               google/relay.c \
  53. @@ -115,8 +117,8 @@
  54.  libjabber_la_SOURCES = $(JABBERSOURCES)
  55.  libjabber_la_LIBADD  = $(GLIB_LIBS) $(SASL_LIBS) $(LIBXML_LIBS) $(IDN_LIBS)\
  56.     $(FARSTREAM_LIBS) \
  57. -   $(GSTREAMER_LIBS)
  58. -
  59. +   $(GSTREAMER_LIBS) \
  60. +   $(LIBNICE_LIBS)
  61.  libfacebook_la_SOURCES = libfacebook.c
  62.  libfacebook_la_LIBADD = libjabber.la
  63.  
  64. @@ -134,6 +136,7 @@
  65.     $(DEBUG_CFLAGS) \
  66.     $(GLIB_CFLAGS) \
  67.     $(IDN_CFLAGS) \
  68. +   $(LIBNICE_CFLAGS) \
  69.     $(LIBXML_CFLAGS) \
  70.     $(FARSTREAM_CFLAGS) \
  71.     $(GSTREAMER_CFLAGS)
  72. diff --git a/libpurple/protocols/jabber/caps.c b/libpurple/protocols/jabber/caps.c
  73. --- a/libpurple/protocols/jabber/caps.c
  74. +++ b/libpurple/protocols/jabber/caps.c
  75. @@ -359,8 +359,14 @@
  76.     for (i = 0; exts[i]; ++i) {
  77.         /* Hack since we advertise the ext along with v1.5 caps but don't
  78.          * store any exts */
  79. -       if (g_str_equal(exts[i], "voice-v1") && !info->exts)
  80. +       if (g_str_equal(exts[i], "voice-v1") && !info->exts) {
  81. +           purple_debug_info("caps","voice-v1 detected.");
  82.             continue;
  83. +       }
  84. +       if (g_str_equal(exts[i], "share-v1") && !info->exts) {
  85. +           purple_debug_info("caps","share-v1 detected.");
  86. +           continue;
  87. +       }
  88.         if (!info->exts ||
  89.                 !g_hash_table_lookup(info->exts->exts, exts[i]))
  90.             return FALSE;
  91. diff --git a/libpurple/protocols/jabber/disco.c b/libpurple/protocols/jabber/disco.c
  92. --- a/libpurple/protocols/jabber/disco.c
  93. +++ b/libpurple/protocols/jabber/disco.c
  94. @@ -142,6 +142,10 @@
  95.                     purple_xmlnode_set_attrib(feature, "var", feat->namespace);
  96.                 }
  97.             }
  98. +       } else if (g_str_equal(node, CAPS0115_NODE "#" "share-v1")) {
  99. +        
  100. +           xmlnode *feature = xmlnode_new_child(query, "feature");
  101. +           xmlnode_set_attrib(feature, "var", NS_GOOGLE_SHARE);
  102.  #ifdef USE_VV
  103.         } else if (g_str_equal(node, CAPS0115_NODE "#" "voice-v1")) {
  104.             /*
  105. diff --git a/libpurple/protocols/jabber/google/google_session.c b/libpurple/protocols/jabber/google/google_session.c
  106. --- a/libpurple/protocols/jabber/google/google_session.c
  107. +++ b/libpurple/protocols/jabber/google/google_session.c
  108. @@ -22,8 +22,8 @@
  109.  #include "debug.h"
  110.  #include "google_session.h"
  111.  #include "relay.h"
  112. -
  113.  #include "jingle/jingle.h"
  114. +#include <nice/agent.h>
  115.  
  116.  #ifdef USE_VV
  117.  
  118. @@ -32,8 +32,10 @@
  119.     gboolean video;
  120.     GList *remote_audio_candidates; /* list of PurpleMediaCandidate */
  121.     GList *remote_video_candidates; /* list of PurpleMediaCandidate */
  122. -   gboolean added_streams;     /* this indicates if the streams have been
  123. -                                  to media (ie. after getting relay credentials */
  124. +   gboolean added_streams;     /* this indicates if the streams have
  125. +                    * been to media (ie. after getting
  126. +                    * relay credentials
  127. +                    */
  128.  } GoogleAVSessionData;
  129.  
  130.  static gboolean
  131. @@ -45,21 +47,93 @@
  132.     return !strcmp(c->id, d->id) && !strcmp(c->initiator, d->initiator);
  133.  }
  134.  
  135. -static void
  136. +void
  137.  google_session_destroy(GoogleSession *session)
  138.  {
  139. -   GoogleAVSessionData *session_data =
  140. -       (GoogleAVSessionData *) session->session_data;
  141. +   JabberStream *js = session->js;
  142. +   session->state = TERMINATED;           
  143. +  
  144. +   if(session->share) {
  145. +    
  146. +       GoogleXferSessionData *share_session = session->session_data;
  147. +       GSList *temp = NULL;
  148. +      
  149. +       if(share_session->xfer) {
  150. +           if(purple_xfer_get_status(share_session->xfer) ==
  151. +              PURPLE_XFER_STATUS_CANCEL_REMOTE) {
  152. +             purple_xfer_cancel_remote(share_session->xfer);
  153. +           }
  154. +           else if (purple_xfer_get_status(share_session->xfer)
  155. +                != PURPLE_XFER_STATUS_CANCEL_LOCAL &&
  156. +                purple_xfer_get_status(share_session->xfer)
  157. +                != PURPLE_XFER_STATUS_DONE) {             
  158. +             purple_xfer_cancel_local(share_session->xfer);
  159. +           }
  160. +       }
  161. +      
  162. +       if(share_session->file_to_send)
  163. +         fclose(share_session->file_to_send);
  164. +
  165. +       share_session->xfer = NULL;
  166. +       g_free(share_session->filename);
  167. +       g_free(share_session->preview_url);
  168. +       g_free(share_session->source_url);
  169. +       g_free(share_session->file_buf);
  170. +       g_free(share_session->channel_name);
  171. +
  172. +       if(share_session->share_agent) {
  173. +           g_signal_handlers_disconnect_by_func(
  174. +               G_OBJECT(share_session->share_agent),
  175. +               G_CALLBACK(cb_candidate_gathering_done),
  176. +               session);
  177. +          
  178. +           g_signal_handlers_disconnect_by_func(
  179. +               G_OBJECT(share_session->share_agent),
  180. +               G_CALLBACK (cb_new_selected_pair), NULL);
  181. +          
  182. +           g_signal_handlers_disconnect_by_func(
  183. +               G_OBJECT(share_session->share_agent),
  184. +               G_CALLBACK (cb_nice_component_state_changed),
  185. +               session);
  186. +          
  187. +           g_signal_handlers_disconnect_by_func(
  188. +               G_OBJECT(share_session->share_agent),
  189. +               G_CALLBACK (cb_nice_component_writable),
  190. +               share_session);      
  191. +           g_object_unref(share_session->share_agent);
  192. +       }
  193. +      
  194. +       purple_circ_buffer_destroy(share_session->buffer);
  195. +      
  196. +       for (temp = share_session->remote_share_candidates; temp; temp =
  197. +                g_slist_delete_link(temp, temp)) {
  198. +           nice_candidate_free(temp->data);
  199. +       }
  200. +      
  201. +       for (temp = share_session->local_share_candidates; temp; temp =
  202. +                g_slist_delete_link(temp, temp)) {
  203. +           nice_candidate_free(temp->data);
  204. +       }
  205. +      
  206. +       g_free(temp);      
  207. +   }
  208. +   else { /*If it is an AV session*/
  209. +       GoogleAVSessionData *session_data = session->session_data;
  210. +       if (session_data->remote_audio_candidates)
  211. +           purple_media_candidate_list_free(
  212. +               session_data->remote_audio_candidates);
  213. +      
  214. +       if (session_data->remote_video_candidates)
  215. +           purple_media_candidate_list_free(
  216. +               session_data->remote_video_candidates);
  217. +   }
  218. +  
  219. +   js->google_share_sessions = g_list_remove(js->google_share_sessions,session);
  220. +
  221.     g_free(session->id.id);
  222.     g_free(session->id.initiator);
  223.     g_free(session->remote_jid);
  224.  
  225. -   if (session_data->remote_audio_candidates)
  226. -       purple_media_candidate_list_free(session_data->remote_audio_candidates);
  227. -
  228. -   if (session_data->remote_video_candidates)
  229. -       purple_media_candidate_list_free(session_data->remote_video_candidates);
  230. -
  231.     if (session->description)
  232.         purple_xmlnode_free(session->description);
  233.  
  234. @@ -67,7 +141,7 @@
  235.     g_free(session);
  236.  }
  237.  
  238. -static PurpleXmlNode *
  239. +PurpleXmlNode *
  240.  google_session_create_xmlnode(GoogleSession *session, const char *type)
  241.  {
  242.     PurpleXmlNode *node = purple_xmlnode_new("session");
  243. @@ -170,6 +244,9 @@
  244.         ((GoogleAVSessionData *)session->session_data)->media;
  245.     gboolean video =
  246.         ((GoogleAVSessionData *)session->session_data)->video;
  247. +
  248. +   gboolean share = session->share;       
  249. +
  250.     if (purple_media_codecs_ready(media, NULL) &&
  251.             purple_media_candidates_prepared(media, NULL, NULL)) {
  252.         gchar *me = g_strdup_printf("%s@%s/%s",
  253. @@ -206,7 +283,10 @@
  254.         }
  255.         purple_xmlnode_insert_child(iq->node, sess);
  256.         desc = purple_xmlnode_new_child(sess, "description");
  257. -       if (video)
  258. +
  259. +       if (share)
  260. +           purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_SHARE);                       
  261. +       else if (video)
  262.             purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_VIDEO);
  263.         else
  264.             purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_PHONE);
  265. @@ -340,56 +420,109 @@
  266.     return new_params;
  267.  }
  268.  
  269. -
  270. -static void
  271. +void
  272.  jabber_google_relay_response_session_initiate_cb(GoogleSession *session,
  273.      const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
  274.      const gchar *relay_username, const gchar *relay_password)
  275.  {
  276. -   GParameter *params;
  277. -   guint num_params;
  278.     JabberStream *js = session->js;
  279. -   GoogleAVSessionData *session_data =
  280. -       (GoogleAVSessionData *) session->session_data;
  281. +  
  282. +   purple_debug_info("google_session", "Inside jabber_google_relay_response_initiate_cb!\n");
  283.  
  284. -   session_data->media = purple_media_manager_create_media(
  285. +   if(session->share) {       
  286. +       GoogleXferSessionData *share_session =
  287. +           (GoogleXferSessionData *)session->session_data;    
  288. +       gint stream_id = share_session->stream_id;
  289. +       NiceAgent *agent = share_session->share_agent;
  290. +
  291. +       purple_debug_info("Google_session", "Here\n\n\n\n");
  292. +
  293. +       if(!agent) {
  294. +/*         if(purple_xfer_get_type(share_session->xfer) == PURPLE_XFER_RECEIVE)
  295. +               purple_xfer_request(share_session->xfer);
  296. +*/         /*if xfer is of type PURPLE_XFER_SEND, We've already requested it*/
  297. +
  298. +           stream_id = gtalk_xfer_init_agent(session);
  299. +           agent = share_session->share_agent;
  300. +
  301. +           purple_debug_info("google_session", "share_agent created with stream id : %d!\n", stream_id);
  302. +
  303. +           if(js->stun_ip) {
  304. +               g_object_set(G_OBJECT (agent), "stun-server", js->stun_ip, NULL);
  305. +               g_object_set(G_OBJECT (agent), "stun-server-port", js->stun_port, NULL);
  306. +           }
  307. +       }
  308. +       else
  309. +           purple_debug_info("google_session", "share_agent is already initialized!..\n");    
  310. +
  311. +       if (relay_ip) {
  312. +           if (relay_udp)
  313. +               nice_agent_set_relay_info(agent, share_session->stream_id, 1, relay_ip, relay_udp,
  314. +                             relay_username, relay_password, NICE_RELAY_TYPE_TURN_UDP);
  315. +           if (relay_tcp)
  316. +               nice_agent_set_relay_info(agent, share_session->stream_id, 1, relay_ip, relay_tcp,
  317. +                             relay_username, relay_password, NICE_RELAY_TYPE_TURN_TCP);
  318. +           if (relay_ssltcp)
  319. +               nice_agent_set_relay_info(agent, share_session->stream_id, 1, relay_ip, relay_ssltcp,
  320. +                             relay_username, relay_password, NICE_RELAY_TYPE_TURN_TLS);
  321. +       }
  322. +      
  323. +       session->relay_processing = FALSE;
  324. +
  325. +       if(session->session_should_die) {
  326. +         purple_debug_info("google_session","Detected session_should_die as 1.\n");
  327. +         google_session_destroy(session);
  328. +         return;
  329. +       }
  330. +       return;
  331. +   }
  332. +   else {
  333. +      
  334. +       GParameter *params;
  335. +       guint num_params;
  336. +      
  337. +       GoogleAVSessionData *session_data =
  338. +           (GoogleAVSessionData *) session->session_data;
  339. +      
  340. +       session_data->media = purple_media_manager_create_media(
  341.             purple_media_manager_get(),
  342.             purple_connection_get_account(js->gc),
  343.             "fsrtpconference", session->remote_jid, TRUE);
  344. +      
  345. +       purple_media_set_prpl_data(session_data->media, session);
  346. +      
  347. +       g_signal_connect_swapped(G_OBJECT(session_data->media),
  348. +                    "candidates-prepared",
  349. +                    G_CALLBACK(google_session_ready), session);
  350. +       g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
  351. +                    G_CALLBACK(google_session_ready), session);
  352. +       g_signal_connect(G_OBJECT(session_data->media), "state-changed",
  353. +                G_CALLBACK(google_session_state_changed_cb), session);
  354. +       g_signal_connect(G_OBJECT(session_data->media), "stream-info",
  355. +                G_CALLBACK(google_session_stream_info_cb), session);
  356.  
  357. -   purple_media_set_prpl_data(session_data->media, session);
  358. -
  359. -   g_signal_connect_swapped(G_OBJECT(session_data->media),
  360. -           "candidates-prepared",
  361. -           G_CALLBACK(google_session_ready), session);
  362. -   g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
  363. -           G_CALLBACK(google_session_ready), session);
  364. -   g_signal_connect(G_OBJECT(session_data->media), "state-changed",
  365. -           G_CALLBACK(google_session_state_changed_cb), session);
  366. -   g_signal_connect(G_OBJECT(session_data->media), "stream-info",
  367. -           G_CALLBACK(google_session_stream_info_cb), session);
  368. -
  369. -   params =
  370. -       jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp,
  371. -           relay_ssltcp, relay_username, relay_password, &num_params);
  372. -
  373. -   if (purple_media_add_stream(session_data->media, "google-voice",
  374. -           session->remote_jid, PURPLE_MEDIA_AUDIO,
  375. -           TRUE, "nice", num_params, params) == FALSE ||
  376. -           (session_data->video && purple_media_add_stream(
  377. -           session_data->media, "google-video",
  378. -           session->remote_jid, PURPLE_MEDIA_VIDEO,
  379. -           TRUE, "nice", num_params, params) == FALSE)) {
  380. -       purple_media_error(session_data->media, "Error adding stream.");
  381. -       purple_media_end(session_data->media, NULL, NULL);
  382. -   } else {
  383. -       session_data->added_streams = TRUE;
  384. +       params =
  385. +           jabber_google_session_get_params(js, relay_ip, relay_udp,
  386. +                            relay_tcp, relay_ssltcp,
  387. +                            relay_username, relay_password,
  388. +                            &num_params);
  389. +      
  390. +       if (purple_media_add_stream(session_data->media, "google-voice",
  391. +                       session->remote_jid, PURPLE_MEDIA_AUDIO,
  392. +                       TRUE, "nice", num_params, params) == FALSE ||
  393. +           (session_data->video && purple_media_add_stream(
  394. +               session_data->media, "google-video",
  395. +               session->remote_jid, PURPLE_MEDIA_VIDEO,
  396. +               TRUE, "nice", num_params, params) == FALSE)) {
  397. +           purple_media_error(session_data->media, "Error adding stream.");
  398. +           purple_media_end(session_data->media, NULL, NULL);
  399. +       } else
  400. +           session_data->added_streams = TRUE;    
  401. +      
  402. +       g_free(params);
  403.     }
  404. -
  405. -   g_free(params);
  406.  }
  407.  
  408. -
  409.  gboolean
  410.  jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSessionType type)
  411.  {
  412. @@ -442,7 +575,7 @@
  413.     }
  414.  
  415.     /* we don't actually know yet wether it succeeded... maybe this is very
  416. -    wrong... */
  417. +      wrong... */
  418.     return TRUE;
  419.  }
  420.  
  421. @@ -568,61 +701,145 @@
  422.  
  423.     session->description = purple_xmlnode_copy(purple_xmlnode_get_child(sess, "description"));
  424.     xmlns = purple_xmlnode_get_namespace(session->description);
  425. +   session->share = FALSE;
  426.  
  427.     if (purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
  428. -       session_data->video = FALSE;
  429. +       video = FALSE;
  430.     else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_VIDEO))
  431. -       session_data->video = TRUE;
  432. +       video = TRUE;
  433. +   else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_SHARE))
  434. +       session->share = TRUE;
  435.     else {
  436.         purple_debug_error("jabber", "Received initiate with "
  437.                 "invalid namespace %s.\n", xmlns);
  438.         return FALSE;
  439.     }
  440.  
  441. -   session_data->media = purple_media_manager_create_media(
  442. +   if (!session->share) {
  443. +       GoogleAVSessionData *session_data =
  444. +           (GoogleAVSessionData *) session->session_data;
  445. +       session_data = g_new0(GoogleAVSessionData, 1);
  446. +      
  447. +       session_data->video = video;
  448. +       session_data->media = purple_media_manager_create_media(
  449.             purple_media_manager_get(),
  450.             purple_connection_get_account(js->gc),
  451.             "fsrtpconference", session->remote_jid, FALSE);
  452.  
  453. -   purple_media_set_prpl_data(session_data->media, session);
  454. +       purple_media_set_prpl_data(session_data->media, session);
  455.  
  456. -   g_signal_connect_swapped(G_OBJECT(session_data->media),
  457. -           "candidates-prepared",
  458. -           G_CALLBACK(google_session_ready), session);
  459. -   g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
  460. -           G_CALLBACK(google_session_ready), session);
  461. -   g_signal_connect(G_OBJECT(session_data->media), "state-changed",
  462. -           G_CALLBACK(google_session_state_changed_cb), session);
  463. -   g_signal_connect(G_OBJECT(session_data->media), "stream-info",
  464. -           G_CALLBACK(google_session_stream_info_cb), session);
  465. +       g_signal_connect_swapped(G_OBJECT(session_data->media),
  466. +                    "candidates-prepared",
  467. +                    G_CALLBACK(google_session_ready), session);
  468. +       g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
  469. +                    G_CALLBACK(google_session_ready), session);
  470. +       g_signal_connect(G_OBJECT(session_data->media), "state-changed",
  471. +                G_CALLBACK(google_session_state_changed_cb), session);
  472. +       g_signal_connect(G_OBJECT(session_data->media), "stream-info",
  473. +                G_CALLBACK(google_session_stream_info_cb), session);
  474.  
  475. -   session->iq_id = g_strdup(iq_id);
  476. +       session->iq_id = g_strdup(iq_id);
  477.  
  478. -   if (js->google_relay_host && js->google_relay_token) {
  479. -       jabber_google_do_relay_request(js, session,
  480. -           jabber_google_relay_response_session_handle_initiate_cb);
  481. -   } else {
  482. -       jabber_google_relay_response_session_handle_initiate_cb(session, NULL,
  483. -           0, 0, 0, NULL, NULL);
  484. +       if (js->google_relay_host && js->google_relay_token) {
  485. +           jabber_google_do_relay_request(js, session,
  486. +                              jabber_google_relay_response_session_handle_initiate_cb);
  487. +       } else {
  488. +           jabber_google_relay_response_session_handle_initiate_cb(session, NULL,
  489. +                                       0, 0, 0, NULL, NULL);
  490. +       }
  491.     }
  492. -
  493. +   else
  494. +     gtalk_xfer_handle_initiate(js, session, sess, iq_id);
  495. +  
  496.     return TRUE;
  497.  }
  498.  
  499. -
  500.  static void
  501.  google_session_handle_candidates(JabberStream  *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
  502.  {
  503.     JabberIq *result;
  504.     GList *list = NULL, *video_list = NULL;
  505. -   PurpleXmlNode *cand;
  506. +   PurpleXmlNode *cand, *transport, *cand_parent;
  507.     static int name = 0;
  508.     char n[4];
  509.     GoogleAVSessionData *session_data =
  510.         (GoogleAVSessionData *) session->session_data;
  511.  
  512. -   for (cand = purple_xmlnode_get_child(sess, "candidate"); cand;
  513. -           cand = purple_xmlnode_get_next_twin(cand)) {
  514. +   cand_parent = sess;
  515. +
  516. +   if(session->share) {
  517. +       /* TODO : Optimize this block for SHARE only!.
  518. +        * Multimedia is being handled elsewhere
  519. +        */
  520. +       GoogleXferSessionData *share_session =
  521. +           (GoogleXferSessionData *)session->session_data;
  522. +       transport = purple_xmlnode_get_child(sess, "transport");
  523. +       cand_parent = transport;
  524. +
  525. +       for (cand = purple_xmlnode_get_child(cand_parent, "candidate"); cand;
  526. +            cand = purple_xmlnode_get_next_twin(cand)) {
  527. +           PurpleMediaCandidate *info;
  528. +           const gchar *cname = purple_xmlnode_get_attrib(cand, "name");
  529. +           const gchar *type = purple_xmlnode_get_attrib(cand, "type");
  530. +           const gchar *protocol = purple_xmlnode_get_attrib(cand, "protocol");
  531. +           const gchar *address = purple_xmlnode_get_attrib(cand, "address");
  532. +           const gchar *port = purple_xmlnode_get_attrib(cand, "port");
  533. +           const gchar *preference = purple_xmlnode_get_attrib(cand, "preference");
  534. +           guint component_id;
  535. +      
  536. +           if (cname && type && address && port) {
  537. +               PurpleMediaCandidateType candidate_type;
  538. +               guint prio =
  539. +                   preference ?
  540. +                   g_ascii_strtod(preference, NULL) * 1000 :
  541. +                   0;
  542. +          
  543. +               g_snprintf(n, sizeof(n), "S%d", name++);
  544. +          
  545. +               if (g_str_equal(type, "local"))
  546. +                   candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
  547. +               else if (g_str_equal(type, "stun"))
  548. +                   candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX;
  549. +               else if (g_str_equal(type, "relay"))
  550. +                   candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;
  551. +               else
  552. +                   candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
  553. +          
  554. +               if (purple_strequal(cname, "rtcp") ||
  555. +                   purple_strequal(cname, "video_rtcp"))
  556. +                   component_id = PURPLE_MEDIA_COMPONENT_RTCP;
  557. +               else
  558. +                   component_id = PURPLE_MEDIA_COMPONENT_RTP;
  559. +          
  560. +               info = purple_media_candidate_new(n, component_id,
  561. +                                 candidate_type,
  562. +                                 purple_strequal(protocol, "udp") ?
  563. +                                 PURPLE_MEDIA_NETWORK_PROTOCOL_UDP :
  564. +                                 PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
  565. +                                 address,
  566. +                                 atoi(port));
  567. +               g_object_set(info, "username", xmlnode_get_attrib(cand, "username"),
  568. +                        "password", xmlnode_get_attrib(cand, "password"),
  569. +                        "priority", prio, NULL);
  570. +          
  571. +                                /*It's a share session*/
  572. +               share_session->remote_share_candidates =
  573. +                   g_slist_append(share_session->remote_share_candidates,
  574. +                              info);
  575. +               purple_debug_info("google_session", "Added candidate to sharelist\n");
  576. +          
  577. +           }
  578. +      
  579. +       }
  580. +       result = jabber_iq_new(js, JABBER_IQ_RESULT);
  581. +       jabber_iq_set_id(result, iq_id);
  582. +       xmlnode_set_attrib(result->node, "to", session->remote_jid);
  583. +       jabber_iq_send(result);
  584. +       return;
  585. +   }
  586. +
  587. +   for (cand = purple_xmlnode_get_child(cand_parent, "candidate"); cand;
  588. +        cand = purple_xmlnode_get_next_twin(cand)) {
  589.         PurpleMediaCandidate *info;
  590.         const gchar *cname = purple_xmlnode_get_attrib(cand, "name");
  591.         const gchar *type = purple_xmlnode_get_attrib(cand, "type");
  592. @@ -663,26 +880,35 @@
  593.             g_object_set(info, "username", purple_xmlnode_get_attrib(cand, "username"),
  594.                     "password", purple_xmlnode_get_attrib(cand, "password"),
  595.                     "priority", prio, NULL);
  596. -           if (!strncmp(cname, "video_", 6)) {
  597. -               if (session_data->added_streams) {
  598. -                   video_list = g_list_append(video_list, info);
  599. +
  600. +           if(!session->share) {
  601. +               if (!strncmp(cname, "video_", 6)) {
  602. +                   if (session_data->added_streams) {
  603. +                       video_list = g_list_append(video_list, info);
  604. +                   } else {
  605. +                       session_data->remote_video_candidates =
  606. +                           g_list_append(session_data->remote_video_candidates,
  607. +                                     info);
  608. +                   }
  609.                 } else {
  610. -                   session_data->remote_video_candidates =
  611. -                       g_list_append(session_data->remote_video_candidates,
  612. -                           info);
  613. -               }
  614. -           } else {
  615. -               if (session_data->added_streams) {
  616. -                   list = g_list_append(list, info);
  617. -               } else {
  618. -                   session_data->remote_audio_candidates =
  619. -                       g_list_append(session_data->remote_audio_candidates,
  620. -                           info);
  621. +                   if (session_data->added_streams) {
  622. +                       list = g_list_append(list, info);
  623. +                   } else {
  624. +                       session_data->remote_audio_candidates =
  625. +                           g_list_append(session_data->remote_audio_candidates,
  626. +                                     info);
  627. +                   }
  628.                 }
  629.             }
  630.         }
  631. +       else {
  632. +           purple_debug_info("google_session",
  633. +                     "cname && port && address && type FAILED!\n");
  634. +       }
  635.     }
  636.  
  637. +   /*if session was share, list and video_list are NULL*/
  638. +
  639.     if (list) {
  640.         purple_media_add_remote_candidates(session_data->media, "google-voice",
  641.             session->remote_jid, list);
  642. @@ -701,6 +927,30 @@
  643.  }
  644.  
  645.  static void
  646. +google_session_handle_transport_accept(JabberStream *js, GoogleSession *session,
  647. +                      PurpleXmlNode *sess, const char *iq_id)
  648. +{
  649. +   JabberIq *result_iq = jabber_iq_new(js,JABBER_IQ_RESULT);
  650. +
  651. +   xmlnode_set_attrib(result_iq->node, "to", session->remote_jid);
  652. +   jabber_iq_set_id(result_iq, iq_id);
  653. +   jabber_iq_send(result_iq);
  654. +   session->state = IN_PROGRESS;
  655. +}
  656. +
  657. +static void
  658. +google_session_handle_transport_info(JabberStream *js, GoogleSession *session,
  659. +                    PurpleXmlNode *sess, const char *iq_id)
  660. +{
  661. +   purple_debug_info("google_session", "Inside handle_transport_info..\n");
  662. +  
  663. +   if(session->share)
  664. +       gtalk_xfer_handle_candidates(js, session, sess, iq_id);
  665. +   else
  666. +       google_session_handle_candidates(js, session, sess, iq_id);
  667. +}
  668. +
  669. +static void
  670.  google_session_handle_accept(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
  671.  {
  672.     PurpleXmlNode *desc_element = purple_xmlnode_get_child(sess, "description");
  673. @@ -778,9 +1028,31 @@
  674.  static void
  675.  google_session_handle_terminate(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess)
  676.  {
  677. -   GoogleAVSessionData *session_data =
  678. -       (GoogleAVSessionData *) session->session_data;
  679. -   purple_media_end(session_data->media, NULL, NULL);
  680. +   JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
  681. +   jabber_iq_set_id(result, iq_id);
  682. +   purple_xmlnode_set_attrib(result->node, "to", session->remote_jid);
  683. +   jabber_iq_send(result);
  684. +
  685. +   purple_debug_info("google_session","Setting session_should_die to 1 \n");
  686. +   session->session_should_die = 1;           
  687. +              
  688. +   if(session->share) {   
  689. +       GoogleXferSessionData *share_session =
  690. +           (GoogleXferSessionData *)session->session_data;
  691. +       share_session->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
  692. +
  693. +       if(session->relay_processing)
  694. +           return;        
  695. +              
  696. +       session->state = TERMINATED;
  697. +       google_session_destroy(session);
  698. +   }
  699. +   else {
  700. +       GoogleAVSessionData *session_data =
  701. +           (GoogleAVSessionData *) session->session_data;
  702. +      
  703. +       purple_media_end(session_data->media, NULL, NULL)
  704. +   }
  705.  }
  706.  
  707.  static void
  708. @@ -790,14 +1062,38 @@
  709.  
  710.     if (!strcmp(type, "initiate")) {
  711.         google_session_handle_initiate(js, session, sess, iq_id);
  712. -   } else if (!strcmp(type, "accept")) {
  713. -       google_session_handle_accept(js, session, sess, iq_id);
  714. -   } else if (!strcmp(type, "reject")) {
  715. -       google_session_handle_reject(js, session, sess);
  716. +
  717. +   } else if (!strcmp(type, "accept")) {  
  718. +       if(session->share)
  719. +           gtalk_xfer_handle_accept(js, session, iq_id);
  720. +       else
  721. +           google_session_handle_accept(js, session, sess, iq_id);
  722. +      
  723. +   } else if (!strcmp(type, "info")) { /*Only useful for share sessions*/         
  724. +       gtalk_xfer_handle_info(js, session, sess, iq_id);
  725. +      
  726. +   } else if (!strcmp(type, "reject")) {          
  727. +       if(session->share)
  728. +           gtalk_xfer_handle_reject(js, session, iq_id);
  729. +       else   
  730. +           google_session_handle_reject(js, session, sess);
  731. +      
  732.     } else if (!strcmp(type, "terminate")) {
  733. -       google_session_handle_terminate(js, session, sess);
  734. +       google_session_handle_terminate(js, session, sess, iq_id);
  735. +
  736.     } else if (!strcmp(type, "candidates")) {
  737.         google_session_handle_candidates(js, session, sess, iq_id);
  738. +
  739. +   } else if (!strcmp(type, "transport-accept")) {
  740. +       google_session_handle_transport_accept(js, session, sess, iq_id);
  741. +
  742. +   } else if (!strcmp(type, "transport-info")) {
  743. +       google_session_handle_transport_info(js, session, sess, iq_id);
  744. +
  745. +   }
  746. +   else {
  747. +       purple_debug_info("google_session",
  748. +                 "No suitable IQ Parse Handler Found..\n");
  749.     }
  750.  }
  751.  
  752. @@ -808,7 +1104,7 @@
  753.  {
  754.     GoogleSession *session = NULL;
  755.     GoogleSessionId id;
  756. -
  757. +   GoogleAVSessionData *session_data;
  758.     PurpleXmlNode *desc_node;
  759.  
  760.     GList *iter = NULL;
  761. @@ -827,9 +1123,11 @@
  762.     iter = purple_media_manager_get_media_by_account(
  763.             purple_media_manager_get(),
  764.             purple_connection_get_account(js->gc));
  765. +
  766.     for (; iter; iter = g_list_delete_link(iter, iter)) {
  767.         GoogleSession *gsession =
  768. -               purple_media_get_prpl_data(iter->data);
  769. +           purple_media_get_prpl_data(iter->data);
  770. +
  771.         if (google_session_id_equal(&(gsession->id), &id)) {
  772.             session = gsession;
  773.             break;
  774. @@ -843,13 +1141,46 @@
  775.         google_session_parse_iq(js, session, session_node, iq_id);
  776.         return;
  777.     }
  778. +   else {
  779. +       if(js->google_share_sessions) {
  780. +           GList *iter = js->google_share_sessions;
  781.  
  782. +           for(; iter; iter=iter->next) {
  783. +               GoogleSession *gsession =
  784. +                   (GoogleSession *)(iter->data);
  785. +
  786. +               if(!gsession) {
  787. +                   purple_debug_info
  788. +                       ("google_session",
  789. +                        "Fatal Error. gsession is NULL.\n");
  790. +                   /*TODO: Remove the exit(0) line once gtalk xfer support is complete*/
  791. +                   exit(0);
  792. +                 }
  793. +
  794. +               if (google_session_id_equal(&id, &(gsession->id))) {
  795. +                   session = gsession;
  796. +                   break;
  797. +                   /*TODO: Ensure this works. Found a GoogleSession*/
  798. +               }
  799. +           }
  800. +       }
  801. +  
  802. +       /*if session!=NULL, it's a Share Session*/
  803. +       if(session) {
  804. +           google_session_parse_iq(js, session,
  805. +                       session_node, iq_id);
  806. +           return;
  807. +       }
  808. +   }
  809.     /* If the session doesn't exist, this has to be an initiate message */
  810.     if (strcmp(purple_xmlnode_get_attrib(session_node, "type"), "initiate"))
  811.         return;
  812. -   desc_node = purple_xmlnode_get_child(session_node, "description");
  813. +   }
  814. +
  815. +   desc_node = xmlnode_get_child(session_node, "description");
  816.     if (!desc_node)
  817.         return;
  818. +
  819.     session = g_new0(GoogleSession, 1);
  820.     session->id.id = g_strdup(id.id);
  821.     session->id.initiator = g_strdup(id.initiator);
  822. @@ -860,6 +1191,7 @@
  823.  
  824.     google_session_handle_initiate(js, session, session_node, iq_id);
  825.  }
  826. +
  827.  #endif /* USE_VV */
  828.  
  829.  
  830. diff --git a/libpurple/protocols/jabber/google/google_session.h b/libpurple/protocols/jabber/google/google_session.h
  831. --- a/libpurple/protocols/jabber/google/google_session.h
  832. +++ b/libpurple/protocols/jabber/google/google_session.h
  833. @@ -22,6 +22,48 @@
  834.  #define PURPLE_JABBER_GOOGLE_SESSION_H_
  835.  
  836.  #include "jabber.h"
  837. +#include <nice/agent.h>
  838. +
  839. +typedef enum {
  840. +   GTALK_XFER_CHANNEL_INITIALIZED = 0,
  841. +   GTALK_XFER_CHANNEL_HTTP_GET_NOT_SENT,
  842. +   GTALK_XFER_CHANNEL_SENT_HTTP_GET,
  843. +   GTALK_XFER_CHANNEL_HTTP_GET_RECEIVED,
  844. +   GTALK_XFER_CHANNEL_HTTP_OK_SENT,
  845. +   GTALK_XFER_CHANNEL_HTTP_SENDING,
  846. +   GTALK_XFER_CHANNEL_HTTP_RECEIVING,
  847. +   GTALK_XFER_CHANNEL_HTTP_TRANSFERRING,
  848. +   GTALK_XFER_CHANNEL_HTTP_SENDING_COMPLETE,
  849. +   GTALK_XFER_CHANNEL_HTTP_RECEIVING_COMPLETE,
  850. +   GTALK_XFER_CHANNEL_PARSED_HTTP_RESPONSE_HEADER
  851. +} GoogleXferChannelState;
  852. +
  853. +typedef struct {
  854. +   gchar *filename;        /*File Details*/
  855. +   guint64 filesize;
  856. +   gchar *preview_url;
  857. +   gchar *source_url;
  858. +   PurpleXfer *xfer;
  859. +   NiceAgent *share_agent; /*Needs to have a manifest
  860. +                 Entry for Folder Sharing: TODO*/
  861. +   gchar *channel_name;
  862. +   NiceComponentState agent_state;
  863. +   PurpleCircBuffer *buffer;
  864. +   GoogleXferChannelState channel_state;
  865. +   gint stream_id;
  866. +   gboolean candidates_gathered;  
  867. +   gboolean file_opened;   /* Stuff for using file buffer
  868. +                  for sending Gtalk Files.. */
  869. +   FILE *file_to_send;
  870. +   char *file_buf;
  871. +   int file_buf_current_size;
  872. +   int file_buf_sent;
  873. +
  874. +   GSList *remote_share_candidates; /* lists of
  875. +                       NiceCandidates */  
  876. +   GSList *local_share_candidates;
  877. +
  878. +} GoogleXferSessionData;
  879.  
  880.  typedef struct {
  881.     char *id;
  882. @@ -32,7 +74,7 @@
  883.     UNINIT,
  884.     SENT_INITIATE,
  885.     RECEIVED_INITIATE,
  886. -   IN_PRORESS,
  887. +   IN_PROGRESS,
  888.     TERMINATED
  889.  } GoogleSessionState;
  890.  
  891. @@ -44,13 +86,47 @@
  892.     char *iq_id;
  893.     PurpleXmlNode *description;     /* store incoming description through
  894.                                     relay credential fetching */
  895. +   gboolean relay_processing;
  896. +   gboolean share;                 /*for indicating whether it's a
  897. +                     fileXfer session*/
  898. +   gboolean session_should_die;
  899.     gpointer session_data;
  900.  } GoogleSession;
  901.  
  902. +void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
  903. +             gchar *lfoundation, gchar *rfoundation, gpointer user_data);
  904. +void cb_nice_component_state_changed(NiceAgent *agent,guint stream_id, guint component_id,
  905. +                    guint state, gpointer user_data);
  906. +void cb_nice_component_writable(NiceAgent *agent, guint stream_id, guint component_id,
  907. +               gpointer user_data);
  908. +
  909. +void gtalk_xfer_handle_initiate(JabberStream *js,
  910. +               GoogleSession *session,
  911. +               xmlnode *sess,
  912. +               const char *iq_id);
  913. +
  914. +void gtalk_xfer_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id);
  915. +void gtalk_xfer_handle_info(JabberStream  *js, GoogleSession *session, xmlnode *sess, const char *iq_id);
  916. +void gtalk_xfer_handle_accept(JabberStream *js, GoogleSession *session, const char *iq_id);
  917. +void gtalk_xfer_handle_reject(JabberStream *js, GoogleSession *session, const char *iq_id);
  918. +gint gtalk_xfer_init_agent(GoogleSession *session);
  919. +
  920. +void jabber_google_relay_response_session_initiate_cb(GoogleSession *session,
  921. +                             const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
  922. +                             const gchar *relay_username, const gchar *relay_password);
  923. +xmlnode *
  924. +google_session_create_xmlnode(GoogleSession *session, const char *type);
  925. +void
  926. +gtalk_xfer_send(PurpleConnection *gc, const char *who, const char *file);
  927. +
  928. +void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer user_data);
  929. +
  930.  gboolean jabber_google_session_initiate(JabberStream *js, const gchar *who,
  931.      PurpleMediaSessionType type);
  932.  
  933.  void jabber_google_session_parse(JabberStream *js, const char *from,
  934.      JabberIqType type, const char *iq, PurpleXmlNode *session);
  935.  
  936. -#endif /* PURPLE_JABBER_GOOGLE_SESSION_H_ */
  937. \ No newline at end of file
  938. +void google_session_destroy(GoogleSession *session);
  939. +
  940. +#endif /* PURPLE_JABBER_GOOGLE_SESSION_H_ */
  941. diff --git a/libpurple/protocols/jabber/google/google_share.c b/libpurple/protocols/jabber/google/google_share.c
  942. new file mode 100644
  943. --- /dev/null
  944. +++ b/libpurple/protocols/jabber/google/google_share.c
  945. @@ -0,0 +1,1377 @@
  946. +/**
  947. + * Purple is the legal property of its developers, wohse names are too numerous
  948. + * to list here.  Please refer to the COPYRIGHT file distributed with this
  949. + * source distribution.
  950. + *
  951. + * This program is free software; you can redistribute it and/or modify
  952. + * it under the terms of the GNU General Public License as published by
  953. + * the Free Software Foundation; either version 2 of the License, or
  954. + * (at your option) any later version.
  955. + *
  956. + * This program is distributed in the hope that it will be useful,
  957. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  958. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  959. + * GNU General Public License for more details.
  960. + *
  961. + * You should have received a copy of the GNU General Public License
  962. + * along with this program; if not, write to the Free Software
  963. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  964. + */
  965. +
  966. +#include "internal.h"
  967. +#include "debug.h"
  968. +#include "google_session.h"
  969. +#include "relay.h"
  970. +#include "jingle/jingle.h"
  971. +#include "jingle/transport.h"
  972. +#include "network.h"
  973. +#include "stun.h"
  974. +#include "media.h"
  975. +#include "relay.h"
  976. +#include <nice/agent.h>
  977. +
  978. +static char*
  979. +gtalk_get_temporary_url(void)
  980. +{
  981. +        /*According to GTalk data, the length of temporary URL must be 44.*/
  982. +   static int z = - 1;
  983. +   char *temporary_url = g_malloc(45);
  984. +   int i = 11;
  985. +   char *alpha = "abcdefghijklmnopqrstuvwxyz";
  986. +   char *num = "0123456789";
  987. +   srandom(time(NULL));
  988. +
  989. +   if(z==10)
  990. +       z = 1;
  991. +   z++;
  992. +
  993. +   strcpy(temporary_url, "/temporary/");
  994. +   for(;i<43;i++) {
  995. +       int j=random()%2;
  996. +
  997. +       if(j==0)
  998. +           temporary_url[i] = alpha[random()%(26-z)];
  999. +       else
  1000. +           temporary_url[i] = num[random()%(10-z)];
  1001. +       }
  1002. +   temporary_url[i]='/';
  1003. +   ++i;
  1004. +   temporary_url[i]='\0';
  1005. +
  1006. +   return temporary_url;
  1007. +}
  1008. +
  1009. +static void
  1010. +gtalk_xfer_send_reject(PurpleXfer *xfer)
  1011. +{
  1012. +   GoogleSession *session = (GoogleSession *) xfer->data;
  1013. +   JabberStream *js = session->js;
  1014. +   JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
  1015. +   xmlnode *session_node;
  1016. +
  1017. +   if(purple_xfer_get_type(xfer) != PURPLE_XFER_RECEIVE)
  1018. +       return;
  1019. +
  1020. +   xmlnode_set_attrib(iq->node, "to", session->remote_jid);   
  1021. +   session_node = xmlnode_new_child(iq->node, "session");
  1022. +   xmlnode_set_attrib(session_node, "type", "reject");
  1023. +   xmlnode_set_attrib(session_node, "id", session->id.id);
  1024. +   xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
  1025. +   xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);        
  1026. +   jabber_iq_send(iq);        
  1027. +}
  1028. +
  1029. +static void
  1030. +gtalk_xfer_request_denied(PurpleXfer *xfer)
  1031. +{
  1032. +   purple_debug_info("google_session", "Request denied by user..\n");
  1033. +   gtalk_xfer_send_reject(xfer);  
  1034. +}
  1035. +
  1036. +/* If buffer contains a line ending, 0-terminate the first line and
  1037. + * return a pointer to the beginning of the next line. Otherwise
  1038. + * return NULL. */
  1039. +
  1040. +static gchar *
  1041. +http_read_line(gchar *buffer, guint len) {
  1042. +
  1043. +   gchar *p = memchr(buffer, '\n', len);
  1044. +
  1045. +        /* Looking for a CRLF basically */
  1046. +
  1047. +   if (p != NULL) {
  1048. +       *p = 0;
  1049. +       if (p > buffer && *(p-1) == '\r')
  1050. +           *(p-1) = '\0';
  1051. +       p++;
  1052. +   }
  1053. +  
  1054. +   return p;
  1055. +}
  1056. +
  1057. +static void
  1058. +cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id,
  1059. +        guint len, gchar *buf, gpointer data)
  1060. +{
  1061. +   GoogleXferSessionData *share_session = (GoogleXferSessionData *)data;
  1062. +   PurpleXfer *xfer = share_session->xfer;
  1063. +   gchar *curr = buf;
  1064. +  
  1065. +   if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
  1066. +       /*TODO: Maybe Add a parser to make sure it's not bad data?*/
  1067. +      
  1068. +       /*We should send back a 200 OK now*/
  1069. +
  1070. +       int send_ret;
  1071. +       gchar *response = g_strdup_printf( "HTTP/1.1 200\r\n"
  1072. +                          "Connection: Keep-Alive\r\n"
  1073. +                          "Content-Length: %" G_GSIZE_FORMAT "\r\n"
  1074. +                          "Content-Type: application/octet-stream\r\n\r\n",
  1075. +                          xfer->size);
  1076. +      
  1077. +       share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_GET_RECEIVED;
  1078. +       send_ret = nice_agent_send(share_session->share_agent,
  1079. +                      share_session->stream_id, 1,
  1080. +                      strlen(response), response);
  1081. +      
  1082. +       purple_debug_info("google_session", "Sending response : %s\n", response);
  1083. +       purple_debug_info("google_session", "For sending 200 OK, send_ret is : %d\n",send_ret);
  1084. +       purple_debug_info("google_session", "Filesize is : %" G_GSIZE_FORMAT "\n", xfer->size);
  1085. +
  1086. +       share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_OK_SENT;
  1087. +  
  1088. +       share_session->file_to_send = fopen(share_session->xfer->local_filename, "rb");
  1089. +      
  1090. +       if(share_session->agent_state == NICE_COMPONENT_STATE_READY) {
  1091. +           share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_SENDING;
  1092. +
  1093. +           cb_nice_component_writable(share_session->share_agent, share_session->stream_id,
  1094. +                          1, share_session);
  1095. +       }
  1096. +   }
  1097. +   else if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
  1098. +       if (share_session->channel_state ==
  1099. +           GTALK_XFER_CHANNEL_SENT_HTTP_GET) {
  1100. +           gchar *tmp;
  1101. +           gsize read_len;
  1102. +          
  1103. +           do {
  1104. +               tmp = http_read_line(curr, len);
  1105. +               read_len = tmp - curr;
  1106. +              
  1107. +               purple_debug_info(
  1108. +                   "google_session",
  1109. +                   "HTTP response header received: %s\n", curr);
  1110. +
  1111. +               if(curr[0] == '\0') {
  1112. +                   break;
  1113. +               }
  1114. +
  1115. +               len -= read_len;
  1116. +               curr += read_len;
  1117. +              
  1118. +               if (g_ascii_strncasecmp(curr, "HTTP/1.1", 8)) {
  1119. +                   if (purple_strequal(curr + 9, "404")) {
  1120. +                       /* got a 404 (file not found) stop... */
  1121. +                   }
  1122. +               }
  1123. +               /* TODO: check Content-Length and other headers too? */
  1124. +              
  1125. +           } while (curr[0] != '\0' && len > 0);
  1126. +
  1127. +           if (curr[0] == '\0') {
  1128. +               /* we found the end of the headers */
  1129. +               purple_debug_info("google_session",
  1130. +                         "Headers End here..(Blank Line)\n");
  1131. +              
  1132. +               share_session->channel_state =
  1133. +                   GTALK_XFER_CHANNEL_PARSED_HTTP_RESPONSE_HEADER;
  1134. +
  1135. +               share_session->channel_state =  GTALK_XFER_CHANNEL_HTTP_RECEIVING;
  1136. +               purple_xfer_start(xfer, -1, NULL, 0);
  1137. +           }
  1138. +           /* otherwise the remaining headers would come in the next package
  1139. +              not sure if this will ever happen */        
  1140. +       } else if (share_session->channel_state ==
  1141. +              GTALK_XFER_CHANNEL_HTTP_RECEIVING) {
  1142. +           static int curlen = 0;
  1143. +           /* write data to transfer */
  1144. +           curlen+=len;
  1145. +          
  1146. +/*         purple_debug_info("google-session",
  1147. +                     "got %d bytes to write to transfer, CURLEN: %d\n", len, curlen);
  1148. +*/        
  1149. +           if (len <= purple_xfer_get_bytes_remaining(xfer)) {
  1150. +               purple_circ_buffer_append(share_session->buffer, curr, len);
  1151. +               purple_xfer_prpl_ready(xfer);
  1152. +           } else {
  1153. +               purple_debug_error("google-share",
  1154. +                          "trying to write past end of file\n");
  1155. +
  1156. +               if(purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_CANCEL_REMOTE &&
  1157. +                  purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_CANCEL_LOCAL) {
  1158. +                   purple_debug_info(
  1159. +                       "google_session",
  1160. +                       "Calling purple_xfer_cancel_remote from cb_nice_recv()\n");
  1161. +                   purple_xfer_cancel_remote(xfer);                                   
  1162. +               }
  1163. +           }
  1164. +       }
  1165. +   }
  1166. +}
  1167. +
  1168. +static void
  1169. +gtalk_xfer_channel_cb(JabberStream *js, const gchar *from, JabberIqType type,
  1170. +             const gchar *id, xmlnode *sess, gpointer data)
  1171. +{
  1172. +   purple_debug_info("google_session", "GTalk responded to our channel send out!\n");
  1173. +
  1174. +   if (type == JABBER_IQ_RESULT) {
  1175. +       GoogleSession *session = (GoogleSession *) data;       
  1176. +       GoogleXferSessionData *share_session =
  1177. +           (GoogleXferSessionData *)session->session_data;
  1178. +      
  1179. +       /* start agent */
  1180. +       nice_agent_gather_candidates(share_session->share_agent, share_session->stream_id);
  1181. +   }
  1182. +}
  1183. +
  1184. +static void
  1185. +gtalk_xfer_accept_cb(JabberStream *js, const gchar *from, JabberIqType type,
  1186. +            const gchar *id, xmlnode *sess, gpointer data)
  1187. +{
  1188. +   GoogleSession *session = (GoogleSession *) data;
  1189. +   GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
  1190. +      
  1191. +   if (type != JABBER_IQ_RESULT) {
  1192. +       share_session->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
  1193. +       google_session_destroy(share_session->xfer->data);
  1194. +       /*TODO: Make the session terminate gracefully here. session_destroy does that,*/
  1195. +   }
  1196. +   else {
  1197. +       /*Send a channel*/
  1198. +      
  1199. +       gchar *me = g_strdup_printf("%s@%s/%s",
  1200. +                       session->js->user->node,
  1201. +                       session->js->user->domain,
  1202. +                       session->js->user->resource);
  1203. +      
  1204. +       JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
  1205. +       xmlnode *sess = google_session_create_xmlnode(session, "info");
  1206. +       xmlnode *channel = xmlnode_new_child(sess, "channel");
  1207. +
  1208. +       share_session->channel_name = jabber_get_next_id(session->js);
  1209. +
  1210. +       xmlnode_set_namespace(channel, NS_GOOGLE_SESSION_SHARE);
  1211. +       xmlnode_set_attrib(channel, "name", share_session->channel_name);
  1212. +       xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  1213. +       xmlnode_set_attrib(iq->node, "from", me);
  1214. +       xmlnode_insert_child(iq->node, sess);
  1215. +       jabber_iq_set_callback(iq, gtalk_xfer_channel_cb, session);
  1216. +       jabber_iq_send(iq);
  1217. +   }
  1218. +}
  1219. +
  1220. +static void
  1221. +gtalk_xfer_send_accept(JabberStream *js, GoogleSession *session)
  1222. +{
  1223. +   JabberIq *iq;
  1224. +   xmlnode *session_node, *description_node, *protocol_node;
  1225. +
  1226. +   purple_debug_info("google_session", "Inside google_xfer_send__accept()\n");
  1227. +   iq = jabber_iq_new(js, JABBER_IQ_SET);
  1228. +   xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  1229. +  
  1230. +   session_node = xmlnode_new_child(iq->node, "session");
  1231. +   description_node = xmlnode_new_child(session_node, "description");
  1232. +  
  1233. +   xmlnode_set_attrib(session_node, "type", "accept");
  1234. +   xmlnode_set_attrib(session_node, "id", session->id.id);
  1235. +   xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
  1236. +   xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
  1237. +  
  1238. +   xmlnode_new_child(description_node, "manifest");
  1239. +   protocol_node = xmlnode_new_child(description_node, "protocol");
  1240. +   xmlnode_new_child(protocol_node, "http");
  1241. +  
  1242. +   xmlnode_set_namespace(description_node, NS_GOOGLE_SESSION_SHARE);
  1243. +   jabber_iq_set_callback(iq, gtalk_xfer_accept_cb, session);
  1244. +   jabber_iq_send(iq);
  1245. +}
  1246. +
  1247. +static void
  1248. +gtalk_xfer_transport_accept_cb(JabberStream *js, const gchar *from,
  1249. +   JabberIqType type, const gchar *id, xmlnode *packet, gpointer data)
  1250. +{
  1251. +   gtalk_xfer_send_accept(js, (GoogleSession *)data);
  1252. +}
  1253. +
  1254. +static void
  1255. +gtalk_xfer_send_initiate_cb(JabberStream *js, const gchar *from, JabberIqType type,
  1256. +             const gchar *id, xmlnode *sess, gpointer data)
  1257. +{
  1258. +   GoogleSession *session = (GoogleSession *)data;
  1259. +
  1260. +   if(type == JABBER_IQ_ERROR) {
  1261. +       google_session_destroy(session);
  1262. +       return;
  1263. +   }
  1264. +
  1265. +   if (js->google_relay_host && js->google_relay_token) {
  1266. +       jabber_google_do_relay_request(js, session,
  1267. +                          jabber_google_relay_response_session_initiate_cb);
  1268. +   } else {
  1269. +       jabber_google_relay_response_session_initiate_cb(session, NULL, 0, 0, 0,
  1270. +                                NULL, NULL);
  1271. +   }
  1272. +
  1273. +}
  1274. +
  1275. +static void
  1276. +gtalk_xfer_send_session_initiate(PurpleXfer *xfer)
  1277. +{
  1278. +   GoogleSession *session = xfer->data;
  1279. +   JabberStream *js = session->js;
  1280. +   JabberIq *iq;
  1281. +   xmlnode *session_node, *description_node, *file_node, *manifest_node, *transport_node;
  1282. +   xmlnode *name_node, *protocol_node, *http_node, *url_source_node, *url_preview_node;
  1283. +   gchar *me = g_strdup_printf("%s@%s/%s",
  1284. +                   js->user->node,
  1285. +                   js->user->domain,
  1286. +                   js->user->resource);
  1287. +
  1288. +   purple_debug_info("google_session", "Inside gtalk_xfer_send_session_initiate()\n");
  1289. +   iq = jabber_iq_new(js, JABBER_IQ_SET);
  1290. +   xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  1291. +
  1292. +   session_node = xmlnode_new_child(iq->node, "session");
  1293. +
  1294. +   xmlnode_set_attrib(session_node, "type", "initiate");
  1295. +   xmlnode_set_attrib(session_node, "id", session->id.id);
  1296. +
  1297. +   xmlnode_set_attrib(session_node, "initiator", me);
  1298. +   xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
  1299. +
  1300. +   description_node = xmlnode_new_child(session_node, "description");
  1301. +   xmlnode_set_namespace(description_node, NS_GOOGLE_SESSION_SHARE);
  1302. +
  1303. +   manifest_node = xmlnode_new_child(description_node, "manifest");
  1304. +   file_node = xmlnode_new_child(manifest_node, "file");
  1305. +   xmlnode_set_attrib(file_node, "size", g_strdup_printf("%" G_GSIZE_FORMAT,xfer->size));
  1306. +
  1307. +   name_node = xmlnode_new_child(file_node, "name");
  1308. +   xmlnode_insert_data(name_node,xfer->filename,strlen(xfer->filename));
  1309. +
  1310. +   protocol_node = xmlnode_new_child(description_node, "protocol");
  1311. +   http_node = xmlnode_new_child(protocol_node, "http");
  1312. +   url_source_node = xmlnode_new_child(http_node, "url");
  1313. +   xmlnode_set_attrib(url_source_node, "name", "source-path");
  1314. +   xmlnode_insert_data(url_source_node, gtalk_get_temporary_url(), -1);
  1315. +
  1316. +   url_preview_node = xmlnode_new_child(http_node, "url");
  1317. +   xmlnode_set_attrib(url_preview_node, "name", "preview-path");
  1318. +   xmlnode_insert_data(url_preview_node, gtalk_get_temporary_url(), -1);
  1319. +
  1320. +   transport_node = xmlnode_new_child(session_node, "transport");
  1321. +   xmlnode_set_namespace(transport_node, NS_GOOGLE_TRANSPORT_P2P);
  1322. +
  1323. +   jabber_iq_set_callback(iq, gtalk_xfer_send_initiate_cb, session);
  1324. +   jabber_iq_send(iq);
  1325. +   session->state = SENT_INITIATE;
  1326. +}
  1327. +
  1328. +static void
  1329. +gtalk_xfer_send_transport_accept(JabberStream *js, GoogleSession *session)
  1330. +{
  1331. +   JabberIq *iq;
  1332. +   xmlnode *session_node, *transport_node;
  1333. +  
  1334. +   purple_debug_info("google_session", "Inside google_xfer_send_transport_accept()\n");
  1335. +   iq = jabber_iq_new(js, JABBER_IQ_SET);
  1336. +   xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  1337. +  
  1338. +   session_node = xmlnode_new_child(iq->node, "session");
  1339. +   transport_node = xmlnode_new_child(session_node, "transport");
  1340. +  
  1341. +   xmlnode_set_attrib(session_node, "type", "transport-accept");
  1342. +   xmlnode_set_attrib(session_node, "id", session->id.id);
  1343. +   xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
  1344. +   xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
  1345. +
  1346. +   xmlnode_set_namespace(transport_node, NS_GOOGLE_TRANSPORT_P2P);
  1347. +   jabber_iq_set_callback(iq, gtalk_xfer_transport_accept_cb, session);
  1348. +   jabber_iq_send(iq);
  1349. +   session->state = IN_PROGRESS;
  1350. +}
  1351. +
  1352. +static void
  1353. +gtalk_xfer_send_terminate(PurpleXfer *xfer)
  1354. +{
  1355. +   GoogleSession *session = (GoogleSession *) xfer->data;
  1356. +   JabberStream *js = session->js;
  1357. +   JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
  1358. +   xmlnode *session_node;
  1359. +
  1360. +   if(session->state < IN_PROGRESS) {
  1361. +       google_session_destroy(session);
  1362. +   }
  1363. +   else {
  1364. +       xmlnode_set_attrib(iq->node, "to", session->remote_jid);   
  1365. +       session_node = xmlnode_new_child(iq->node, "session");
  1366. +       xmlnode_set_attrib(session_node, "type", "terminate");
  1367. +       xmlnode_set_attrib(session_node, "id", session->id.id);
  1368. +       xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
  1369. +       xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);        
  1370. +       purple_debug_info("google_session", "Sending google_s_dest as callback..Sending IQ\n");
  1371. +       jabber_iq_send(iq);        
  1372. +       google_session_destroy(session);
  1373. +   }
  1374. +}
  1375. +
  1376. +static void
  1377. +gtalk_xfer_cancel_xfer(PurpleXfer *xfer)
  1378. +{
  1379. +   GoogleSession *session = (GoogleSession *)xfer->data;
  1380. +
  1381. +   purple_debug_info("gs", "Inside gtalk_xfer_cancel_xfer...\n");
  1382. +  
  1383. +   if(session->state == TERMINATED)
  1384. +       return;
  1385. +
  1386. +   gtalk_xfer_send_terminate(xfer);
  1387. +}
  1388. +
  1389. +static void
  1390. +gtalk_xfer_init(PurpleXfer *xfer)
  1391. +{
  1392. +   GoogleSession *session = (GoogleSession *)(xfer->data);
  1393. +   JabberStream *js = session->js;
  1394. +
  1395. +   purple_debug_info("google_session", "Inside gtalk_xfer_init\n");
  1396. +  
  1397. +   js->google_share_sessions = g_list_prepend(js->google_share_sessions, session);
  1398. +  
  1399. +   if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE)
  1400. +       gtalk_xfer_send_transport_accept(js, session);
  1401. +
  1402. +   if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
  1403. +       gtalk_xfer_send_session_initiate(xfer);
  1404. +}
  1405. +
  1406. +gint
  1407. +gtalk_xfer_init_agent(GoogleSession *session)
  1408. +{
  1409. +   gint stream_id;
  1410. +   NiceAgent *agent;
  1411. +   GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
  1412. +  
  1413. +   purple_debug_info("google_session", "Inside gtalk_xfer_init_agent\n");
  1414. +   if(!share_session)
  1415. +     return -1;
  1416. +  
  1417. +   if(share_session->share_agent)
  1418. +     return share_session->stream_id;
  1419. +
  1420. +   agent = share_session->share_agent;
  1421. +  
  1422. +   agent = nice_agent_new_reliable (g_main_context_default(), NICE_COMPATIBILITY_GOOGLE);
  1423. +   stream_id = nice_agent_add_stream(agent, 1);
  1424. +   share_session->share_agent = agent;
  1425. +
  1426. +   nice_agent_attach_recv (share_session->share_agent, stream_id, 1, g_main_context_default(),
  1427. +               cb_nice_recv, share_session);
  1428. +  
  1429. +   g_signal_connect (G_OBJECT (share_session->share_agent), "candidate-gathering-done",
  1430. +             G_CALLBACK (cb_candidate_gathering_done),  session);
  1431. +  
  1432. +   g_signal_connect (G_OBJECT (share_session->share_agent), "new-selected-pair",
  1433. +             G_CALLBACK (cb_new_selected_pair), NULL);
  1434. +  
  1435. +   g_signal_connect  (G_OBJECT (share_session->share_agent), "component-state-changed",
  1436. +              G_CALLBACK (cb_nice_component_state_changed), session);
  1437. +
  1438. +   g_signal_connect (G_OBJECT (share_session->share_agent), "reliable-transport-writable",
  1439. +             G_CALLBACK (cb_nice_component_writable), share_session);
  1440. +
  1441. +   share_session->share_agent = agent;
  1442. +   share_session->stream_id = stream_id;
  1443. +   return stream_id;
  1444. +}
  1445. +
  1446. +
  1447. +void
  1448. +gtalk_xfer_handle_info(JabberStream  *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
  1449. +{
  1450. +   JabberIq *iq;
  1451. +   xmlnode *channel = xmlnode_get_child(sess, "channel");
  1452. +   xmlnode *complete = xmlnode_get_child(sess, "complete");   
  1453. +   GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data; 
  1454. +
  1455. +   purple_debug_info("google_session", "Inside gtalk_xfer_handle_info\n");
  1456. +  
  1457. +   if(complete) {
  1458. +       iq = jabber_iq_new(js, JABBER_IQ_RESULT);
  1459. +       jabber_iq_set_id(iq, iq_id);
  1460. +       xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  1461. +       jabber_iq_send(iq);
  1462. +       /*Maybe this call to session_destroy shouldn't occur and we should trigger the destroy when
  1463. +         GTalk sends us the terminate message,(which ideally should be immediately following
  1464. +         the "complete" message), but that would be depending on Google Talk for killing
  1465. +         this session. Need to resolve this and this comment should go away ASAP. TODO*/
  1466. +       google_session_destroy(session);
  1467. +       return;
  1468. +   }
  1469. +
  1470. +   if(channel)
  1471. +       share_session->channel_name = g_strdup(xmlnode_get_attrib(channel, "name"));
  1472. +  
  1473. +   iq = jabber_iq_new(js, JABBER_IQ_RESULT);
  1474. +   jabber_iq_set_id(iq, iq_id);
  1475. +   xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  1476. +   jabber_iq_send(iq);
  1477. +
  1478. +   purple_debug_info("google_session", "Starting candidate cathering with nice agent..\n");
  1479. +
  1480. +   nice_agent_gather_candidates(share_session->share_agent, share_session->stream_id);
  1481. +}
  1482. +
  1483. +
  1484. +static NiceCandidate *
  1485. +nice_candidate_from_xml(const xmlnode *candidate,
  1486. +           guint stream_id)
  1487. +{
  1488. +   NiceCandidate *cand = NULL;
  1489. +   const gchar *name = xmlnode_get_attrib(candidate, "name");
  1490. +   const gchar *type = xmlnode_get_attrib(candidate, "type");
  1491. +   const gchar *address = xmlnode_get_attrib(candidate, "address");
  1492. +   guint port = atoi(xmlnode_get_attrib(candidate, "port"));
  1493. +   const gchar *preference = xmlnode_get_attrib(candidate, "preference");
  1494. +  
  1495. +   if (name && type && address && port != 0) {
  1496. +       guint prio = preference ? g_ascii_strtod(preference, NULL) * 1000 : 0;
  1497. +       cand = nice_candidate_new(purple_strequal(type, "host") ?
  1498. +           NICE_CANDIDATE_TYPE_HOST :
  1499. +           purple_strequal(type, "stun") ? NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE :
  1500. +           purple_strequal(type, "relay") ? NICE_CANDIDATE_TYPE_RELAYED :
  1501. +           NICE_CANDIDATE_TYPE_HOST);
  1502. +
  1503. +       nice_address_init(&cand->addr);
  1504. +
  1505. +       if (!nice_address_set_from_string(&cand->addr, address)) {
  1506. +           purple_debug_error("google_session",
  1507. +               "Invalid NiceAddress in NiceCandidate.\n");
  1508. +           nice_candidate_free(cand);
  1509. +           return NULL;
  1510. +       }
  1511. +
  1512. +       nice_address_set_port(&cand->addr, port);
  1513. +       cand->priority = prio;
  1514. +       cand->stream_id = stream_id;
  1515. +       cand->username = g_strdup(xmlnode_get_attrib(candidate, "username"));
  1516. +       cand->password = g_strdup(xmlnode_get_attrib(candidate, "password"));
  1517. +   } else {
  1518. +       purple_debug_error("google_session", "received invalid candidate!\n");
  1519. +   }
  1520. +
  1521. +   return cand;
  1522. +}
  1523. +
  1524. +void
  1525. +gtalk_xfer_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
  1526. +{
  1527. +   GSList *candidate_list = NULL;
  1528. +   xmlnode *candidate_node, *transport_node;
  1529. +   GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
  1530. +   JabberIq *result;
  1531. +   transport_node = NULL;
  1532. +
  1533. +   purple_debug_info("google_session", "Inside gtalk_xfer_handle_candidates..\n");
  1534. +
  1535. +   /*Sending IQ_RESULT first and then processing the candidate*/
  1536. +/*Modifying this to handle multiple candidates inside a single transport message*/
  1537. +  
  1538. +   if(sess)
  1539. +       transport_node = xmlnode_get_child(sess, "transport");
  1540. +  
  1541. +   if(transport_node) {
  1542. +  
  1543. +       for (candidate_node = xmlnode_get_child(transport_node, "candidate");
  1544. +            candidate_node; candidate_node = xmlnode_get_next_twin(candidate_node)) {
  1545. +           NiceCandidate *cand =
  1546. +               nice_candidate_from_xml(candidate_node,
  1547. +                           share_session->stream_id);
  1548. +          
  1549. +           if (cand) {
  1550. +               candidate_list = g_slist_append(candidate_list, cand);
  1551. +           }
  1552. +       }
  1553. +      
  1554. +       if (share_session->candidates_gathered) {
  1555. +           nice_agent_set_remote_candidates(share_session->share_agent, share_session->stream_id,
  1556. +                            1, candidate_list);
  1557. +           while(candidate_list) {
  1558. +               NiceCandidate *c = (NiceCandidate *) candidate_list->data;
  1559. +               nice_candidate_free(c);
  1560. +               candidate_list = g_slist_delete_link(candidate_list, candidate_list);
  1561. +           }
  1562. +
  1563. +       } else {
  1564. +           share_session->remote_share_candidates =
  1565. +               g_slist_concat(share_session->remote_share_candidates, candidate_list);
  1566. +       }      
  1567. +   }
  1568. +   purple_debug_info("google_session", "Added remote candidate to Nice Agent!.\n");   
  1569. +  
  1570. +   result = jabber_iq_new(js, JABBER_IQ_RESULT);
  1571. +   jabber_iq_set_id(result, iq_id);
  1572. +   xmlnode_set_attrib(result->node, "to", session->remote_jid);
  1573. +   jabber_iq_send(result);
  1574. +}
  1575. +
  1576. +void
  1577. +gtalk_xfer_handle_accept(JabberStream *js, GoogleSession *session, const char *iq_id)
  1578. +{
  1579. +   JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
  1580. +   jabber_iq_set_id(result, iq_id);
  1581. +   xmlnode_set_attrib(result->node, "to", session->remote_jid);
  1582. +   jabber_iq_send(result);
  1583. +}
  1584. +
  1585. +
  1586. +void
  1587. +gtalk_xfer_handle_reject(JabberStream *js, GoogleSession *session, const char *iq_id)
  1588. +{ 
  1589. +   GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
  1590. +   JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
  1591. +   jabber_iq_set_id(result, iq_id);
  1592. +   xmlnode_set_attrib(result->node, "to", session->remote_jid);
  1593. +   jabber_iq_send(result);
  1594. +
  1595. +   purple_debug_info("google_session", "The remote user Rejected the Xfer request..\n");
  1596. +  
  1597. +   share_session->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
  1598. +   session->state = TERMINATED;
  1599. +   google_session_destroy(session);
  1600. +}
  1601. +
  1602. +/*TODO: NEVER USED??*/
  1603. +static void
  1604. +gtalk_xfer_send_candidates(GoogleSession *session)
  1605. +{     
  1606. +   GoogleXferSessionData *share_session = (GoogleXferSessionData *)session->session_data;
  1607. +   GSList *candidates = share_session->local_share_candidates;
  1608. +   GSList *iter;
  1609. +   purple_debug_info("google_session", "inside gtalk_xfer_send_candidates()\n");
  1610. +  
  1611. +   for(iter = candidates; iter; iter = iter->next) {
  1612. +       JabberIq *iq;
  1613. +       gchar *ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
  1614. +       gchar *port;
  1615. +       gchar *username, *password;
  1616. +       xmlnode *sess;
  1617. +       xmlnode *candidate, *transport;
  1618. +       NiceCandidate *nice_candid = (NiceCandidate *)iter->data;
  1619. +       NiceCandidateType type;
  1620. +
  1621. +       iq = jabber_iq_new(session->js, JABBER_IQ_SET);
  1622. +       sess = google_session_create_xmlnode(session, "transport-info");
  1623. +       xmlnode_insert_child(iq->node, sess);
  1624. +       xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  1625. +
  1626. +       transport = xmlnode_new("transport");
  1627. +       xmlnode_set_namespace(transport, NS_GOOGLE_TRANSPORT_P2P);
  1628. +       xmlnode_insert_child(sess, transport);
  1629. +
  1630. +       candidate = xmlnode_new("candidate");
  1631. +              
  1632. +       nice_address_to_string(&nice_candid->addr, ip);
  1633. +       port = g_strdup_printf("%u",nice_address_get_port(&nice_candid->addr));
  1634. +
  1635. +       purple_debug_info("google_session", "IP and port : %s:%s\n",ip,port);
  1636. +
  1637. +       type = nice_candid->type;
  1638. +              
  1639. +       xmlnode_set_attrib(candidate, "address", ip);
  1640. +       xmlnode_set_attrib(candidate, "port", port);
  1641. +       xmlnode_set_attrib(candidate, "name", "private-1");
  1642. +
  1643. +       username = g_strdup(nice_candid->username);
  1644. +       password = g_strdup(nice_candid->password);
  1645. +              
  1646. +       xmlnode_set_attrib(candidate, "username", username != NULL ? username : "");
  1647. +/*TODO: Fix preference*/
  1648. +       xmlnode_set_attrib(candidate, "preference", type == NICE_CANDIDATE_TYPE_HOST ? "0.000015":
  1649. +                  "0.000000");
  1650. +
  1651. +       xmlnode_set_attrib(candidate, "protocol", "udp");
  1652. +       /*CHECK THIS : TODO Type*/
  1653. +
  1654. +       xmlnode_set_attrib(candidate, "type",
  1655. +                  type == NICE_CANDIDATE_TYPE_HOST ? "local":
  1656. +                  type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ? "stun":
  1657. +                  type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE ? "prflx":
  1658. +                  type == NICE_CANDIDATE_TYPE_RELAYED ? "relay"
  1659. +                  : "local");
  1660. +
  1661. +       if(type == NICE_CANDIDATE_TYPE_RELAYED) {
  1662. +         if(nice_candid->turn) {
  1663. +           gchar *turn_ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
  1664. +           nice_address_to_string(&nice_candid->turn->server, turn_ip);
  1665. +           purple_debug_info("google_session", "turn IP for NiceCandidate: %s\n", turn_ip);
  1666. +         }
  1667. +         else
  1668. +           purple_debug_info("google_session", "TURN is NULL for candidate..\n");
  1669. +       }
  1670. +      
  1671. +      
  1672. +       xmlnode_set_attrib(candidate, "generation", "0");
  1673. +       xmlnode_set_attrib(candidate, "network", "0");
  1674. +       xmlnode_insert_child(transport, candidate);
  1675. +
  1676. +       g_free(ip);
  1677. +       g_free(port);
  1678. +       g_free(username);
  1679. +       g_free(password);
  1680. +       jabber_iq_send(iq);
  1681. +   }
  1682. +}
  1683. +
  1684. +/*Thanks for this, malu :D*/
  1685. +static xmlnode *
  1686. +nice_candidate_to_xml(const NiceCandidate *cand,
  1687. +             GoogleXferSessionData *share_session)
  1688. +{
  1689. +   xmlnode *candidate = xmlnode_new("candidate");
  1690. +   gchar address[NICE_ADDRESS_STRING_LEN];
  1691. +   gchar pref[16];
  1692. +   gchar *local_ufrag, *local_password;
  1693. +
  1694. +   nice_address_to_string(&cand->addr, address);
  1695. +   xmlnode_set_attrib(candidate, "address", address);
  1696. +   xmlnode_set_attrib(candidate, "port",
  1697. +       g_strdup_printf("%d", nice_address_get_port(&cand->addr)));
  1698. +   xmlnode_set_attrib(candidate, "name", share_session->channel_name);
  1699. +  
  1700. +   if(!cand->username) {
  1701. +       nice_agent_get_local_credentials(share_session->share_agent,
  1702. +                        share_session->stream_id,
  1703. +                        &local_ufrag, &local_password);
  1704. +       xmlnode_set_attrib(candidate, "username", local_ufrag);
  1705. +   }  
  1706. +   else
  1707. +       xmlnode_set_attrib(candidate, "username", cand->username);
  1708. +  
  1709. +   xmlnode_set_attrib(candidate, "password",
  1710. +       cand->password != NULL ? cand->password : "");
  1711. +   g_ascii_dtostr(pref, 16, cand->priority / 1000.0);
  1712. +   xmlnode_set_attrib(candidate, "preference", pref);
  1713. +   xmlnode_set_attrib(candidate, "protocol",
  1714. +       cand->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "udp" : "tcp");
  1715. +   xmlnode_set_attrib(candidate, "type",
  1716. +       cand->type == NICE_CANDIDATE_TYPE_HOST ? "host" :
  1717. +       cand->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ? "stun" :
  1718. +       cand->type == NICE_CANDIDATE_TYPE_RELAYED ? "relay" : "host");
  1719. +   xmlnode_set_attrib(candidate, "generation", "0");
  1720. +   xmlnode_set_attrib(candidate, "network", "0");
  1721. +
  1722. +   return candidate;
  1723. +}
  1724. +
  1725. +void
  1726. +cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer user_data)
  1727. +{
  1728. +   GoogleSession *session = (GoogleSession *)user_data;   
  1729. +   GoogleXferSessionData *share_session =
  1730. +       (GoogleXferSessionData *)session->session_data;
  1731. +   GSList *local_candidates = nice_agent_get_local_candidates(agent, stream_id, 1);
  1732. +  
  1733. +   purple_debug_info("google_session", "candidate gathering done!\n");
  1734. +   share_session->candidates_gathered = TRUE;
  1735. +
  1736. +   /* add remote candidates received while gathering local candidates */
  1737. +   nice_agent_set_remote_candidates(agent, share_session->stream_id, 1,
  1738. +                    share_session->remote_share_candidates);
  1739. +
  1740. +
  1741. +   while (share_session->remote_share_candidates) {
  1742. +       NiceCandidate *c =
  1743. +           (NiceCandidate *) share_session->remote_share_candidates->data;
  1744. +       nice_candidate_free(c);
  1745. +       share_session->remote_share_candidates =
  1746. +           g_slist_delete_link(share_session->remote_share_candidates,
  1747. +                       share_session->remote_share_candidates);
  1748. +   }
  1749. +      
  1750. +   /* Time to send local candidates. */
  1751. +   if (local_candidates) {
  1752. +       NiceCandidate *candidate = (NiceCandidate *) local_candidates->data;
  1753. +       JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
  1754. +       gchar *me = g_strdup_printf("%s@%s/%s",
  1755. +               session->js->user->node,
  1756. +               session->js->user->domain,
  1757. +               session->js->user->resource);
  1758. +      
  1759. +       /*Preparing the xml nodes for sending out candidates to gtalk*/
  1760. +       xmlnode *sess = google_session_create_xmlnode(session, "transport-info");
  1761. +       xmlnode *transport = xmlnode_new_child(sess, "transport");
  1762. +
  1763. +       xmlnode_insert_child(transport, nice_candidate_to_xml(candidate, share_session));
  1764. +       xmlnode_set_namespace(transport, NS_GOOGLE_TRANSPORT_P2P);
  1765. +
  1766. +       xmlnode_insert_child(iq->node, sess);
  1767. +       xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  1768. +       xmlnode_set_attrib(iq->node, "from", me);
  1769. +       jabber_iq_send(iq);
  1770. +
  1771. +       nice_candidate_free(candidate);
  1772. +       local_candidates = g_slist_delete_link(local_candidates, local_candidates);
  1773. +   }
  1774. +}
  1775. +
  1776. +static void
  1777. +gtalk_xfer_end(PurpleXfer *xfer)
  1778. +{
  1779. +   GoogleSession *session = (GoogleSession *) xfer->data;
  1780. +   JabberStream *js = session->js;
  1781. +   JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
  1782. +   xmlnode *complete_node, *session_node;
  1783. +
  1784. +   if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {    
  1785. +       xmlnode_set_attrib(iq->node, "to", session->remote_jid);   
  1786. +       session_node = xmlnode_new_child(iq->node, "session");
  1787. +       xmlnode_set_attrib(session_node, "type", "info");
  1788. +       xmlnode_set_attrib(session_node, "id", session->id.id);
  1789. +       xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
  1790. +       xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
  1791. +  
  1792. +       complete_node = xmlnode_new_child(session_node, "complete");
  1793. +       xmlnode_set_namespace(complete_node, NS_GOOGLE_SESSION_SHARE)
  1794. +       jabber_iq_send(iq);
  1795. +
  1796. +       gtalk_xfer_send_terminate(xfer);
  1797. +   }
  1798. +   else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
  1799. +       purple_debug_info("google_session", "XFER_SEND Ended..in gtalk_xfer_end\n");
  1800. +   }
  1801. +}
  1802. +
  1803. +
  1804. +static gssize
  1805. +gtalk_xfer_read(guchar **out_buffer, PurpleXfer *xfer)
  1806. +{
  1807. +   GoogleSession *session = (GoogleSession *) xfer->data;
  1808. +   GoogleXferSessionData *share_session =
  1809. +       (GoogleXferSessionData *)session->session_data;
  1810. +
  1811. +   guchar *buffer;
  1812. +   gsize size;
  1813. +   gsize tmp;
  1814. +
  1815. +   size = share_session->buffer->bufused;
  1816. +  
  1817. +   *out_buffer = buffer = g_malloc(size);
  1818. +   while ((tmp = purple_circ_buffer_get_max_read(share_session->buffer))) {
  1819. +       memcpy(buffer, share_session->buffer->outptr, tmp);
  1820. +       buffer += tmp;
  1821. +       purple_circ_buffer_mark_read(share_session->buffer, tmp);
  1822. +   }
  1823. +  
  1824. +   return size;
  1825. +}
  1826. +
  1827. +static char *
  1828. +nice_component_state_to_str(guint state)
  1829. +{
  1830. +   switch(state) {
  1831. +
  1832. +   case NICE_COMPONENT_STATE_DISCONNECTED : return "NICE_COMPONENT_STATE_DISCONNECTED";
  1833. +      
  1834. +   case NICE_COMPONENT_STATE_GATHERING : return "NICE_COMPONENT_STATE_GATHERING";
  1835. +
  1836. +   case NICE_COMPONENT_STATE_CONNECTING : return "NICE_COMPONENT_STATE_CONNECTING";
  1837. +
  1838. +   case NICE_COMPONENT_STATE_CONNECTED : return "NICE_COMPONENT_STATE_CONNECTED";
  1839. +
  1840. +   case NICE_COMPONENT_STATE_READY : return "NICE_COMPONENT_STATE_READY";
  1841. +
  1842. +   case NICE_COMPONENT_STATE_FAILED : return "NICE_COMPONENT_STATE_FAILED";
  1843. +
  1844. +   case NICE_COMPONENT_STATE_LAST : return "NICE_COMPONENT_STATE_LAST";
  1845. +
  1846. +   default: return "UNKOWN STATE";
  1847. +   }
  1848. +}
  1849. +
  1850. +void cb_nice_component_state_changed(NiceAgent *agent,guint stream_id,
  1851. +                    guint component_id,
  1852. +                    guint state, gpointer user_data)
  1853. +{
  1854. +   GoogleSession *session = (GoogleSession *)user_data;   
  1855. +   GoogleXferSessionData *share_session =
  1856. +       (GoogleXferSessionData *)session->session_data;
  1857. +   GSList *remote_candids =
  1858. +       nice_agent_get_remote_candidates(agent, stream_id, component_id);
  1859. +   GSList *local_candids =
  1860. +       nice_agent_get_local_candidates(agent, stream_id, component_id);
  1861. +   NiceCandidate *rcand, *lcand;
  1862. +   gchar *temp = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
  1863. +   gboolean selected_pair;
  1864. +
  1865. +   share_session->agent_state = state;
  1866. +  
  1867. +   purple_debug_info("google_session",
  1868. +             "State of NiceAgent Changed : [%d]%s.Stream ID: %d\n",
  1869. +             state, nice_component_state_to_str(state), stream_id);
  1870. +
  1871. +   if(state != NICE_COMPONENT_STATE_READY) {
  1872. +       return;
  1873. +   }
  1874. +  
  1875. +   selected_pair = nice_agent_get_selected_pair(share_session->share_agent,
  1876. +                            share_session->stream_id, 1,
  1877. +                            &lcand, &rcand);
  1878. +   if(selected_pair) {
  1879. +       purple_debug_info("google_session", "Selected Candidates : n");
  1880. +       nice_address_to_string(&lcand->addr, temp);
  1881. +       purple_debug_info("google_session", "LOCAL CAND : IP: %s, Port:%u\n"
  1882. +                 ,temp, nice_address_get_port(&lcand->addr));
  1883. +       nice_address_to_string(&rcand->addr, temp);
  1884. +       purple_debug_info("google_session", "REMOTE CAN : IP: %s, Port:%u\n",
  1885. +                 temp, nice_address_get_port(&rcand->addr));
  1886. +   }
  1887. +   else
  1888. +       purple_debug_info("google_session", "GETTING selected pair failed..\n");
  1889. +
  1890. +   g_free(temp);
  1891. +      
  1892. +   purple_debug_info("google_session", "List of remote candidates : \n");
  1893. +  
  1894. +   while(remote_candids) {
  1895. +       gchar *ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
  1896. +       NiceCandidate *c = (NiceCandidate *)remote_candids->data;
  1897. +       nice_address_to_string(&c->addr, ip);
  1898. +
  1899. +       purple_debug_info("google_session", "IP: %s, Port:%u\n",
  1900. +                 ip, nice_address_get_port(&c->addr));
  1901. +       remote_candids = remote_candids->next;
  1902. +   }
  1903. +   purple_debug_info("google_session", "***********\n");
  1904. +
  1905. +   purple_debug_info("google_session", "List of local candidates : \n");
  1906. +   while(local_candids) {
  1907. +       gchar *ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
  1908. +       NiceCandidate *c = (NiceCandidate *)local_candids->data;
  1909. +       nice_address_to_string(&c->addr, ip);
  1910. +
  1911. +       purple_debug_info("google_session", "IP: %s, Port:%u\n",
  1912. +                 ip, nice_address_get_port(&c->addr));
  1913. +       local_candids = local_candids->next;
  1914. +   }
  1915. +   purple_debug_info("google_session", "***********\n");                      
  1916. +      
  1917. +  
  1918. +   if(purple_xfer_get_type(share_session->xfer) == PURPLE_XFER_SEND &&
  1919. +      share_session->channel_state == GTALK_XFER_CHANNEL_HTTP_OK_SENT) {
  1920. +       share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_SENDING;
  1921. +       cb_nice_component_writable(share_session->share_agent,
  1922. +                      share_session->stream_id,
  1923. +                      1, share_session);
  1924. +   }
  1925. +  
  1926. +   if(state == NICE_COMPONENT_STATE_READY &&
  1927. +      purple_xfer_get_type(share_session->xfer) == PURPLE_XFER_RECEIVE) {
  1928. +
  1929. +     gint send_ret;
  1930. +     gchar *raw_filename = purple_strreplace(share_session->filename,
  1931. +                         " ","%20");
  1932. +     gchar *url = g_strdup_printf("%s%s", share_session->source_url,
  1933. +                      raw_filename);
  1934. +     gchar *request = g_strdup_printf("GET %s HTTP/1.1\r\n"
  1935. +                      "Connection: Keep-Alive\r\n"
  1936. +                      "Content-Length: 0\r\n"
  1937. +                      "Host: %s:0\r\n"
  1938. +                      "User-Agent: %s\r\n\r\n",
  1939. +                      url, session->remote_jid,
  1940. +                      "Google Talk");
  1941. +
  1942. +     purple_debug_info("google_session", "READY!\n");
  1943. +    
  1944. +     send_ret = nice_agent_send(share_session->share_agent,
  1945. +                    share_session->stream_id, 1,
  1946. +                    strlen(request), request);
  1947. +
  1948. +     if(send_ret > 0) {
  1949. +         share_session->channel_state = GTALK_XFER_CHANNEL_SENT_HTTP_GET;
  1950. +         purple_debug_info("google_session",
  1951. +                   "send_ret is %d, \nRequest is : \n%s\n",
  1952. +                   send_ret, request);    
  1953. +     }
  1954. +     else {
  1955. +         share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_GET_NOT_SENT;
  1956. +         purple_debug_info("google_session",
  1957. +                   "GET Request not sent. Waiting for writable.\n");
  1958. +     }
  1959. +    
  1960. +   }
  1961. +}
  1962. +
  1963. +static void
  1964. +gtalk_xfer_get_next_block(GoogleXferSessionData *share_session)
  1965. +{
  1966. +   int fread_ret;
  1967. +  
  1968. +   if(!share_session)
  1969. +       return;
  1970. +  
  1971. +   share_session->file_buf = malloc(1200);
  1972. +   fread_ret = fread(share_session->file_buf, 1, 1200, share_session->file_to_send);
  1973. +   share_session->file_buf_current_size = fread_ret;
  1974. +   share_session->file_buf_sent = 0;
  1975. +}
  1976. +
  1977. +void cb_nice_component_writable(NiceAgent *agent, guint stream_id,
  1978. +               guint component_id, gpointer user_data)  
  1979. +{
  1980. +   GoogleXferSessionData *share_session = (GoogleXferSessionData *)user_data;
  1981. +   PurpleXfer *xfer = share_session->xfer;
  1982. +  
  1983. +   char *file_buf = share_session->file_buf;
  1984. +   int send_ret;
  1985. +      
  1986. +   if(share_session->channel_state == GTALK_XFER_CHANNEL_HTTP_GET_NOT_SENT) {
  1987. +       gint send_ret;
  1988. +       GoogleSession *session = (GoogleSession *)xfer->data;
  1989. +       gchar *raw_filename = purple_strreplace(share_session->filename,
  1990. +                           " ","%20");
  1991. +       gchar *url = g_strdup_printf("%s%s",
  1992. +                        share_session->source_url,
  1993. +                        raw_filename);
  1994. +
  1995. +       gchar *request = g_strdup_printf("GET %s HTTP/1.1\r\n"
  1996. +                        "Connection: Keep-Alive\r\n"
  1997. +                        "Content-Length: 0\r\n"
  1998. +                        "Host: %s:0\r\n"
  1999. +                        "User-Agent: %s\r\n\r\n",
  2000. +                        url, session->remote_jid,
  2001. +                        "Google Talk");
  2002. +      
  2003. +       send_ret = nice_agent_send(share_session->share_agent,
  2004. +                      share_session->stream_id, 1,
  2005. +                      strlen(request), request);
  2006. +       purple_debug_info("google_session", "send_ret is %d, \nRequest is : \n%s\n",
  2007. +                 send_ret, request);      
  2008. +
  2009. +       if(send_ret > 0) { /*Considering this to be successful. Maybe add a check for response?*/
  2010. +           share_session->channel_state = GTALK_XFER_CHANNEL_SENT_HTTP_GET;
  2011. +           purple_debug_info("google_session",
  2012. +                     "Request is : %s with length %" G_GSIZE_FORMAT "\n",
  2013. +                     request, strlen(request));
  2014. +       }
  2015. +       else {
  2016. +           share_session->channel_state = GTALK_XFER_CHANNEL_HTTP_GET_NOT_SENT;
  2017. +           purple_debug_info("google_session",
  2018. +                     "GET Request not sent. Will wait for writable.\n");
  2019. +       }  
  2020. +   }
  2021. +
  2022. +   if(share_session->channel_state == GTALK_XFER_CHANNEL_HTTP_SENDING) {
  2023. +       if(share_session->file_buf == NULL) { /*This means that we should read the buffer*/
  2024. +           gtalk_xfer_get_next_block(share_session);
  2025. +           file_buf = share_session->file_buf;
  2026. +       }
  2027. +      
  2028. +       while (1) {
  2029. +
  2030. +           send_ret = nice_agent_send(share_session->share_agent,
  2031. +                          share_session->stream_id, 1,
  2032. +                          share_session->file_buf_current_size -
  2033. +                          share_session->file_buf_sent,
  2034. +                          file_buf+share_session->file_buf_sent);
  2035. +
  2036. +           if(send_ret<=0) {              
  2037. +               break;
  2038. +           }
  2039. +           else { //proper send_ret value
  2040. +               xfer->bytes_sent += send_ret;
  2041. +               xfer->bytes_remaining -= send_ret;
  2042. +               purple_xfer_update_progress(xfer);
  2043. +               share_session->file_buf_sent += send_ret;
  2044. +           }
  2045. +              
  2046. +           if(purple_xfer_get_bytes_remaining(xfer) <= 0) {
  2047. +               purple_debug_info("google_session",
  2048. +                         "File Successfully sent to GTalk!\n");
  2049. +               purple_xfer_set_completed(xfer, 1);
  2050. +               return;
  2051. +           }
  2052. +
  2053. +                  /*The following is equivalent to checking if send_ret is less
  2054. +          *than the no of bytes we wanted to send..
  2055. +          */
  2056. +           if(share_session->file_buf_current_size != share_session->file_buf_sent)
  2057. +               break;
  2058. +
  2059. +           if(share_session->file_buf_sent >= share_session->file_buf_current_size) {
  2060. +               free(file_buf);
  2061. +               share_session->file_buf = NULL;
  2062. +               share_session->file_buf_sent = 0;
  2063. +               share_session-> file_buf_current_size = 0;
  2064. +               gtalk_xfer_get_next_block(share_session);
  2065. +               file_buf = share_session->file_buf;
  2066. +           }
  2067. +       }
  2068. +   }
  2069. +}
  2070. +
  2071. +void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
  2072. +             gchar *lfoundation, gchar *rfoundation, gpointer user_data)
  2073. +{
  2074. +  purple_debug_info("google_session",
  2075. +           "Got a new selected pair with foundations : %s:%s\n",
  2076. +           lfoundation,
  2077. +           rfoundation);
  2078. +}
  2079. +
  2080. +static void
  2081. +gtalk_xfer_start(PurpleXfer *xfer)
  2082. +{
  2083. +   purple_debug_info("google_session", "Inside gtalk_xfer_start()\n");
  2084. +
  2085. +   if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
  2086. +       guchar *buffer = g_malloc( xfer->bytes_remaining );
  2087. +       int wrote = purple_xfer_write( xfer, buffer, xfer->bytes_remaining );
  2088. +
  2089. +       if ( wrote > 0 )
  2090. +           purple_xfer_set_bytes_sent( xfer, wrote );
  2091. +
  2092. +       /* free the buffer */
  2093. +       g_free( buffer );
  2094. +       buffer = NULL;
  2095. +   }
  2096. +}
  2097. +
  2098. +static GoogleSession *
  2099. +gtalk_xfer_new_session(JabberStream *js, const char *who)
  2100. +{
  2101. +   GoogleSession *session = g_new0(GoogleSession, 1);
  2102. +   GoogleXferSessionData *share_session = g_new0(GoogleXferSessionData, 1);
  2103. +   gchar *me = g_strdup_printf("%s@%s/%s",
  2104. +                   js->user->node,
  2105. +                   js->user->domain,
  2106. +                   js->user->resource);
  2107. +  
  2108. +
  2109. +   JabberBuddy *jb = jabber_buddy_find(js, who, FALSE);
  2110. +   JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, NULL);
  2111. +   gchar *jid;      
  2112. +  
  2113. +   if (!jbr) {
  2114. +       purple_debug_error("google_session",
  2115. +               "Could not find buddy's resource\n");
  2116. +   }
  2117. +
  2118. +   if ((strchr(who, '/') == NULL) && jbr && (jbr->name != NULL)) {
  2119. +       jid = g_strdup_printf("%s/%s", who, jbr->name);
  2120. +   } else {
  2121. +       jid = g_strdup(who);
  2122. +   }
  2123. +
  2124. +   share_session->buffer = purple_circ_buffer_new(65536);
  2125. +   session->id.id = jabber_get_next_id(js);
  2126. +   session->id.initiator = me;
  2127. +   session->share = 1;
  2128. +   session->session_data = share_session;
  2129. +  
  2130. +   session->state = UNINIT; /*TODO: Add similar state changes in the
  2131. +                  code for GoogleSession*/
  2132. +   session->js = js;
  2133. +   session->remote_jid = g_strdup(jid);
  2134. +
  2135. +   return session;
  2136. +}
  2137. +
  2138. +void
  2139. +gtalk_xfer_send(PurpleConnection *gc, const char *who, const char *file)
  2140. +{
  2141. +  PurpleXfer *xfer = NULL;
  2142. +  JabberStream *js = purple_connection_get_protocol_data(gc);
  2143. +
  2144. +  purple_debug_info("google_session", "INSIDE GTALK_XFER_SEND\n");
  2145. +  
  2146. +  if (file) {
  2147. +     purple_debug_info("google_session", "file is not NULL, %s\n", file);   
  2148. +     purple_xfer_request_accepted(xfer, file);
  2149. +  }
  2150. +  else {
  2151. +     GoogleSession *session = gtalk_xfer_new_session(js, who);  
  2152. +     GoogleXferSessionData *share_session =
  2153. +         (GoogleXferSessionData *)session->session_data;
  2154. +     session->state = SENT_INITIATE;
  2155. +
  2156. +     purple_debug_info("google_session", "File is NULL!\n");  
  2157. +     session->share = TRUE;
  2158. +
  2159. +     xfer = purple_xfer_new(purple_connection_get_account(gc),
  2160. +                PURPLE_XFER_SEND,
  2161. +                session->remote_jid);
  2162. +     js->gtalk_xfer_list = g_list_prepend(js->gtalk_xfer_list,
  2163. +                          share_session->xfer);
  2164. +
  2165. +     /*Setting up Stuff for XFER_SEND*/
  2166. +     purple_xfer_set_init_fnc(xfer, gtalk_xfer_init);
  2167. +     purple_xfer_set_request_denied_fnc(xfer,
  2168. +                        gtalk_xfer_request_denied);
  2169. +     purple_xfer_set_cancel_send_fnc(xfer, gtalk_xfer_cancel_xfer);
  2170. +/*   purple_xfer_set_write_fnc(xfer, gtalk_xfer_write);*/
  2171. +
  2172. +     xfer->data = session;
  2173. +     share_session->xfer = xfer;
  2174. +     purple_debug_info("google_session","xfer status :  %d\n",
  2175. +               purple_xfer_get_status(xfer));
  2176. +    
  2177. +     xfer->status = PURPLE_XFER_STATUS_NOT_STARTED;
  2178. +     purple_xfer_request(xfer);
  2179. +  }
  2180. +
  2181. +}
  2182. +
  2183. +static void
  2184. +gtalk_xfer_send_info(JabberStream *js, GoogleSession *session, xmlnode *sess)
  2185. +{
  2186. +
  2187. +   JabberIq *iq;
  2188. +   xmlnode *session_node, *channel_node;
  2189. +
  2190. +   purple_debug_info("google_session", "Inside google_xfer_send__accept\n");
  2191. +   iq = jabber_iq_new(js, JABBER_IQ_SET);
  2192. +   xmlnode_set_attrib(iq->node, "to", session->remote_jid);
  2193. +  
  2194. +   session_node = xmlnode_new_child(iq->node, "session");
  2195. +   xmlnode_set_attrib(session_node, "type", "info");
  2196. +   xmlnode_set_attrib(session_node, "id", xmlnode_get_attrib(sess, "id"));
  2197. +   xmlnode_set_attrib(session_node, "initiator", session->id.initiator);
  2198. +   xmlnode_set_namespace(session_node, NS_GOOGLE_SESSION);
  2199. +  
  2200. +   channel_node = xmlnode_new_child(session_node, "channel");
  2201. +   xmlnode_set_attrib(channel_node, "name", "private-1");
  2202. +   xmlnode_set_namespace(channel_node, NS_GOOGLE_SESSION_SHARE);
  2203. +  
  2204. +   jabber_iq_send(iq);
  2205. +}
  2206. +
  2207. +void
  2208. +gtalk_xfer_handle_initiate(JabberStream *js, GoogleSession *session,
  2209. +              xmlnode *sess, const char *iq_id)
  2210. +{
  2211. +       GoogleXferSessionData *share_session =
  2212. +           (GoogleXferSessionData *)session->session_data;    
  2213. +       xmlnode *description = xmlnode_get_child(sess, "description");
  2214. +       xmlnode *manifest,*file,*filename = NULL,*protocol,*http;
  2215. +       xmlnode *url_source_path,*url_preview_path,*transport;
  2216. +       guint filesize = 0;
  2217. +       JabberIq *result;
  2218. +
  2219. +       share_session = g_new0(GoogleXferSessionData, 1);
  2220. +
  2221. +       if( description ) {
  2222. +           manifest = xmlnode_get_child(description, "manifest");
  2223. +           if( manifest ) {
  2224. +               file = xmlnode_get_child(manifest, "file");
  2225. +               if( file ) {
  2226. +                   filename = xmlnode_get_child(file,
  2227. +                                    "name");
  2228. +                   filesize = atoi(xmlnode_get_attrib(file,
  2229. +                                      "size"));
  2230. +                   purple_debug_info("google_session",
  2231. +                             "File size : %d",filesize);
  2232. +                   share_session->filesize =
  2233. +                       g_ascii_strtoull(
  2234. +                           (gchar *)xmlnode_get_attrib(file, "size"),
  2235. +                           NULL,10);
  2236. +                   if( filename ) {
  2237. +                       purple_debug_info("google_session",
  2238. +                                 "Filename : %s",
  2239. +                                 xmlnode_get_data_unescaped(filename));
  2240. +                      
  2241. +                       share_session->filename =
  2242. +                           xmlnode_get_data_unescaped(filename);
  2243. +                   }
  2244. +                   else
  2245. +                       purple_debug_info("google_session",
  2246. +                                 "Filename is NULL");
  2247. +               }
  2248. +           }
  2249. +
  2250. +           protocol = xmlnode_get_child(description, "protocol");
  2251. +           if( protocol ) {
  2252. +               http = xmlnode_get_child(protocol, "http");
  2253. +               if( http ) {
  2254. +                   url_source_path = xmlnode_get_child(http, "url");
  2255. +                   if( url_source_path ) {
  2256. +                       purple_debug_info(
  2257. +                           "google_session",
  2258. +                           "url_source_path is not NULL. Name : %s",
  2259. +                           xmlnode_get_data_unescaped(url_source_path));
  2260. +
  2261. +                       share_session->source_url =
  2262. +                           xmlnode_get_data_unescaped(url_source_path);
  2263. +                   }
  2264. +                   url_preview_path = xmlnode_get_next_twin(url_source_path);
  2265. +                   if(url_preview_path) {
  2266. +                       purple_debug_info(
  2267. +                           "google_session",
  2268. +                           "url_source_preview is not NULL. Data : %s",
  2269. +                           xmlnode_get_data_unescaped(url_preview_path));
  2270. +
  2271. +                       share_session->preview_url =
  2272. +                           xmlnode_get_data_unescaped(url_preview_path);
  2273. +                   }
  2274. +               }
  2275. +           }
  2276. +          
  2277. +           transport = xmlnode_get_child(sess, "transport");
  2278. +       }
  2279. +       /*Add the GoogleSession *session to the GList*/
  2280. +      
  2281. +       share_session->xfer = purple_xfer_new(purple_connection_get_account(js->gc),
  2282. +                             PURPLE_XFER_RECEIVE,
  2283. +                             session->remote_jid);
  2284. +
  2285. +       js->gtalk_xfer_list = g_list_prepend(js->gtalk_xfer_list,
  2286. +                            share_session->xfer);
  2287. +
  2288. +       if(filename)
  2289. +           purple_xfer_set_filename(share_session->xfer,
  2290. +                        xmlnode_get_data_unescaped(filename));
  2291. +
  2292. +       purple_xfer_set_size(share_session->xfer, filesize);
  2293. +       /*Setting up stuff for XFER_RECEIVE*/
  2294. +       purple_xfer_set_init_fnc(share_session->xfer, gtalk_xfer_init);
  2295. +       purple_xfer_set_request_denied_fnc(share_session->xfer,
  2296. +                          gtalk_xfer_request_denied);
  2297. +       purple_xfer_set_cancel_recv_fnc(share_session->xfer,
  2298. +                       gtalk_xfer_cancel_xfer);
  2299. +       purple_xfer_set_read_fnc(share_session->xfer, gtalk_xfer_read);
  2300. +       purple_xfer_set_end_fnc(share_session->xfer, gtalk_xfer_end);
  2301. +      
  2302. +       share_session->xfer->data = session;
  2303. +       share_session->buffer = purple_circ_buffer_new(65536);
  2304. +
  2305. +       session->session_data = share_session;
  2306. +
  2307. +       result = jabber_iq_new(js,JABBER_IQ_RESULT);
  2308. +       xmlnode_set_attrib(result->node, "to", session->remote_jid);
  2309. +       jabber_iq_set_id(result, iq_id);
  2310. +       jabber_iq_send(result);
  2311. +              
  2312. +       if (js->google_relay_host && js->google_relay_token) {
  2313. +           jabber_google_do_relay_request(js, session,
  2314. +                              jabber_google_relay_response_session_initiate_cb);
  2315. +       } else {
  2316. +           jabber_google_relay_response_session_initiate_cb(session, NULL, 0, 0, 0,
  2317. +                                    NULL, NULL);
  2318. +       }
  2319. +       /*Ask the user to accept the file transfer*/
  2320. +       purple_xfer_request(share_session->xfer);
  2321. +       session->state = RECEIVED_INITIATE;
  2322. +}
  2323. diff --git a/libpurple/protocols/jabber/google/jingleinfo.c b/libpurple/protocols/jabber/google/jingleinfo.c
  2324. --- a/libpurple/protocols/jabber/google/jingleinfo.c
  2325. +++ b/libpurple/protocols/jabber/google/jingleinfo.c
  2326. @@ -58,7 +58,6 @@
  2327.  
  2328.         purple_debug_info("jabber", "set Google STUN IP/port address: "
  2329.                           "%s:%d\n", dst, port);
  2330. -
  2331.         /* unmark ongoing query */
  2332.         js->stun_query = NULL;
  2333.     }
  2334. diff --git a/libpurple/protocols/jabber/google/relay.c b/libpurple/protocols/jabber/google/relay.c
  2335. --- a/libpurple/protocols/jabber/google/relay.c
  2336. +++ b/libpurple/protocols/jabber/google/relay.c
  2337. @@ -62,12 +62,28 @@
  2338.  }
  2339.  
  2340.  static void
  2341. +jabber_google_relay_remove_url_data(JabberStream *js,
  2342. +   PurpleUtilFetchUrlData *url_data)
  2343. +{
  2344. +   GList *iter = js->google_relay_requests;
  2345. +
  2346. +   while (iter) {
  2347. +       if (iter->data == url_data) {
  2348. +           js->google_relay_requests =
  2349. +               g_list_delete_link(js->google_relay_requests, iter);
  2350. +           break;
  2351. +       }
  2352. +   }
  2353. +}
  2354. +
  2355. +static void
  2356.  jabber_google_relay_fetch_cb(PurpleHttpConnection *http_conn,
  2357.     PurpleHttpResponse *response, gpointer user_data)
  2358.  {
  2359.     JabberGoogleRelayCallbackData *data =
  2360.         (JabberGoogleRelayCallbackData *) user_data;
  2361.     GoogleSession *session = data->session;
  2362. +   JabberStream *js = session->js;
  2363.     JabberGoogleRelayCallback *cb = data->cb;
  2364.     gchar *relay_ip = NULL;
  2365.     guint relay_udp = 0;
  2366. @@ -104,6 +120,7 @@
  2367.  {
  2368.     PurpleHttpRequest *req;
  2369.     JabberGoogleRelayCallbackData *data = g_new0(JabberGoogleRelayCallbackData, 1);
  2370. +   session->relay_processing = TRUE;
  2371.  
  2372.     data->session = session;
  2373.     data->cb = cb;
  2374. diff --git a/libpurple/protocols/jabber/google/relay.h b/libpurple/protocols/jabber/google/relay.h
  2375. --- a/libpurple/protocols/jabber/google/relay.h
  2376. +++ b/libpurple/protocols/jabber/google/relay.h
  2377. @@ -30,4 +30,10 @@
  2378.  void jabber_google_do_relay_request(JabberStream *js, GoogleSession *session,
  2379.     JabberGoogleRelayCallback cb);
  2380.  
  2381. +
  2382. +typedef struct {
  2383. +   GoogleSession *session;
  2384. +   JabberGoogleRelayCallback *cb;
  2385. +} JabberGoogleRelayCallbackData;
  2386. +
  2387.  #endif /* JABBER_GOOGLE_RELAY */
  2388. diff --git a/libpurple/protocols/jabber/iq.c b/libpurple/protocols/jabber/iq.c
  2389. --- a/libpurple/protocols/jabber/iq.c
  2390. +++ b/libpurple/protocols/jabber/iq.c
  2391. @@ -572,10 +572,10 @@
  2392.             jabber_roster_parse);
  2393.     jabber_iq_register_handler("query", "jabber:iq:version",
  2394.             jabber_iq_version_parse);
  2395. -#ifdef USE_VV
  2396. +
  2397.     jabber_iq_register_handler("session", NS_GOOGLE_SESSION,
  2398.         jabber_google_session_parse);
  2399. -#endif
  2400. +
  2401.     jabber_iq_register_handler("block", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
  2402.     jabber_iq_register_handler("unblock", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
  2403.     jabber_iq_register_handler("time", NS_ENTITY_TIME, jabber_time_parse);
  2404. diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
  2405. --- a/libpurple/protocols/jabber/jabber.c
  2406. +++ b/libpurple/protocols/jabber/jabber.c
  2407. @@ -669,7 +669,7 @@
  2408.     else {
  2409.         gchar *tmp;
  2410.         if (len == 0)
  2411. -           tmp = g_strdup(_("Server closed the connection"));
  2412. +           tmp = g_strdup_printf(_("Server closed the connection"));
  2413.         else
  2414.             tmp = g_strdup_printf(_("Lost connection with server: %s"),
  2415.                     g_strerror(errno));
  2416. @@ -727,7 +727,7 @@
  2417.     } else {
  2418.         gchar *tmp;
  2419.         if (len == 0)
  2420. -           tmp = g_strdup(_("Server closed the connection"));
  2421. +           tmp = g_strdup_printf(_("Server closed the connection"));
  2422.         else
  2423.             tmp = g_strdup_printf(_("Lost connection with server: %s"),
  2424.                     g_strerror(errno));
  2425. @@ -3536,7 +3536,11 @@
  2426.          when actually trying */
  2427.         if (jb == NULL)
  2428.             return TRUE;
  2429. -
  2430. +       /* If the client on the other side is GoogleTalk, js->googletalk will be TRUE
  2431. +          We know for a fact it can receive file, so return TRUE
  2432. +       */
  2433. +       if (js->googletalk)
  2434. +           return TRUE;
  2435.         /* find out if there is any resources without caps */
  2436.         for (iter = jb->resources; iter ; iter = g_list_next(iter)) {
  2437.             JabberBuddyResource *jbr = (JabberBuddyResource *) iter->data;
  2438. @@ -3887,7 +3891,13 @@
  2439.  
  2440.     /* Jingle features! */
  2441.     jabber_add_feature(JINGLE, 0);
  2442. -
  2443. +   jabber_add_feature(JINGLE_APP_FT, 0);
  2444. +   jabber_add_feature(JINGLE_TRANSPORT_S5B, 0);
  2445. +   jabber_add_feature(JINGLE_TRANSPORT_IBB, 0);
  2446. +
  2447. +   /* Google Talk File Transfer*/
  2448. +   jabber_add_feature(NS_GOOGLE_SHARE,0);
  2449. +  
  2450.  #ifdef USE_VV
  2451.     jabber_add_feature(NS_GOOGLE_PROTOCOL_SESSION, jabber_audio_enabled);
  2452.     jabber_add_feature(NS_GOOGLE_VOICE, jabber_audio_enabled);
  2453. diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h
  2454. --- a/libpurple/protocols/jabber/jabber.h
  2455. +++ b/libpurple/protocols/jabber/jabber.h
  2456. @@ -198,6 +198,9 @@
  2457.  
  2458.     JabberCapabilities server_caps;
  2459.     gboolean googletalk;
  2460. +   GList *google_share_sessions;
  2461. +   GList *gtalk_xfer_list;
  2462. +  
  2463.     char *server_name;
  2464.  
  2465.     char *gmail_last_time;
  2466. diff --git a/libpurple/protocols/jabber/namespaces.h b/libpurple/protocols/jabber/namespaces.h
  2467. --- a/libpurple/protocols/jabber/namespaces.h
  2468. +++ b/libpurple/protocols/jabber/namespaces.h
  2469. @@ -99,6 +99,7 @@
  2470.  #define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
  2471.  #define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
  2472.  #define NS_GOOGLE_VOICE "http://www.google.com/xmpp/protocol/voice/v1"
  2473. +#define NS_GOOGLE_SHARE "http://www.google.com/xmpp/protocol/share/v1"
  2474.  #define NS_GOOGLE_JINGLE_INFO "google:jingleinfo"
  2475.  
  2476.  #define NS_GOOGLE_MAIL_NOTIFY "google:mail:notify"
  2477. @@ -108,6 +109,8 @@
  2478.  #define NS_GOOGLE_SESSION "http://www.google.com/session"
  2479.  #define NS_GOOGLE_SESSION_PHONE "http://www.google.com/session/phone"
  2480.  #define NS_GOOGLE_SESSION_VIDEO "http://www.google.com/session/video"
  2481. +#define NS_GOOGLE_SESSION_SHARE "http://www.google.com/session/share"
  2482. +#define NS_GOOGLE_TRANSPORT_P2P "http://www.google.com/transport/p2p"
  2483.  
  2484.  #define NS_GOOGLE_TRANSPORT_P2P "http://www.google.com/transport/p2p"
  2485.  
  2486. diff --git a/libpurple/protocols/jabber/parser.c b/libpurple/protocols/jabber/parser.c
  2487. --- a/libpurple/protocols/jabber/parser.c
  2488. +++ b/libpurple/protocols/jabber/parser.c
  2489. @@ -272,9 +272,11 @@
  2490.     int ret;
  2491.  
  2492.     if (js->context == NULL) {
  2493. +    
  2494.         /* libxml inconsistently starts parsing on creating the
  2495.          * parser, so do a ParseChunk right afterwards to force it. */
  2496.         js->context = xmlCreatePushParserCtxt(&jabber_parser_libxml, js, buf, len, NULL);
  2497. +
  2498.         xmlParseChunk(js->context, "", 0, 0);
  2499.     } else if ((ret = xmlParseChunk(js->context, buf, len, 0)) != XML_ERR_OK) {
  2500.         xmlError *err = xmlCtxtGetLastError(js->context);
  2501. diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c
  2502. --- a/libpurple/protocols/jabber/presence.c
  2503. +++ b/libpurple/protocols/jabber/presence.c
  2504. @@ -352,7 +352,7 @@
  2505.     purple_xmlnode_set_attrib(c, "node", CAPS0115_NODE);
  2506.     purple_xmlnode_set_attrib(c, "hash", "sha-1");
  2507.     purple_xmlnode_set_attrib(c, "ver", jabber_caps_get_own_hash(js));
  2508. -
  2509. +   purple_xmlnode_set_attrib(c, "ext", "share-v1");
  2510.  #ifdef USE_VV
  2511.     /*
  2512.      * MASSIVE HUGE DISGUSTING HACK
  2513. @@ -363,16 +363,18 @@
  2514.      * calls.
  2515.      *
  2516.      * Ditto for 'video-v1'.
  2517. +    *
  2518. +    * Ditto for 'share-v1' for supporting file transfers.
  2519.      */
  2520.     audio_enabled = jabber_audio_enabled(js, NULL /* unused */);
  2521.     video_enabled = jabber_video_enabled(js, NULL /* unused */);
  2522.  
  2523.     if (audio_enabled && video_enabled)
  2524. -       purple_xmlnode_set_attrib(c, "ext", "voice-v1 camera-v1 video-v1");
  2525. +       xmlnode_set_attrib(c, "ext", "voice-v1 camera-v1 video-v1 share-v1");
  2526.     else if (audio_enabled)
  2527. -       purple_xmlnode_set_attrib(c, "ext", "voice-v1");
  2528. +       xmlnode_set_attrib(c, "ext", "voice-v1 share-v1");
  2529.     else if (video_enabled)
  2530. -       purple_xmlnode_set_attrib(c, "ext", "camera-v1 video-v1");
  2531. +       xmlnode_set_attrib(c, "ext", "camera-v1 video-v1 share-v1");
  2532.  #endif
  2533.  
  2534.     return presence;
  2535. diff --git a/libpurple/protocols/jabber/si.c b/libpurple/protocols/jabber/si.c
  2536. --- a/libpurple/protocols/jabber/si.c
  2537. +++ b/libpurple/protocols/jabber/si.c
  2538. @@ -38,6 +38,7 @@
  2539.  #include "ibb.h"
  2540.  #include "iq.h"
  2541.  #include "si.h"
  2542. +#include "google/google_session.h"
  2543.  
  2544.  #define STREAMHOST_CONNECT_TIMEOUT 15
  2545.  #define ENABLE_FT_THUMBNAILS 0
  2546. @@ -1654,6 +1655,16 @@
  2547.  void jabber_si_xfer_send(PurpleConnection *gc, const char *who, const char *file)
  2548.  {
  2549.     PurpleXfer *xfer;
  2550. +   JabberStream *js = purple_connection_get_protocol_data(gc);
  2551. +
  2552. +   if(js->googletalk) {
  2553. +     purple_debug_info("jabber", "Found Google Talk. Try to Send File Now..");
  2554. +     /*TODO: Rename the gtalk_xfer_send function most probably ALSO, isn't file always NULL for googletalk?*/
  2555. +     gtalk_xfer_send(gc, who, file);
  2556. +     return;
  2557. +   }
  2558. +   else
  2559. +     purple_debug_info("Jabber", "Not Google Talk..Something is Broken..\n");
  2560.  
  2561.     xfer = jabber_si_new_xfer(gc, who);
  2562.  
  2563. diff --git a/libpurple/protocols/yahoo/yahoo_filexfer.c b/libpurple/protocols/yahoo/yahoo_filexfer.c
  2564. --- a/libpurple/protocols/yahoo/yahoo_filexfer.c
  2565. +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c
  2566. @@ -482,10 +482,10 @@
  2567.  {
  2568.     gchar *ans;
  2569.     int i,j;
  2570. -   ans = g_strnfill(24, ' ');
  2571. -   ans[23] = '$';
  2572. -   ans[22] = '$';
  2573. -   for(i = 0; i < 22; i++)
  2574. +   ans = g_strnfill(44, ' ');
  2575. +   ans[43] = '=';
  2576. +
  2577. +   for(i = 0; i < 43; i++)
  2578.     {
  2579.         j = g_random_int_range (0,61);
  2580.         if(j < 26)
  2581. diff --git a/libpurple/xfer.c b/libpurple/xfer.c
  2582. --- a/libpurple/xfer.c
  2583. +++ b/libpurple/xfer.c
  2584. @@ -1585,8 +1585,8 @@
  2585.         purple_debug_misc("xfer", "prpl is ready on ft %p, waiting for UI\n", xfer);
  2586.         return;
  2587.     }
  2588. -
  2589. -   purple_debug_misc("xfer", "Prpl (and UI) ready on ft %p, so proceeding\n", xfer);
  2590. +   /*TODO: Commented out as this gives many messages while transferring a file from Gtalk to pidgin*/
  2591. +   //purple_debug_misc("xfer", "Prpl (and UI) ready on ft %p, so proceeding\n", xfer);
  2592.  
  2593.     priv->ready = PURPLE_XFER_READY_NONE;
  2594.  
  2595. diff --git a/libpurple/xfer.h b/libpurple/xfer.h
  2596. --- a/libpurple/xfer.h
  2597. +++ b/libpurple/xfer.h
  2598. @@ -97,6 +97,7 @@
  2599.      *
  2600.      * @return size if the write was successful, or a value between 0 and
  2601.      *         size on error.
  2602. +    * @since 2.6.0
  2603.      */
  2604.     gssize (*ui_write)(PurpleXfer *xfer, const guchar *buffer, gssize size);
  2605.  
  2606. @@ -111,6 +112,7 @@
  2607.      * @returns The amount of data in the buffer, 0 if nothing is available,
  2608.      *          and a negative value if an error occurred and the transfer
  2609.      *          should be cancelled (libpurple will cancel).
  2610. +    * @since 2.6.0
  2611.      */
  2612.     gssize (*ui_read)(PurpleXfer *xfer, guchar **buffer, gssize size);
  2613.  
  2614. @@ -123,6 +125,8 @@
  2615.      * @param xfer    The file transfer structure
  2616.      * @param buffer  A pointer to the beginning of the unwritten data.
  2617.      * @param size    The amount of unwritten data.
  2618. +    *
  2619. +    * @since 2.6.0
  2620.      */
  2621.     void (*data_not_sent)(PurpleXfer *xfer, const guchar *buffer, gsize size);
  2622.  
  2623. @@ -174,6 +178,9 @@
  2624.  /**
  2625.   * Creates a new file transfer handle.
  2626.   * This is called by prpls.
  2627. + * The handle starts with a ref count of 1, and this reference
  2628. + * is owned by the core. The prpl normally does not need to
  2629. + * purple_xfer_ref or unref.
  2630.   *
  2631.   * @param account The account sending or receiving the file.
  2632.   * @param type    The type of file transfer.
  2633. @@ -185,6 +192,32 @@
  2634.                                 PurpleXferType type, const char *who);
  2635.  
  2636.  /**
  2637. + * Returns all xfers
  2638. + *
  2639. + * @return all current xfers with refs
  2640. + */
  2641. +GList *purple_xfers_get_all(void);
  2642. +
  2643. +/**
  2644. + * Increases the reference count on a PurpleXfer.
  2645. + * Please call purple_xfer_unref later.
  2646. + *
  2647. + * @param xfer A file transfer handle.
  2648. + */
  2649. +void purple_xfer_ref(PurpleXfer *xfer);
  2650. +
  2651. +/**
  2652. + * Decreases the reference count on a PurpleXfer.
  2653. + * If the reference reaches 0, purple_xfer_destroy (an internal function)
  2654. + * will destroy the xfer. It calls the ui destroy cb first.
  2655. + * Since the core keeps a ref on the xfer, only an erroneous call to
  2656. + * this function will destroy the xfer while still in use.
  2657. + *
  2658. + * @param xfer A file transfer handle.
  2659. + */
  2660. +void purple_xfer_unref(PurpleXfer *xfer);
  2661. +
  2662. +/**
  2663.   * Requests confirmation for a file transfer from the user. If receiving
  2664.   * a file which is known at this point, this requests user to accept and
  2665.   * save the file. If the filename is unknown (not set) this only requests user
  2666. @@ -260,6 +293,8 @@
  2667.   * @param xfer The file transfer.
  2668.   *
  2669.   * @return The name of the remote user.
  2670. + *
  2671. + * @since 2.1.0
  2672.   */
  2673.  const char *purple_xfer_get_remote_user(const PurpleXfer *xfer);
  2674.  
  2675. @@ -278,6 +313,7 @@
  2676.   * @param xfer The file transfer.
  2677.   *
  2678.   * @return Whether or not the transfer was cancelled.
  2679. + * FIXME: This should be renamed using cancelled for 3.0.0.
  2680.   */
  2681.  gboolean purple_xfer_is_cancelled(const PurpleXfer *xfer);
  2682.  
  2683. @@ -379,6 +415,7 @@
  2684.   * @param xfer  The file transfer.
  2685.   *
  2686.   * @return The time when the transfer started.
  2687. + * @since 2.4.0
  2688.   */
  2689.  time_t purple_xfer_get_start_time(const PurpleXfer *xfer);
  2690.  
  2691. @@ -388,6 +425,7 @@
  2692.   * @param xfer  The file transfer.
  2693.   *
  2694.   * @return The time when the transfer ended.
  2695. + * @since 2.4.0
  2696.   */
  2697.  time_t purple_xfer_get_end_time(const PurpleXfer *xfer);
  2698.  
  2699. @@ -705,6 +743,8 @@
  2700.   * read/write/data_not_sent UI ops.
  2701.   *
  2702.   * @param xfer The file transfer which is ready.
  2703. + *
  2704. + * @since 2.6.0
  2705.   */
  2706.  void purple_xfer_ui_ready(PurpleXfer *xfer);
  2707.  
  2708. @@ -714,6 +754,8 @@
  2709.   * ops and cannot/does not provide a raw fd to the core.
  2710.   *
  2711.   * @param xfer The file transfer which is ready.
  2712. + *
  2713. + * @since 2.6.0
  2714.   */
  2715.  void purple_xfer_prpl_ready(PurpleXfer *xfer);
  2716.  
  2717. @@ -724,6 +766,7 @@
  2718.   * @param len  If not @c NULL, the length of the thumbnail data returned
  2719.   *             will be set in the location pointed to by this.
  2720.   * @return The thumbnail data, or NULL if there is no thumbnail
  2721. + * @since 2.7.0
  2722.   */
  2723.  gconstpointer purple_xfer_get_thumbnail(const PurpleXfer *xfer, gsize *len);
  2724.  
  2725. @@ -732,6 +775,7 @@
  2726.   *
  2727.   * @param xfer The file transfer to get the mimetype for
  2728.   * @return The mimetype of the thumbnail, or @c NULL if not thumbnail is set
  2729. + * @since 2.7.0
  2730.   */
  2731.  const gchar *purple_xfer_get_thumbnail_mimetype(const PurpleXfer *xfer);
  2732.  
  2733. @@ -743,6 +787,7 @@
  2734.   * @param thumbnail A pointer to the thumbnail data, this will be copied
  2735.   * @param size The size in bytes of the passed in thumbnail data
  2736.   * @param mimetype The mimetype of the generated thumbnail
  2737. + * @since 2.7.0
  2738.   */
  2739.  void purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail,
  2740.     gsize size, const gchar *mimetype);
  2741. @@ -754,6 +799,7 @@
  2742.   * @param xfer The file transfer to create a thumbnail for
  2743.   * @param formats A comma-separated list of mimetypes for image formats
  2744.   *       the protocols can use for thumbnails.
  2745. + * @since 2.7.0
  2746.   */
  2747.  void purple_xfer_prepare_thumbnail(PurpleXfer *xfer, const gchar *formats);
  2748.  
  2749. diff --git a/libpurple/xmlnode.c b/libpurple/xmlnode.c
  2750. --- a/libpurple/xmlnode.c
  2751. +++ b/libpurple/xmlnode.c
  2752. @@ -210,6 +210,7 @@
  2753.  
  2754.     g_return_if_fail(node != NULL);
  2755.     g_return_if_fail(attr != NULL);
  2756. +   if(!value) purple_debug_info("google_session", "Name of attribute/prefix we tried to set : %s/%s\n", attr, prefix);
  2757.     g_return_if_fail(value != NULL);
  2758.  
  2759.     purple_xmlnode_remove_attrib_with_namespace(node, attr, xmlns);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement