diff libpurple/protocols/msn/soap.c @ 20539:2c8c6d77f12c

Make use of the GQueue in MsnSoapConn to manage the SOAP requests, allowing them to work perfectly even when dispatching multiple requests at once. Delete a user from the userlist after the contact is deleted from the server.
author Carlos Silva <typ0@pidgin.im>
date Wed, 19 Sep 2007 06:08:42 +0000
parents f6dff814d95f
children 989f5906ca17
line wrap: on
line diff
--- a/libpurple/protocols/msn/soap.c	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/soap.c	Wed Sep 19 06:08:42 2007 +0000
@@ -34,6 +34,18 @@
 void
 msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step)
 {
+#ifdef MSN_SOAP_DEBUG
+	const char *MsnSoapStepText[] =
+	{
+		"Unconnected",
+		"Connecting",
+		"Connected",
+		"Processing",
+		"Connected Idle"
+	};
+
+	purple_debug_info("MSN SOAP", "Setting SOAP process step to %s\n", MsnSoapStepText[step]);
+#endif
 	soapconn->step = step;
 }
 
@@ -53,8 +65,9 @@
 	soapconn->input_handler = 0;
 	soapconn->output_handler = 0;
 
-	msn_soap_set_process_step(soapconn,MSN_SOAP_UNCONNECTED);
+	msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
 	soapconn->soap_queue = g_queue_new();
+
 	return soapconn;
 }
 
@@ -65,6 +78,7 @@
 {
 	MsnSoapConn * soapconn;
 	MsnSession *session;
+	gboolean soapconn_is_valid = FALSE;
 
 	purple_debug_misc("MSN SOAP","SOAP server connection established!\n");
 
@@ -76,12 +90,17 @@
 
 	soapconn->gsc = gsc;
 
+	msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTED);
+
 	/*connection callback*/
-	if(soapconn->connect_cb != NULL){
-		soapconn->connect_cb(data,gsc,cond);
+	if (soapconn->connect_cb != NULL) {
+		soapconn_is_valid = soapconn->connect_cb(soapconn, gsc);
 	}
 
-	msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTED);
+	if (!soapconn_is_valid) {
+		return;
+	}
+
 	/*we do the SOAP request here*/
 	msn_soap_post_head_request(soapconn);
 }
@@ -93,20 +112,24 @@
 	MsnSoapConn * soapconn = data;
 
 	g_return_if_fail(data != NULL);
+
 	purple_debug_warning("MSN SOAP","Soap connection error!\n");
+
 	msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
 
 	/*error callback*/
-	if(soapconn->error_cb != NULL){
-		soapconn->error_cb(gsc,error,data);
+	if (soapconn->error_cb != NULL) {
+		soapconn->error_cb(soapconn, gsc, error);
+	} else {
+		msn_soap_post(soapconn, NULL);
 	}
 }
 
 /*init the soap connection*/
 void
 msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl,
-				PurpleSslInputFunction	connect_cb,
-				PurpleSslErrorFunction	error_cb)
+				MsnSoapSslConnectCbFunction connect_cb,
+				MsnSoapSslErrorCbFunction error_cb)
 {
 	purple_debug_misc("MSN SOAP","Initializing SOAP connection\n");
 	soapconn->login_host = g_strdup(host);
@@ -119,32 +142,50 @@
 void
 msn_soap_connect(MsnSoapConn *soapconn)
 {
-	if(soapconn->ssl_conn){
+	if (soapconn->ssl_conn) {
 		purple_ssl_connect(soapconn->session->account, soapconn->login_host,
 				PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb, msn_soap_error_cb,
 				soapconn);
-	}else{
+	} else {
 	}
-	msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTING);
+
+	msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTING);
 }
 
