Advertisement
tomkiewicz

another-diff

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