/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