+
+static void
+msn_soap_close_handler(guint *handler)
+{
+	if (*handler > 0) {
+		purple_input_remove(*handler);
+		*handler = 0;
+	} 
+#ifdef MSN_SOAP_DEBUG
+	else {
+		purple_debug_misc("MSN SOAP", "Handler inactive, not removing\n");
+	}
+#endif
+
+}
+
+
 /*close the soap connection*/
 void
 msn_soap_close(MsnSoapConn *soapconn)
 {
-	if(soapconn->ssl_conn){
-		if(soapconn->gsc != NULL){
+	if (soapconn->ssl_conn) {
+		if (soapconn->gsc != NULL) {
 			purple_ssl_close(soapconn->gsc);
 			soapconn->gsc = NULL;
 		}
-	}else{
+	} else {
 	}
-	msn_soap_set_process_step(soapconn,MSN_SOAP_UNCONNECTED);
+	msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
 }
 
 /*clean the unhandled SOAP request*/
 void
-msn_soap_clean_unhandled_request(MsnSoapConn *soapconn)
+msn_soap_clean_unhandled_requests(MsnSoapConn *soapconn)
 {
 	MsnSoapReq *request;
 
@@ -154,7 +195,7 @@
 
 	while ((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){
 		if (soapconn->read_cb) {
-			soapconn->read_cb(soapconn, -1, 0);
+			soapconn->read_cb(soapconn);
 		}
 		msn_soap_request_free(request);
 	}
@@ -187,7 +228,7 @@
 	msn_soap_close(soapconn);
 
 	/*process the unhandled soap request*/
-	msn_soap_clean_unhandled_request(soapconn);
+	msn_soap_clean_unhandled_requests(soapconn);
 
 	g_queue_free(soapconn->soap_queue);
 	g_free(soapconn);
@@ -199,10 +240,10 @@
 int
 msn_soap_connected(MsnSoapConn *soapconn)
 {
-	if(soapconn->ssl_conn){
-		return (soapconn->gsc == NULL? 0 : 1);
+	if (soapconn->ssl_conn) {
+		return (soapconn->gsc == NULL ? 0 : 1);
 	}
-	return(soapconn->fd>0? 1 : 0);
+	return (soapconn->fd > 0 ? 1 : 0);
 }
 
 /*read and append the content to the buffer*/
@@ -237,7 +278,7 @@
 						"read len: %d, error = %s\n",
 						len, strerror(errno));
 				  purple_input_remove(soapconn->input_handler);
-				  soapconn->input_handler = 0;
+				  //soapconn->input_handler = 0;
 				  g_free(soapconn->read_buf);
 				  soapconn->read_buf = NULL;
 				  soapconn->read_len = 0;
@@ -309,7 +350,12 @@
 		location = strstr(soapconn->read_buf, "Location: ");
 		if (location == NULL)
 		{
-			msn_soap_free_read_buf(soapconn);
+			c = (char *) g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
+			if (c != NULL) {
+				/* we have read the whole HTTP headers and found no Location: */
+				msn_soap_free_read_buf(soapconn);
+				msn_soap_post(soapconn, NULL);
+			}
 
 			return;
 		}
@@ -317,6 +363,8 @@
 
 		if ((c = strchr(location, '\r')) != NULL)
 			*c = '\0';
+		else
+			return;
 
 		/* Skip the http:// */
 		if ((c = strchr(location, '/')) != NULL)
@@ -332,10 +380,18 @@
 
 		g_free(soapconn->login_host);
 		soapconn->login_host = g_strdup(location);
+		
+		msn_soap_close_handler( &(soapconn->input_handler) );
+		msn_soap_close(soapconn);
 
-		purple_ssl_connect(session->account, soapconn->login_host,
+		if (purple_ssl_connect(session->account, soapconn->login_host,
 			PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb,
-			msn_soap_error_cb, soapconn);
+			msn_soap_error_cb, soapconn) == NULL) {
+		
+			purple_debug_error("MSN SOAP", "Unable to connect to %s !\n", soapconn->login_host);
+			// dispatch next request
+			msn_soap_post(soapconn, NULL);
+		}
 	}
 	/* Another case of redirection, active on May, 2007
 	   See http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener#Redirect
@@ -345,20 +401,22 @@
 	{
 		char *location, *c;
 
-		location = strstr(soapconn->read_buf, "<psf:redirectUrl>");
+		if ( (location = strstr(soapconn->read_buf, "<psf:redirectUrl>") ) == NULL)
+			return;
+
 		/* Omit the tag preceding the URL */
 		location += strlen("<psf:redirectUrl>");
-		location = strstr(location, ":/");
-		if (location == NULL)
-		{
-			msn_soap_free_read_buf(soapconn);
+		if (location > soapconn->read_buf + soapconn->read_len)
 			return;
-		}
+		if ( (location = strstr(location, "://")) == NULL)
+			return;
 
 		location += strlen("://"); /* Skip http:// or https:// */
 
 		if ( (c = strstr(location, "</psf:redirectUrl>")) != NULL )
 			*c = '\0';
+		else
+			return;
 
 		if ( (c = strstr(location, "/")) != NULL )
 		{
@@ -369,10 +427,18 @@
 
 		g_free(soapconn->login_host);
 		soapconn->login_host = g_strdup(location);
+		
+		msn_soap_close_handler( &(soapconn->input_handler) );
+		msn_soap_close(soapconn);
 
-		purple_ssl_connect(session->account, soapconn->login_host,
-			PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb,
-			msn_soap_error_cb, soapconn);
+		if (purple_ssl_connect(session->account, soapconn->login_host,
+				PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb,
+				msn_soap_error_cb, soapconn) == NULL) {
+
+			purple_debug_error("MSN SOAP", "Unable to connect to %s !\n", soapconn->login_host);
+			// dispatch next request
+			msn_soap_post(soapconn, NULL);
+		}
 	}
 	else if (strstr(soapconn->read_buf, "HTTP/1.1 401 Unauthorized") != NULL)
 	{
@@ -405,17 +471,23 @@
 	else if (strstr(soapconn->read_buf,
 				"<faultcode>wsse:FailedAuthentication</faultcode>") != NULL)
 	{
-		char *faultstring;
+		gchar *faultstring;
 
 		faultstring = strstr(soapconn->read_buf, "<faultstring>");
 
 		if (faultstring != NULL)
 		{
+			gchar *c;
 			faultstring += strlen("<faultstring>");
-			*strstr(soapconn->read_buf, "</faultstring>") = '\0';
+			if (faultstring < soapconn->read_buf + soapconn->read_len) {
+				c = strstr(soapconn->read_buf, "</faultstring>");
+				if (c != NULL) {
+					*c = '\0';
+					msn_session_set_error(session, MSN_ERROR_AUTH, faultstring);
+				}
+			}
 		}
 		
-		msn_session_set_error(session, MSN_ERROR_AUTH, faultstring);
 	}
 	else if (strstr(soapconn->read_buf, "HTTP/1.1 503 Service Unavailable"))
 	{
@@ -424,69 +496,86 @@
 	else if ((strstr(soapconn->read_buf, "HTTP/1.1 200 OK"))
 		||(strstr(soapconn->read_buf, "HTTP/1.1 500")))
 	{
-			/*OK! process the SOAP body*/
-			body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
-			if (!body_start) {
-				return;
-			}
-			body_start += 4;
+		gboolean soapconn_is_valid = FALSE;
 
-			//	purple_debug_misc("msn", "Soap Read: {%s}\n", soapconn->read_buf);
+		/*OK! process the SOAP body*/
+		body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
+		if (!body_start) {
+			return;
+		}
+		body_start += 4;
 
-			/* we read the content-length*/
-			length_start = strstr(soapconn->read_buf, "Content-Length: ");
+		if (body_start > soapconn->read_buf + soapconn->read_len)
+			return;
+
+		/* we read the content-length*/
+		if ( (length_start = g_strstr_len(soapconn->read_buf, soapconn->read_len, "Content-Length: ")) != NULL)
 			length_start += strlen("Content-Length: ");
-			length_end = strstr(length_start, "\r\n");
-			body_len = g_strndup(length_start, length_end - length_start);
+
+		if (length_start > soapconn->read_buf + soapconn->read_len)
+			return;
+
+		if ( (length_end = strstr(length_start, "\r\n")) == NULL )
+			return;
+
+		body_len = g_strndup(length_start, length_end - length_start);
 
-			/*setup the conn body */
-			soapconn->body		= body_start;
-			soapconn->body_len	= atoi(body_len);
-			g_free(body_len);
+		/*setup the conn body */
+		soapconn->body		= body_start;
+		soapconn->body_len	= atoi(body_len);
+		g_free(body_len);
 #ifdef MSN_SOAP_DEBUG
-			purple_debug_misc("MSN SOAP","SOAP bytes read so far: %d, Content-Length: %d\n", soapconn->read_len, soapconn->body_len);
+		purple_debug_misc("MSN SOAP","SOAP bytes read so far: %d, Content-Length: %d\n", soapconn->read_len, soapconn->body_len);
 #endif
-			soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len;
-			if ( soapconn->need_to_read > 0 ) {
-				return;
-			}
+		soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len;
+		if ( soapconn->need_to_read > 0 ) {
+			return;
+		}
 
 #if defined(MSN_SOAP_DEBUG) && !defined(_WIN32)
 
-			node = xmlnode_from_str(soapconn->body, soapconn->body_len);
+		node = xmlnode_from_str(soapconn->body, soapconn->body_len);
 	
-			if (node != NULL) {
-				formattedxml = xmlnode_to_formatted_str(node, NULL);
-				http_headers = g_strndup(soapconn->read_buf, soapconn->body - soapconn->read_buf);
+		if (node != NULL) {
+			formattedxml = xmlnode_to_formatted_str(node, NULL);
+			http_headers = g_strndup(soapconn->read_buf, soapconn->body - soapconn->read_buf);
 				
-				purple_debug_info("MSN SOAP","Data with XML payload received from the SOAP server:\n%s%s\n", http_headers, formattedxml);
-				g_free(http_headers);
-				g_free(formattedxml);
-				xmlnode_free(node);
-			}
-			else
-				purple_debug_info("MSN SOAP","Data received from the SOAP server:\n%s\n", soapconn->read_buf);
+			purple_debug_info("MSN SOAP","Data with XML payload received from the SOAP server:\n%s%s\n", http_headers, formattedxml);
+			g_free(http_headers);
+			g_free(formattedxml);
+			xmlnode_free(node);
+		}
+		else
+			purple_debug_info("MSN SOAP","Data received from the SOAP server:\n%s\n", soapconn->read_buf);
 #endif
 
-			/*remove the read handler*/
-			purple_input_remove(soapconn->input_handler);
-			soapconn->input_handler = 0;
-			/*
-			 * close the soap connection,if more soap request came,
-			 * Just reconnect to do it,
-			 *
-			 * To solve the problem described below:
-			 * When I post the soap request in one socket one after the other,
-			 * The first read is ok, But the second soap read always got 0 bytes,
-			 * Weird!
-			 * */
-			msn_soap_close(soapconn);
+		/*remove the read handler*/
+		msn_soap_close_handler( &(soapconn->input_handler) );
+//		purple_input_remove(soapconn->input_handler);
+//		soapconn->input_handler = 0;
+		/*
+		 * close the soap connection,if more soap request came,
+		 * Just reconnect to do it,
+		 *
+		 * To solve the problem described below:
+		 * When I post the soap request in one socket one after the other,
+		 * The first read is ok, But the second soap read always got 0 bytes,
+		 * Weird!
+		 * */
+		msn_soap_close(soapconn);
 
-			/*call the read callback*/
-			if ( soapconn->read_cb != NULL ) {
-				soapconn->read_cb(soapconn, source, 0);
-			}
-	}
+		/*call the read callback*/
+		if ( soapconn->read_cb != NULL ) {
+			soapconn_is_valid = soapconn->read_cb(soapconn);
+		}
+		
+		if (!soapconn_is_valid) {
+			return;
+		}
+
+		/* dispatch next request in queue */
+		msn_soap_post(soapconn, NULL);
+	}	
 	return;
 }
 
@@ -524,9 +613,11 @@
 
 	g_return_if_fail(soapconn != NULL);
 	if ( soapconn->write_buf == NULL ) {
-		purple_debug_error("MSN SOAP","SOAP buffer is NULL\n");
-		purple_input_remove(soapconn->output_handler);
-		soapconn->output_handler = -1;
+		purple_debug_error("MSN SOAP","SOAP write buffer is NULL\n");
+	//	msn_soap_check_conn_errors(soapconn);
+	//	purple_input_remove(soapconn->output_handler);
+	//	soapconn->output_handler = 0;
+		msn_soap_close_handler( &(soapconn->output_handler) );
 		return;
 	}
 	total_len = strlen(soapconn->write_buf);
@@ -542,10 +633,17 @@
 		return;
 	else if (len <= 0){
 		/*SSL write error!*/
-		purple_input_remove(soapconn->output_handler);
-		soapconn->output_handler = -1;
+//		msn_soap_check_conn_errors(soapconn);
+
+		msn_soap_close_handler( &(soapconn->output_handler) );
+//		purple_input_remove(soapconn->output_handler);
+//		soapconn->output_handler = 0;
+
+		msn_soap_close(soapconn);
+
 		/* TODO: notify of the error */
-		purple_debug_error("MSN SOAP","Error writing to SSL connection!\n");
+		purple_debug_error("MSN SOAP", "Error writing to SSL connection!\n");
+		msn_soap_post(soapconn, NULL);
 		return;
 	}
 	soapconn->written_len += len;
@@ -553,8 +651,9 @@
 	if (soapconn->written_len < total_len)
 		return;
 
-	purple_input_remove(soapconn->output_handler);
-	soapconn->output_handler = -1;
+	msn_soap_close_handler( &(soapconn->output_handler) );
+//	purple_input_remove(soapconn->output_handler);
+//	soapconn->output_handler = 0;
 
 	/*clear the write buff*/
 	msn_soap_free_write_buf(soapconn);
@@ -563,20 +662,25 @@
 	 * callback for write done
 	 */
 	if(soapconn->written_cb != NULL){
-		soapconn->written_cb(soapconn, source, 0);
+		soapconn->written_cb(soapconn);
 	}
 	/*maybe we need to read the input?*/
-	if (soapconn->input_handler == 0) {
+	if ( soapconn->input_handler == 0 ) {
 		soapconn->input_handler = purple_input_add(soapconn->gsc->fd,
 			PURPLE_INPUT_READ, msn_soap_read_cb, soapconn);
 	}
-//	msn_soap_read_cb(soapconn,source,0);
 }
 
 /*write the buffer to SOAP connection*/
 void
-msn_soap_write(MsnSoapConn * soapconn, char *write_buf, PurpleInputFunction written_cb)
+msn_soap_write(MsnSoapConn * soapconn, char *write_buf, MsnSoapWrittenCbFunction written_cb)
 {
+	if (soapconn == NULL) {
+		return;
+	}
+
+	msn_soap_set_process_step(soapconn, MSN_SOAP_PROCESSING);
+
 	soapconn->write_buf = write_buf;
 	soapconn->written_len = 0;
 	soapconn->written_cb = written_cb;
@@ -586,7 +690,7 @@
 	/*clear the read buffer first*/
 	/*start the write*/
 	soapconn->output_handler = purple_input_add(soapconn->gsc->fd, PURPLE_INPUT_WRITE,
-													msn_soap_write_cb, soapconn);
+						    msn_soap_write_cb, soapconn);
 	msn_soap_write_cb(soapconn, soapconn->gsc->fd, PURPLE_INPUT_WRITE);
 }
 
@@ -594,7 +698,9 @@
 MsnSoapReq *
 msn_soap_request_new(const char *host,const char *post_url,const char *soap_action,
 				const char *body, const gpointer data_cb,
-				PurpleInputFunction read_cb,PurpleInputFunction written_cb)
+				MsnSoapReadCbFunction read_cb,
+				MsnSoapWrittenCbFunction written_cb,
+				MsnSoapConnectInitFunction connect_init)
 {
 	MsnSoapReq *request;
 
@@ -608,6 +714,7 @@
 	request->data_cb 	= data_cb;
 	request->read_cb	= read_cb;
 	request->written_cb	= written_cb;
+	request->connect_init	= connect_init;
 
 	return request;
 }
@@ -624,6 +731,7 @@
 	g_free(request->body);
 	request->read_cb	= NULL;
 	request->written_cb	= NULL;
+	request->connect_init	= NULL;
 
 	g_free(request);
 }
