/soc/2013/ashmew2/filetransferX: d7ce402599aa: Putting in HTTP G...

Ashish Gupta ashmew2 at gmail.com
Tue Aug 20 19:07:21 EDT 2013


Changeset: d7ce402599aa520b15ca994f8437a21520eec621
Author:	 Ashish Gupta <ashmew2 at gmail.com>
Date:	 2013-08-21 00:01 +0530
Branch:	 filetransferX
URL: https://hg.pidgin.im/soc/2013/ashmew2/filetransferX/rev/d7ce402599aa

Description:

Putting in HTTP GET response handling

diffstat:

 libpurple/protocols/jabber/google/google_session.c |  241 ++++++++++++++++----
 1 files changed, 189 insertions(+), 52 deletions(-)

diffs (truncated from 357 to 300 lines):

diff --git a/libpurple/protocols/jabber/google/google_session.c b/libpurple/protocols/jabber/google/google_session.c
--- a/libpurple/protocols/jabber/google/google_session.c
+++ b/libpurple/protocols/jabber/google/google_session.c
@@ -50,6 +50,12 @@ typedef struct {
 	guint read_len;
 } ShareChannel;
 
+typedef enum {
+	GTALK_XFER_CHANNEL_INITIALIZED = 0,
+	GTALK_XFER_CHANNEL_SENT_HTTP_GET,
+	GTALK_XFER_CHANNEL_PARSED_HTTP_RESPONSE_HEADER
+} GoogleXferChannelState;
+
 typedef struct {
 	gchar *filename;                            /*File Details*/
 	guint64 filesize;
@@ -62,11 +68,12 @@ typedef struct {
 	gchar *channel_name;
 	NiceComponentState agent_state;
 	PurpleCircBuffer *buffer; /*Need to add something for HTTP_STATUS too */
+	GoogleXferChannelState channel_state;
 	guint stream_id;
 	gboolean candidates_gathered;
+	gboolean pair_selected;
 	GList *remote_share_candidates; /* lists of PurpleMediaCandidate OR NiceCandidates(maybe?)*/
-	GList *local_share_candidates;
-	
+	GList *local_share_candidates;	
 } GoogleXferSessionData; 
 /*Thanks malu!*/
 
@@ -448,7 +455,7 @@ jabber_google_relay_response_session_ini
 		if(!share_session->share_agent) {/*TODO: Should probably have an agent_init function for this..Later..*/
 			purple_xfer_request(share_session->xfer);
 			
-			agent = nice_agent_new_reliable (g_main_context_default(), NICE_COMPATIBILITY_RFC5245);			
+			agent = nice_agent_new_reliable (g_main_context_default(), NICE_COMPATIBILITY_GOOGLE);			
 			share_session->share_agent = agent;
 			share_session->stream_id = nice_agent_add_stream(agent, 1);
 			stream_id = share_session->stream_id;
@@ -483,15 +490,41 @@ jabber_google_relay_response_session_ini
 			g_signal_connect(G_OBJECT(agent), "reliable-transport-writable",
 					 G_CALLBACK(cb_nice_component_writable), session);
 			g_signal_connect(G_OBJECT(agent), "component-state-changed",
-					 G_CALLBACK(cb_nice_component_state_changed), share_session);
+					 G_CALLBACK(cb_nice_component_state_changed), session);
 			/*Add relay candidates to our candidate list?*/
 /*		            * candidate address='49.248.181.68' port='46448' username='HKmLfAkZB81f7r8x' password='' preference='0.000000' protocol='udp' type='stun' component='1' network='0' generation='0' name='private-1'
  */
-			purple_debug_info("google_session", "share_agent is NULL in relab_cb! Returning..\n");
+			purple_debug_info("google_session", "share_agent is NULL in relab_cb! Adding relay candids manually ..\n");
 /*Set up other stuff for NiceAgent TODO*/
 /*TODO : Return for now, trying to receive a file from GTalk, otherwise we went on with the relay_candidate_* set up..*/
 /*TODO: The point here is that the share_agent will ALWAYS BE NULL when receiving a file because we are not changing it in
   handle_initiate() */
+
+			relay_candidate_udp = nice_candidate_new(NICE_CANDIDATE_TYPE_RELAYED);
+			relay_candidate_udp->transport = NICE_CANDIDATE_TRANSPORT_UDP;
+			relay_candidate_udp->priority = 0;
+			relay_candidate_udp->stream_id = stream_id;
+			relay_candidate_udp->username = g_strdup_printf("%s",relay_username);
+			relay_candidate_udp->password = g_strdup_printf("%s",relay_password);
+			nice_address_set_from_string(&relay_candidate_udp->addr, relay_ip);
+			nice_address_set_port(&relay_candidate_udp->addr, relay_udp);
+			relay_candidate_udp->turn = g_new0(TurnServer, 1);
+			nice_address_set_from_string(&relay_candidate_udp->turn->server, relay_ip);
+			relay_candidate_udp->turn->type = NICE_RELAY_TYPE_TURN_UDP;
+			relay_candidate_udp->turn->username = g_strdup_printf("%s",relay_username);
+			relay_candidate_udp->turn->password = g_strdup_printf("%s",relay_password);
+			
+			relay_candidate_tcp = nice_candidate_copy(relay_candidate_udp);
+			nice_address_set_port(&relay_candidate_tcp->addr, relay_tcp);
+			
+			relay_candidate_ssltcp = nice_candidate_copy(relay_candidate_udp);
+			nice_address_set_port(&relay_candidate_ssltcp->addr, relay_ssltcp);
+			
+			share_session->local_share_candidates = g_list_append(share_session->local_share_candidates, relay_candidate_udp);
+//			share_session->local_share_candidates = g_list_append(share_session->local_share_candidates, relay_candidate_tcp);
+//			share_session->local_share_candidates = g_list_append(share_session->local_share_candidates, relay_candidate_ssltcp);
+			
+			purple_debug_info("google_session", "Added relay candidates without a crash.\n");
 			return;
 		}
 		else {
@@ -499,31 +532,6 @@ jabber_google_relay_response_session_ini
 		}
 /*TODO: Add candidates here to the local_candidates GList in GoogleXferSessionData;*/
 		
-		relay_candidate_udp = nice_candidate_new(NICE_CANDIDATE_TYPE_RELAYED);
-		relay_candidate_udp->transport = NICE_CANDIDATE_TRANSPORT_UDP;
-		relay_candidate_udp->priority = 0;
-		relay_candidate_udp->stream_id = stream_id;
-		relay_candidate_udp->username = g_strdup_printf("%s",relay_username);
-		relay_candidate_udp->password = g_strdup_printf("%s",relay_password);
-		nice_address_set_from_string(&relay_candidate_udp->addr, relay_ip);
-		nice_address_set_port(&relay_candidate_udp->addr, relay_udp);
-		relay_candidate_udp->turn = g_new0(TurnServer, 1);
-		nice_address_set_from_string(&relay_candidate_udp->turn->server, relay_ip);
-		relay_candidate_udp->turn->type = NICE_RELAY_TYPE_TURN_UDP;
-		relay_candidate_udp->turn->username = g_strdup_printf("%s",relay_username);
-		relay_candidate_udp->turn->password = g_strdup_printf("%s",relay_password);
-
-		relay_candidate_tcp = nice_candidate_copy(relay_candidate_udp);
-		nice_address_set_port(&relay_candidate_tcp->addr, relay_tcp);
-
-		relay_candidate_ssltcp = nice_candidate_copy(relay_candidate_udp);
-		nice_address_set_port(&relay_candidate_ssltcp->addr, relay_ssltcp);
-		
-		share_session->local_share_candidates = g_list_append(share_session->local_share_candidates, relay_candidate_udp);
-		share_session->local_share_candidates = g_list_append(share_session->local_share_candidates, relay_candidate_tcp);
-		share_session->local_share_candidates = g_list_append(share_session->local_share_candidates, relay_candidate_ssltcp);
-
-		purple_debug_info("google_session", "Added relay candidates without a crash.\n");
 
 /*		purple_debug_info("google_session", "Trying to Set Relay IP : %s\n", relay_ip);*/
 		if (relay_ip) {
@@ -1279,11 +1287,13 @@ static void
 google_session_handle_transport_info(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
 {
 	GoogleAVSessionData *session_data = (GoogleAVSessionData *)session->session_data;
+	GoogleXferSessionData *share_session = session_data->share_session;
 	purple_debug_info("google_session", "Inside handle_transport_info..\n");
 
-	if(session_data->share)
+	if(session_data->share && !share_session->pair_selected)
 		gtalk_xfer_handle_candidates(js, session, sess, iq_id);
-	else
+
+	if(!session_data->share)
 		google_session_handle_candidates(js, session, sess, iq_id);
 }
 
@@ -1693,11 +1703,116 @@ Call gtalk_xfer_send_candidates() Here .
 gtalk_xfer_send_candidates(session);*/
 }
 
+
+/* If buffer contains a line ending, 0-terminate the first line and
+ * return a pointer to the beginning of the next line. Otherwise
+ * return NULL. */
+
+gchar *
+http_read_line(gchar *buffer, guint len) {
+
+	gchar *p = memchr(buffer, '\n', len);
+
+        /* Looking for a CRLF basically */
+
+	if (p != NULL) {
+		*p = 0;
+		if (p > buffer && *(p-1) == '\r')
+			*(p-1) = '\0';
+		p++;
+	}
+	
+	return p;
+}
+
+gssize
+gtalk_xfer_read(guchar **out_buffer, PurpleXfer *xfer)
+{
+	GoogleSession *session = (GoogleSession *) xfer->data;
+	GoogleAVSessionData *session_data =
+		(GoogleShareSessionData *) session->session_data;
+	GoogleXferSessionData *share_session = session_data->share_session;
+
+	guchar *buffer;
+	gsize size;
+	gsize tmp;
+
+	size = share_session->buffer->bufused;
+
+	*out_buffer = buffer = g_malloc(size);
+	while ((tmp = purple_circ_buffer_get_max_read(session_data->buffer))) {
+		memcpy(buffer, session_data->buffer->outptr, tmp);
+		buffer += tmp;
+		purple_circ_buffer_mark_read(session_data->buffer, tmp);
+	}
+
+	return size;
+}
+
 void
 cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id,
     guint len, gchar *buf, gpointer data)
 {
-	purple_debug_info("google_session", "__Inside cb_nice_recv\n");
+/*The overall process is to first send a GET Request. Then wait for the response headers . Then, once the response headers are received, 
+  The actual file starts to flow. At that time, we simply start our xfer to read the inbound data!*/
+   purple_debug_info("google_session", "Received : \n%s\n", buf);
+   
+   if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
+	   if (session_data->channel_state ==
+	       GTALK_XFER_CHANNEL_SENT_HTTP_GET) {
+		   gchar *tmp;
+		   gsize read_len;
+				
+		   do {
+			   tmp = http_read_line(curr, len);
+			   read_len = tmp - curr;
+				
+			   purple_debug_info("google_session", "HTTP response header received : %s\n", curr);
+
+			   len -= read_len;
+			   curr += read_len;
+
+			   if (g_ascii_strncasecmp(curr, "HTTP/1.1", 8)) {
+				   if (purple_strequal(curr + 9, "404")) {
+					   /* got a 404 (file not found) stop... */
+					   /* TODO: Terminate the session gracefully as 404 happened? That means source_url
+					    is bugged. Starting the Xfer over again might be the only option. */
+				   }
+			   }
+			   /* TODO: check Content-Length and other headers too? */
+				
+		   } while (curr[0] != '\0' && len > 0);
+
+		   if (curr[0] == '\0') {
+			   /* we found the end of the headers */
+			   purple_debug_info("google_session", "Headers End here..(Blank Line encountered)\n");
+
+			   session_data->channel_state =
+				   GTALK_XFER_CHANNEL_PARSED_HTTP_RESPONSE_HEADER;
+			   purple_xfer_start(xfer, -1, NULL, 0);
+		   }
+		   /* otherwise the remaining headers would come in the next package
+		      not sure if this will ever happen */
+				
+	   } else if (session_data->channel_state ==
+		      GOOGLE_SHARE_CHANNEL_PARSED_HTTP_RESPONSE_HEADER) {
+		   /* write data to transfer */
+		   purple_debug_info("google-share",
+				     "got %d bytes to write to transfer\n", len);
+
+		   if (len <= purple_xfer_get_bytes_remaining(xfer)) {
+			   purple_circ_buffer_append(session_data->buffer, curr, len);
+			   purple_xfer_prpl_ready(xfer);
+		   } else {
+			   purple_debug_error("google-share",
+					      "trying to write past end of file\n");
+			   purple_xfer_cancel_remote(xfer);
+		   }
+	   }
+   } else {
+
+   }
+}
 }
 
 char *nice_component_state_to_str(guint state)