@@ -632,18 +740,24 @@
 void
 msn_soap_post_head_request(MsnSoapConn *soapconn)
 {
-	purple_debug_info("MSN SOAP", "Posting new request from head of the queue\n");
+	g_return_if_fail(soapconn != NULL);
+	g_return_if_fail(soapconn->soap_queue != NULL);
 	
-	g_return_if_fail(soapconn->soap_queue != NULL);
+	if (soapconn->step == MSN_SOAP_CONNECTED ||
+	    soapconn->step == MSN_SOAP_CONNECTED_IDLE) {
+
+		purple_debug_info("MSN SOAP", "Posting new request from head of the queue\n");
 
-	if(!g_queue_is_empty(soapconn->soap_queue)){
-		MsnSoapReq *request;
-		if((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){
-			msn_soap_post_request(soapconn,request);
+		if ( !g_queue_is_empty(soapconn->soap_queue) ) {
+			MsnSoapReq *request;
+
+			if ( (request = g_queue_pop_head(soapconn->soap_queue)) != NULL ) {
+				msn_soap_post_request(soapconn,request);
+			}
+		} else {
+			purple_debug_info("MSN SOAP", "No requests to process found.\n");
+			msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTED_IDLE);
 		}
-	} else {
-		purple_debug_info("MSN SOAP", "No requests to process found.\n");
-		msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTED_IDLE);
 	}
 }
 
@@ -651,35 +765,59 @@
  * if not connected, Connected first.
  */
 void
-msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request,
-				MsnSoapConnectInitFunction msn_soap_init_func)
+msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request)
 {
+	MsnSoapReq *head_request;
+
+	if (soapconn == NULL)
+		return;
+
 	if (request != NULL) {
+#ifdef MSN_SOAP_DEBUG
+		purple_debug_misc("MSN SOAP", "Request added to the queue\n");
+#endif
 		g_queue_push_tail(soapconn->soap_queue, request);
 	}
-	if (!msn_soap_connected(soapconn) && (soapconn->step == MSN_SOAP_UNCONNECTED)
-					&&(!g_queue_is_empty(soapconn->soap_queue))) {
-		/*not connected?and we have something to process connect it first*/
-		purple_debug_misc("MSN SOAP","No connection to SOAP server. Connecting...\n");
-		msn_soap_init_func(soapconn);
-		msn_soap_connect(soapconn);
-		return;
-	}
-	purple_debug_misc("MSN SOAP","Connected to SOAP server\n");
+
+	if ( !g_queue_is_empty(soapconn->soap_queue)) {
+
+		/* we may have to reinitialize the soap connection, so avoid
+		 * reusing the connection for now */
+
+		if (soapconn->step == MSN_SOAP_CONNECTED_IDLE) {
+			purple_debug_misc("MSN SOAP","Already connected to SOAP server, re-initializing\n");
+			msn_soap_close_handler( &(soapconn->input_handler) );
+			msn_soap_close_handler( &(soapconn->output_handler) );
+			msn_soap_close(soapconn);
+		}
+
+		if (!msn_soap_connected(soapconn) && (soapconn->step == MSN_SOAP_UNCONNECTED)) {
 
-	/*if connected, what we only needed to do is to queue the request, 
-	 * when SOAP request in the queue processed done, will do this command.
-	 * we just waiting...
-	 * If we send the request this time,error may occure
-	 */
-	if (soapconn->step == MSN_SOAP_CONNECTED_IDLE){
-		msn_soap_post_head_request(soapconn);
+			/*not connected?and we have something to process connect it first*/
+			purple_debug_misc("MSN SOAP","No connection to SOAP server. Connecting...\n");
+			head_request = g_queue_peek_head(soapconn->soap_queue);
+
+			if (head_request == NULL) {
+				purple_debug_error("MSN SOAP", "Queue is not empty, but failed to peek the head request!\n");
+				return;
+			}
+
+			if (head_request->connect_init != NULL) {
+				head_request->connect_init(soapconn);
+			}
+			msn_soap_connect(soapconn);
+			return;
+		}
+
+		purple_debug_info("MSN SOAP", "Currently processing another SOAP request\n");
+	} else {
+		purple_debug_info("MSN SOAP", "No requests left to dispatch\n");
 	}
 }
 
 /*Post the soap request action*/
 void
-msn_soap_post_request(MsnSoapConn *soapconn,MsnSoapReq *request)
+msn_soap_post_request(MsnSoapConn *soapconn, MsnSoapReq *request)
 {
 	char * soap_head = NULL;
 	char * request_str = NULL;