@@ -1725,21 +1840,48 @@ char *nice_component_state_to_str(guint 
 void cb_nice_component_state_changed(NiceAgent *agent,guint stream_id, guint component_id,
 				      guint state, gpointer user_data)
 {
-	GoogleXferSessionData *share_session = (GoogleXferSessionData *)user_data;
+	GoogleSession *session = (GoogleSession *)user_data;
+	GoogleAVSessionData *session_data = session->session_data;
+	GoogleXferSessionData *share_session = session_data->share_session;
+
 	share_session->agent_state = state;
 
 	purple_debug_info("google_session", "__State of NiceAgent Changed...Current State : [%d]%s.Stream ID: %d\n", state, nice_component_state_to_str(state), stream_id);
-	if(state == NICE_COMPONENT_STATE_CONNECTED) {
+
+	if(state == NICE_COMPONENT_STATE_READY) {
+	  purple_debug_info("google_session", "READY!\n");
+	  gint send_ret;
+	  JabberStream *js = session->js;
+	  gchar *url = g_strdup_printf("%s%s", share_session->source_url, share_session->filename);
+	  gchar *request = g_strdup_printf("GET %s HTTP/1.1\r\n"
+		"Connection: Keep-Alive\r\n"
+	    "Content-Length: 0\r\n"
+	    "Host: %s@%s/%s:0\r\n"
+	    "User-Agent: %s\r\n\r\n", url, js->user->node, js->user->domain,
+	    js->user->resource, "Pidgin 2.10.7"); 
+
+	  send_ret = nice_agent_send(share_session->share_agent, share_session->stream_id, 1,
+			  strlen(request), request);
+	  share_session->channel_state = GTALK_XFER_CHANNEL_SENT_HTTP_GET;
+	  purple_debug_info("google_session", "send_ret is %d, Request is : \n%s\n",send_ret, request);	    
+	}
+/*	else if(state == NICE_COMPONENT_STATE_CONNECTED && !share_session->pair_selected) {/*
 		GSList *remote_candids = nice_agent_get_remote_candidates(agent, stream_id, component_id);
-		GSList *local_candids = nice_agent_get_local_candidates(agent, stream_id, component_id);
-		NiceCandidate *rc = (NiceCandidate *)remote_candids->data;
+		GSList *local_candids = share_session->local_share_candidates; /*TODO: Done for grabbing the relay candidate*/
+//nice_agent_get_local_candidates(agent, stream_id, component_id);
+/*		NiceCandidate *rc;
 		NiceCandidate *lc = (NiceCandidate *)local_candids->data;
+
 		gchar *ip = g_malloc(NICE_ADDRESS_STRING_LEN + 1);
 		gboolean set_pair;
 
-/*		strcpy(rc->foundation, "rf");
-		strcpy(lc->foundation, "lf");
-*/		
+		while(local_candids) {
+			rc = (NiceCandidate *)local_candids->data;
+			if(rc->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE) //Stun candidate
+				break;



More information about the Commits mailing list