comparison 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
comparison
equal deleted inserted replaced
20525:5bef3197383a 20539:2c8c6d77f12c
32 32
33 /*setup the soap process step*/ 33 /*setup the soap process step*/
34 void 34 void
35 msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step) 35 msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step)
36 { 36 {
37 #ifdef MSN_SOAP_DEBUG
38 const char *MsnSoapStepText[] =
39 {
40 "Unconnected",
41 "Connecting",
42 "Connected",
43 "Processing",
44 "Connected Idle"
45 };
46
47 purple_debug_info("MSN SOAP", "Setting SOAP process step to %s\n", MsnSoapStepText[step]);
48 #endif
37 soapconn->step = step; 49 soapconn->step = step;
38 } 50 }
39 51
40 //msn_soap_new(MsnSession *session,gpointer data,int sslconn) 52 //msn_soap_new(MsnSession *session,gpointer data,int sslconn)
41 /*new a soap connection*/ 53 /*new a soap connection*/
51 63
52 soapconn->gsc = NULL; 64 soapconn->gsc = NULL;
53 soapconn->input_handler = 0; 65 soapconn->input_handler = 0;
54 soapconn->output_handler = 0; 66 soapconn->output_handler = 0;
55 67
56 msn_soap_set_process_step(soapconn,MSN_SOAP_UNCONNECTED); 68 msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
57 soapconn->soap_queue = g_queue_new(); 69 soapconn->soap_queue = g_queue_new();
70
58 return soapconn; 71 return soapconn;
59 } 72 }
60 73
61 /*ssl soap connect callback*/ 74 /*ssl soap connect callback*/
62 void 75 void
63 msn_soap_connect_cb(gpointer data, PurpleSslConnection *gsc, 76 msn_soap_connect_cb(gpointer data, PurpleSslConnection *gsc,
64 PurpleInputCondition cond) 77 PurpleInputCondition cond)
65 { 78 {
66 MsnSoapConn * soapconn; 79 MsnSoapConn * soapconn;
67 MsnSession *session; 80 MsnSession *session;
81 gboolean soapconn_is_valid = FALSE;
68 82
69 purple_debug_misc("MSN SOAP","SOAP server connection established!\n"); 83 purple_debug_misc("MSN SOAP","SOAP server connection established!\n");
70 84
71 soapconn = data; 85 soapconn = data;
72 g_return_if_fail(soapconn != NULL); 86 g_return_if_fail(soapconn != NULL);
74 session = soapconn->session; 88 session = soapconn->session;
75 g_return_if_fail(session != NULL); 89 g_return_if_fail(session != NULL);
76 90
77 soapconn->gsc = gsc; 91 soapconn->gsc = gsc;
78 92
93 msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTED);
94
79 /*connection callback*/ 95 /*connection callback*/
80 if(soapconn->connect_cb != NULL){ 96 if (soapconn->connect_cb != NULL) {
81 soapconn->connect_cb(data,gsc,cond); 97 soapconn_is_valid = soapconn->connect_cb(soapconn, gsc);
82 } 98 }
83 99
84 msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTED); 100 if (!soapconn_is_valid) {
101 return;
102 }
103
85 /*we do the SOAP request here*/ 104 /*we do the SOAP request here*/
86 msn_soap_post_head_request(soapconn); 105 msn_soap_post_head_request(soapconn);
87 } 106 }
88 107
89 /*ssl soap error callback*/ 108 /*ssl soap error callback*/
91 msn_soap_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) 110 msn_soap_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data)
92 { 111 {
93 MsnSoapConn * soapconn = data; 112 MsnSoapConn * soapconn = data;
94 113
95 g_return_if_fail(data != NULL); 114 g_return_if_fail(data != NULL);
115
96 purple_debug_warning("MSN SOAP","Soap connection error!\n"); 116 purple_debug_warning("MSN SOAP","Soap connection error!\n");
117
97 msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED); 118 msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
98 119
99 /*error callback*/ 120 /*error callback*/
100 if(soapconn->error_cb != NULL){ 121 if (soapconn->error_cb != NULL) {
101 soapconn->error_cb(gsc,error,data); 122 soapconn->error_cb(soapconn, gsc, error);
123 } else {
124 msn_soap_post(soapconn, NULL);
102 } 125 }
103 } 126 }
104 127
105 /*init the soap connection*/ 128 /*init the soap connection*/
106 void 129 void
107 msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl, 130 msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl,
108 PurpleSslInputFunction connect_cb, 131 MsnSoapSslConnectCbFunction connect_cb,
109 PurpleSslErrorFunction error_cb) 132 MsnSoapSslErrorCbFunction error_cb)
110 { 133 {
111 purple_debug_misc("MSN SOAP","Initializing SOAP connection\n"); 134 purple_debug_misc("MSN SOAP","Initializing SOAP connection\n");
112 soapconn->login_host = g_strdup(host); 135 soapconn->login_host = g_strdup(host);
113 soapconn->ssl_conn = ssl; 136 soapconn->ssl_conn = ssl;
114 soapconn->connect_cb = connect_cb; 137 soapconn->connect_cb = connect_cb;
117 140
118 /*connect the soap connection*/ 141 /*connect the soap connection*/
119 void 142 void
120 msn_soap_connect(MsnSoapConn *soapconn) 143 msn_soap_connect(MsnSoapConn *soapconn)
121 { 144 {
122 if(soapconn->ssl_conn){ 145 if (soapconn->ssl_conn) {
123 purple_ssl_connect(soapconn->session->account, soapconn->login_host, 146 purple_ssl_connect(soapconn->session->account, soapconn->login_host,
124 PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb, msn_soap_error_cb, 147 PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb, msn_soap_error_cb,
125 soapconn); 148 soapconn);
126 }else{ 149 } else {
127 } 150 }
128 msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTING); 151
129 } 152 msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTING);
153 }
154
155
156 static void
157 msn_soap_close_handler(guint *handler)
158 {
159 if (*handler > 0) {
160 purple_input_remove(*handler);
161 *handler = 0;
162 }
163 #ifdef MSN_SOAP_DEBUG
164 else {
165 purple_debug_misc("MSN SOAP", "Handler inactive, not removing\n");
166 }
167 #endif
168
169 }
170
130 171
131 /*close the soap connection*/ 172 /*close the soap connection*/
132 void 173 void
133 msn_soap_close(MsnSoapConn *soapconn) 174 msn_soap_close(MsnSoapConn *soapconn)
134 { 175 {
135 if(soapconn->ssl_conn){ 176 if (soapconn->ssl_conn) {
136 if(soapconn->gsc != NULL){ 177 if (soapconn->gsc != NULL) {
137 purple_ssl_close(soapconn->gsc); 178 purple_ssl_close(soapconn->gsc);
138 soapconn->gsc = NULL; 179 soapconn->gsc = NULL;
139 } 180 }
140 }else{ 181 } else {
141 } 182 }
142 msn_soap_set_process_step(soapconn,MSN_SOAP_UNCONNECTED); 183 msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
143 } 184 }
144 185
145 /*clean the unhandled SOAP request*/ 186 /*clean the unhandled SOAP request*/
146 void 187 void
147 msn_soap_clean_unhandled_request(MsnSoapConn *soapconn) 188 msn_soap_clean_unhandled_requests(MsnSoapConn *soapconn)
148 { 189 {
149 MsnSoapReq *request; 190 MsnSoapReq *request;
150 191
151 g_return_if_fail(soapconn != NULL); 192 g_return_if_fail(soapconn != NULL);
152 193
153 soapconn->body = NULL; 194 soapconn->body = NULL;
154 195
155 while ((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){ 196 while ((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){
156 if (soapconn->read_cb) { 197 if (soapconn->read_cb) {
157 soapconn->read_cb(soapconn, -1, 0); 198 soapconn->read_cb(soapconn);
158 } 199 }
159 msn_soap_request_free(request); 200 msn_soap_request_free(request);
160 } 201 }
161 } 202 }
162 203
185 226
186 /*close ssl connection*/ 227 /*close ssl connection*/
187 msn_soap_close(soapconn); 228 msn_soap_close(soapconn);
188 229
189 /*process the unhandled soap request*/ 230 /*process the unhandled soap request*/
190 msn_soap_clean_unhandled_request(soapconn); 231 msn_soap_clean_unhandled_requests(soapconn);
191 232
192 g_queue_free(soapconn->soap_queue); 233 g_queue_free(soapconn->soap_queue);
193 g_free(soapconn); 234 g_free(soapconn);
194 } 235 }
195 236
197 * if connected return 1 238 * if connected return 1
198 */ 239 */
199 int 240 int
200 msn_soap_connected(MsnSoapConn *soapconn) 241 msn_soap_connected(MsnSoapConn *soapconn)
201 { 242 {
202 if(soapconn->ssl_conn){ 243 if (soapconn->ssl_conn) {
203 return (soapconn->gsc == NULL? 0 : 1); 244 return (soapconn->gsc == NULL ? 0 : 1);
204 } 245 }
205 return(soapconn->fd>0? 1 : 0); 246 return (soapconn->fd > 0 ? 1 : 0);
206 } 247 }
207 248
208 /*read and append the content to the buffer*/ 249 /*read and append the content to the buffer*/
209 static gssize 250 static gssize
210 msn_soap_read(MsnSoapConn *soapconn) 251 msn_soap_read(MsnSoapConn *soapconn)
235 276
236 default : purple_debug_error("MSN SOAP", "Read error!" 277 default : purple_debug_error("MSN SOAP", "Read error!"
237 "read len: %d, error = %s\n", 278 "read len: %d, error = %s\n",
238 len, strerror(errno)); 279 len, strerror(errno));
239 purple_input_remove(soapconn->input_handler); 280 purple_input_remove(soapconn->input_handler);
240 soapconn->input_handler = 0; 281 //soapconn->input_handler = 0;
241 g_free(soapconn->read_buf); 282 g_free(soapconn->read_buf);
242 soapconn->read_buf = NULL; 283 soapconn->read_buf = NULL;
243 soapconn->read_len = 0; 284 soapconn->read_len = 0;
244 /* TODO: error handling */ 285 /* TODO: error handling */
245 return len; 286 return len;
307 348
308 purple_debug_info("MSN SOAP", "HTTP Redirect\n"); 349 purple_debug_info("MSN SOAP", "HTTP Redirect\n");
309 location = strstr(soapconn->read_buf, "Location: "); 350 location = strstr(soapconn->read_buf, "Location: ");
310 if (location == NULL) 351 if (location == NULL)
311 { 352 {
312 msn_soap_free_read_buf(soapconn); 353 c = (char *) g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
354 if (c != NULL) {
355 /* we have read the whole HTTP headers and found no Location: */
356 msn_soap_free_read_buf(soapconn);
357 msn_soap_post(soapconn, NULL);
358 }
313 359
314 return; 360 return;
315 } 361 }
316 location = strchr(location, ' ') + 1; 362 location = strchr(location, ' ') + 1;
317 363
318 if ((c = strchr(location, '\r')) != NULL) 364 if ((c = strchr(location, '\r')) != NULL)
319 *c = '\0'; 365 *c = '\0';
366 else
367 return;
320 368
321 /* Skip the http:// */ 369 /* Skip the http:// */
322 if ((c = strchr(location, '/')) != NULL) 370 if ((c = strchr(location, '/')) != NULL)
323 location = c + 2; 371 location = c + 2;
324 372
330 *c = '\0'; 378 *c = '\0';
331 } 379 }
332 380
333 g_free(soapconn->login_host); 381 g_free(soapconn->login_host);
334 soapconn->login_host = g_strdup(location); 382 soapconn->login_host = g_strdup(location);
335 383
336 purple_ssl_connect(session->account, soapconn->login_host, 384 msn_soap_close_handler( &(soapconn->input_handler) );
385 msn_soap_close(soapconn);
386
387 if (purple_ssl_connect(session->account, soapconn->login_host,
337 PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb, 388 PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb,
338 msn_soap_error_cb, soapconn); 389 msn_soap_error_cb, soapconn) == NULL) {
390
391 purple_debug_error("MSN SOAP", "Unable to connect to %s !\n", soapconn->login_host);
392 // dispatch next request
393 msn_soap_post(soapconn, NULL);
394 }
339 } 395 }
340 /* Another case of redirection, active on May, 2007 396 /* Another case of redirection, active on May, 2007
341 See http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener#Redirect 397 See http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener#Redirect
342 */ 398 */
343 else if (strstr(soapconn->read_buf, 399 else if (strstr(soapconn->read_buf,
344 "<faultcode>psf:Redirect</faultcode>") != NULL) 400 "<faultcode>psf:Redirect</faultcode>") != NULL)
345 { 401 {
346 char *location, *c; 402 char *location, *c;
347 403
348 location = strstr(soapconn->read_buf, "<psf:redirectUrl>"); 404 if ( (location = strstr(soapconn->read_buf, "<psf:redirectUrl>") ) == NULL)
405 return;
406
349 /* Omit the tag preceding the URL */ 407 /* Omit the tag preceding the URL */
350 location += strlen("<psf:redirectUrl>"); 408 location += strlen("<psf:redirectUrl>");
351 location = strstr(location, ":/"); 409 if (location > soapconn->read_buf + soapconn->read_len)
352 if (location == NULL) 410 return;
353 { 411 if ( (location = strstr(location, "://")) == NULL)
354 msn_soap_free_read_buf(soapconn); 412 return;
355 return;
356 }
357 413
358 location += strlen("://"); /* Skip http:// or https:// */ 414 location += strlen("://"); /* Skip http:// or https:// */
359 415
360 if ( (c = strstr(location, "</psf:redirectUrl>")) != NULL ) 416 if ( (c = strstr(location, "</psf:redirectUrl>")) != NULL )
361 *c = '\0'; 417 *c = '\0';
418 else
419 return;
362 420
363 if ( (c = strstr(location, "/")) != NULL ) 421 if ( (c = strstr(location, "/")) != NULL )
364 { 422 {
365 g_free(soapconn->login_path); 423 g_free(soapconn->login_path);
366 soapconn->login_path = g_strdup(c); 424 soapconn->login_path = g_strdup(c);
367 *c = '\0'; 425 *c = '\0';
368 } 426 }
369 427
370 g_free(soapconn->login_host); 428 g_free(soapconn->login_host);
371 soapconn->login_host = g_strdup(location); 429 soapconn->login_host = g_strdup(location);
372 430
373 purple_ssl_connect(session->account, soapconn->login_host, 431 msn_soap_close_handler( &(soapconn->input_handler) );
374 PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb, 432 msn_soap_close(soapconn);
375 msn_soap_error_cb, soapconn); 433
434 if (purple_ssl_connect(session->account, soapconn->login_host,
435 PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb,
436 msn_soap_error_cb, soapconn) == NULL) {
437
438 purple_debug_error("MSN SOAP", "Unable to connect to %s !\n", soapconn->login_host);
439 // dispatch next request
440 msn_soap_post(soapconn, NULL);
441 }
376 } 442 }
377 else if (strstr(soapconn->read_buf, "HTTP/1.1 401 Unauthorized") != NULL) 443 else if (strstr(soapconn->read_buf, "HTTP/1.1 401 Unauthorized") != NULL)
378 { 444 {
379 const char *error; 445 const char *error;
380 446
403 * Further info: http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener 469 * Further info: http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener
404 */ 470 */
405 else if (strstr(soapconn->read_buf, 471 else if (strstr(soapconn->read_buf,
406 "<faultcode>wsse:FailedAuthentication</faultcode>") != NULL) 472 "<faultcode>wsse:FailedAuthentication</faultcode>") != NULL)
407 { 473 {
408 char *faultstring; 474 gchar *faultstring;
409 475
410 faultstring = strstr(soapconn->read_buf, "<faultstring>"); 476 faultstring = strstr(soapconn->read_buf, "<faultstring>");
411 477
412 if (faultstring != NULL) 478 if (faultstring != NULL)
413 { 479 {
480 gchar *c;
414 faultstring += strlen("<faultstring>"); 481 faultstring += strlen("<faultstring>");
415 *strstr(soapconn->read_buf, "</faultstring>") = '\0'; 482 if (faultstring < soapconn->read_buf + soapconn->read_len) {
483 c = strstr(soapconn->read_buf, "</faultstring>");
484 if (c != NULL) {
485 *c = '\0';
486 msn_session_set_error(session, MSN_ERROR_AUTH, faultstring);
487 }
488 }
416 } 489 }
417 490
418 msn_session_set_error(session, MSN_ERROR_AUTH, faultstring);
419 } 491 }
420 else if (strstr(soapconn->read_buf, "HTTP/1.1 503 Service Unavailable")) 492 else if (strstr(soapconn->read_buf, "HTTP/1.1 503 Service Unavailable"))
421 { 493 {
422 msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, NULL); 494 msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
423 } 495 }
424 else if ((strstr(soapconn->read_buf, "HTTP/1.1 200 OK")) 496 else if ((strstr(soapconn->read_buf, "HTTP/1.1 200 OK"))
425 ||(strstr(soapconn->read_buf, "HTTP/1.1 500"))) 497 ||(strstr(soapconn->read_buf, "HTTP/1.1 500")))
426 { 498 {
427 /*OK! process the SOAP body*/ 499 gboolean soapconn_is_valid = FALSE;
428 body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n"); 500
429 if (!body_start) { 501 /*OK! process the SOAP body*/
430 return; 502 body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
431 } 503 if (!body_start) {
432 body_start += 4; 504 return;
433 505 }
434 // purple_debug_misc("msn", "Soap Read: {%s}\n", soapconn->read_buf); 506 body_start += 4;
435 507
436 /* we read the content-length*/ 508 if (body_start > soapconn->read_buf + soapconn->read_len)
437 length_start = strstr(soapconn->read_buf, "Content-Length: "); 509 return;
510
511 /* we read the content-length*/
512 if ( (length_start = g_strstr_len(soapconn->read_buf, soapconn->read_len, "Content-Length: ")) != NULL)
438 length_start += strlen("Content-Length: "); 513 length_start += strlen("Content-Length: ");
439 length_end = strstr(length_start, "\r\n"); 514
440 body_len = g_strndup(length_start, length_end - length_start); 515 if (length_start > soapconn->read_buf + soapconn->read_len)
441 516 return;
442 /*setup the conn body */ 517
443 soapconn->body = body_start; 518 if ( (length_end = strstr(length_start, "\r\n")) == NULL )
444 soapconn->body_len = atoi(body_len); 519 return;
445 g_free(body_len); 520
521 body_len = g_strndup(length_start, length_end - length_start);
522
523 /*setup the conn body */
524 soapconn->body = body_start;
525 soapconn->body_len = atoi(body_len);
526 g_free(body_len);
446 #ifdef MSN_SOAP_DEBUG 527 #ifdef MSN_SOAP_DEBUG
447 purple_debug_misc("MSN SOAP","SOAP bytes read so far: %d, Content-Length: %d\n", soapconn->read_len, soapconn->body_len); 528 purple_debug_misc("MSN SOAP","SOAP bytes read so far: %d, Content-Length: %d\n", soapconn->read_len, soapconn->body_len);
448 #endif 529 #endif
449 soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len; 530 soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len;
450 if ( soapconn->need_to_read > 0 ) { 531 if ( soapconn->need_to_read > 0 ) {
451 return; 532 return;
452 } 533 }
453 534
454 #if defined(MSN_SOAP_DEBUG) && !defined(_WIN32) 535 #if defined(MSN_SOAP_DEBUG) && !defined(_WIN32)
455 536
456 node = xmlnode_from_str(soapconn->body, soapconn->body_len); 537 node = xmlnode_from_str(soapconn->body, soapconn->body_len);
457 538
458 if (node != NULL) { 539 if (node != NULL) {
459 formattedxml = xmlnode_to_formatted_str(node, NULL); 540 formattedxml = xmlnode_to_formatted_str(node, NULL);
460 http_headers = g_strndup(soapconn->read_buf, soapconn->body - soapconn->read_buf); 541 http_headers = g_strndup(soapconn->read_buf, soapconn->body - soapconn->read_buf);
461 542
462 purple_debug_info("MSN SOAP","Data with XML payload received from the SOAP server:\n%s%s\n", http_headers, formattedxml); 543 purple_debug_info("MSN SOAP","Data with XML payload received from the SOAP server:\n%s%s\n", http_headers, formattedxml);
463 g_free(http_headers); 544 g_free(http_headers);
464 g_free(formattedxml); 545 g_free(formattedxml);
465 xmlnode_free(node); 546 xmlnode_free(node);
466 } 547 }
467 else 548 else
468 purple_debug_info("MSN SOAP","Data received from the SOAP server:\n%s\n", soapconn->read_buf); 549 purple_debug_info("MSN SOAP","Data received from the SOAP server:\n%s\n", soapconn->read_buf);
469 #endif 550 #endif
470 551
471 /*remove the read handler*/ 552 /*remove the read handler*/
472 purple_input_remove(soapconn->input_handler); 553 msn_soap_close_handler( &(soapconn->input_handler) );
473 soapconn->input_handler = 0; 554 // purple_input_remove(soapconn->input_handler);
474 /* 555 // soapconn->input_handler = 0;
475 * close the soap connection,if more soap request came, 556 /*
476 * Just reconnect to do it, 557 * close the soap connection,if more soap request came,
477 * 558 * Just reconnect to do it,
478 * To solve the problem described below: 559 *
479 * When I post the soap request in one socket one after the other, 560 * To solve the problem described below:
480 * The first read is ok, But the second soap read always got 0 bytes, 561 * When I post the soap request in one socket one after the other,
481 * Weird! 562 * The first read is ok, But the second soap read always got 0 bytes,
482 * */ 563 * Weird!
483 msn_soap_close(soapconn); 564 * */
484 565 msn_soap_close(soapconn);
485 /*call the read callback*/ 566
486 if ( soapconn->read_cb != NULL ) { 567 /*call the read callback*/
487 soapconn->read_cb(soapconn, source, 0); 568 if ( soapconn->read_cb != NULL ) {
488 } 569 soapconn_is_valid = soapconn->read_cb(soapconn);
489 } 570 }
571
572 if (!soapconn_is_valid) {
573 return;
574 }
575
576 /* dispatch next request in queue */
577 msn_soap_post(soapconn, NULL);
578 }
490 return; 579 return;
491 } 580 }
492 581
493 void 582 void
494 msn_soap_free_read_buf(MsnSoapConn *soapconn) 583 msn_soap_free_read_buf(MsnSoapConn *soapconn)
522 MsnSoapConn *soapconn = data; 611 MsnSoapConn *soapconn = data;
523 int len, total_len; 612 int len, total_len;
524 613
525 g_return_if_fail(soapconn != NULL); 614 g_return_if_fail(soapconn != NULL);
526 if ( soapconn->write_buf == NULL ) { 615 if ( soapconn->write_buf == NULL ) {
527 purple_debug_error("MSN SOAP","SOAP buffer is NULL\n"); 616 purple_debug_error("MSN SOAP","SOAP write buffer is NULL\n");
528 purple_input_remove(soapconn->output_handler); 617 // msn_soap_check_conn_errors(soapconn);
529 soapconn->output_handler = -1; 618 // purple_input_remove(soapconn->output_handler);
619 // soapconn->output_handler = 0;
620 msn_soap_close_handler( &(soapconn->output_handler) );
530 return; 621 return;
531 } 622 }
532 total_len = strlen(soapconn->write_buf); 623 total_len = strlen(soapconn->write_buf);
533 624
534 /* 625 /*
540 631
541 if (len < 0 && errno == EAGAIN) 632 if (len < 0 && errno == EAGAIN)
542 return; 633 return;
543 else if (len <= 0){ 634 else if (len <= 0){
544 /*SSL write error!*/ 635 /*SSL write error!*/
545 purple_input_remove(soapconn->output_handler); 636 // msn_soap_check_conn_errors(soapconn);
546 soapconn->output_handler = -1; 637
638 msn_soap_close_handler( &(soapconn->output_handler) );
639 // purple_input_remove(soapconn->output_handler);
640 // soapconn->output_handler = 0;
641
642 msn_soap_close(soapconn);
643
547 /* TODO: notify of the error */ 644 /* TODO: notify of the error */
548 purple_debug_error("MSN SOAP","Error writing to SSL connection!\n"); 645 purple_debug_error("MSN SOAP", "Error writing to SSL connection!\n");
646 msn_soap_post(soapconn, NULL);
549 return; 647 return;
550 } 648 }
551 soapconn->written_len += len; 649 soapconn->written_len += len;
552 650
553 if (soapconn->written_len < total_len) 651 if (soapconn->written_len < total_len)
554 return; 652 return;
555 653
556 purple_input_remove(soapconn->output_handler); 654 msn_soap_close_handler( &(soapconn->output_handler) );
557 soapconn->output_handler = -1; 655 // purple_input_remove(soapconn->output_handler);
656 // soapconn->output_handler = 0;
558 657
559 /*clear the write buff*/ 658 /*clear the write buff*/
560 msn_soap_free_write_buf(soapconn); 659 msn_soap_free_write_buf(soapconn);
561 660
562 /* Write finish! 661 /* Write finish!
563 * callback for write done 662 * callback for write done
564 */ 663 */
565 if(soapconn->written_cb != NULL){ 664 if(soapconn->written_cb != NULL){
566 soapconn->written_cb(soapconn, source, 0); 665 soapconn->written_cb(soapconn);
567 } 666 }
568 /*maybe we need to read the input?*/ 667 /*maybe we need to read the input?*/
569 if (soapconn->input_handler == 0) { 668 if ( soapconn->input_handler == 0 ) {
570 soapconn->input_handler = purple_input_add(soapconn->gsc->fd, 669 soapconn->input_handler = purple_input_add(soapconn->gsc->fd,
571 PURPLE_INPUT_READ, msn_soap_read_cb, soapconn); 670 PURPLE_INPUT_READ, msn_soap_read_cb, soapconn);
572 } 671 }
573 // msn_soap_read_cb(soapconn,source,0);
574 } 672 }
575 673
576 /*write the buffer to SOAP connection*/ 674 /*write the buffer to SOAP connection*/
577 void 675 void
578 msn_soap_write(MsnSoapConn * soapconn, char *write_buf, PurpleInputFunction written_cb) 676 msn_soap_write(MsnSoapConn * soapconn, char *write_buf, MsnSoapWrittenCbFunction written_cb)
579 { 677 {
678 if (soapconn == NULL) {
679 return;
680 }
681
682 msn_soap_set_process_step(soapconn, MSN_SOAP_PROCESSING);
683
580 soapconn->write_buf = write_buf; 684 soapconn->write_buf = write_buf;
581 soapconn->written_len = 0; 685 soapconn->written_len = 0;
582 soapconn->written_cb = written_cb; 686 soapconn->written_cb = written_cb;
583 687
584 msn_soap_free_read_buf(soapconn); 688 msn_soap_free_read_buf(soapconn);
585 689
586 /*clear the read buffer first*/ 690 /*clear the read buffer first*/
587 /*start the write*/ 691 /*start the write*/
588 soapconn->output_handler = purple_input_add(soapconn->gsc->fd, PURPLE_INPUT_WRITE, 692 soapconn->output_handler = purple_input_add(soapconn->gsc->fd, PURPLE_INPUT_WRITE,
589 msn_soap_write_cb, soapconn); 693 msn_soap_write_cb, soapconn);
590 msn_soap_write_cb(soapconn, soapconn->gsc->fd, PURPLE_INPUT_WRITE); 694 msn_soap_write_cb(soapconn, soapconn->gsc->fd, PURPLE_INPUT_WRITE);
591 } 695 }
592 696
593 /* New a soap request*/ 697 /* New a soap request*/
594 MsnSoapReq * 698 MsnSoapReq *
595 msn_soap_request_new(const char *host,const char *post_url,const char *soap_action, 699 msn_soap_request_new(const char *host,const char *post_url,const char *soap_action,
596 const char *body, const gpointer data_cb, 700 const char *body, const gpointer data_cb,
597 PurpleInputFunction read_cb,PurpleInputFunction written_cb) 701 MsnSoapReadCbFunction read_cb,
702 MsnSoapWrittenCbFunction written_cb,
703 MsnSoapConnectInitFunction connect_init)
598 { 704 {
599 MsnSoapReq *request; 705 MsnSoapReq *request;
600 706
601 request = g_new0(MsnSoapReq, 1); 707 request = g_new0(MsnSoapReq, 1);
602 request->id = 0; 708 request->id = 0;
606 request->soap_action = g_strdup(soap_action); 712 request->soap_action = g_strdup(soap_action);
607 request->body = g_strdup(body); 713 request->body = g_strdup(body);
608 request->data_cb = data_cb; 714 request->data_cb = data_cb;
609 request->read_cb = read_cb; 715 request->read_cb = read_cb;
610 request->written_cb = written_cb; 716 request->written_cb = written_cb;
717 request->connect_init = connect_init;
611 718
612 return request; 719 return request;
613 } 720 }
614 721
615 /*free a soap request*/ 722 /*free a soap request*/
622 g_free(request->login_path); 729 g_free(request->login_path);
623 g_free(request->soap_action); 730 g_free(request->soap_action);
624 g_free(request->body); 731 g_free(request->body);
625 request->read_cb = NULL; 732 request->read_cb = NULL;
626 request->written_cb = NULL; 733 request->written_cb = NULL;
734 request->connect_init = NULL;
627 735
628 g_free(request); 736 g_free(request);
629 } 737 }
630 738
631 /*post the soap request queue's head request*/ 739 /*post the soap request queue's head request*/
632 void 740 void
633 msn_soap_post_head_request(MsnSoapConn *soapconn) 741 msn_soap_post_head_request(MsnSoapConn *soapconn)
634 { 742 {
635 purple_debug_info("MSN SOAP", "Posting new request from head of the queue\n"); 743 g_return_if_fail(soapconn != NULL);
744 g_return_if_fail(soapconn->soap_queue != NULL);
636 745
637 g_return_if_fail(soapconn->soap_queue != NULL); 746 if (soapconn->step == MSN_SOAP_CONNECTED ||
638 747 soapconn->step == MSN_SOAP_CONNECTED_IDLE) {
639 if(!g_queue_is_empty(soapconn->soap_queue)){ 748
640 MsnSoapReq *request; 749 purple_debug_info("MSN SOAP", "Posting new request from head of the queue\n");
641 if((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){ 750
642 msn_soap_post_request(soapconn,request); 751 if ( !g_queue_is_empty(soapconn->soap_queue) ) {
643 } 752 MsnSoapReq *request;
644 } else { 753
645 purple_debug_info("MSN SOAP", "No requests to process found.\n"); 754 if ( (request = g_queue_pop_head(soapconn->soap_queue)) != NULL ) {
646 msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTED_IDLE); 755 msn_soap_post_request(soapconn,request);
756 }
757 } else {
758 purple_debug_info("MSN SOAP", "No requests to process found.\n");
759 msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTED_IDLE);
760 }
647 } 761 }
648 } 762 }
649 763
650 /*post the soap request , 764 /*post the soap request ,
651 * if not connected, Connected first. 765 * if not connected, Connected first.
652 */ 766 */
653 void 767 void
654 msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request, 768 msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request)
655 MsnSoapConnectInitFunction msn_soap_init_func) 769 {
656 { 770 MsnSoapReq *head_request;
771
772 if (soapconn == NULL)
773 return;
774
657 if (request != NULL) { 775 if (request != NULL) {
776 #ifdef MSN_SOAP_DEBUG
777 purple_debug_misc("MSN SOAP", "Request added to the queue\n");
778 #endif
658 g_queue_push_tail(soapconn->soap_queue, request); 779 g_queue_push_tail(soapconn->soap_queue, request);
659 } 780 }
660 if (!msn_soap_connected(soapconn) && (soapconn->step == MSN_SOAP_UNCONNECTED) 781
661 &&(!g_queue_is_empty(soapconn->soap_queue))) { 782 if ( !g_queue_is_empty(soapconn->soap_queue)) {
662 /*not connected?and we have something to process connect it first*/ 783
663 purple_debug_misc("MSN SOAP","No connection to SOAP server. Connecting...\n"); 784 /* we may have to reinitialize the soap connection, so avoid
664 msn_soap_init_func(soapconn); 785 * reusing the connection for now */
665 msn_soap_connect(soapconn); 786
666 return; 787 if (soapconn->step == MSN_SOAP_CONNECTED_IDLE) {
667 } 788 purple_debug_misc("MSN SOAP","Already connected to SOAP server, re-initializing\n");
668 purple_debug_misc("MSN SOAP","Connected to SOAP server\n"); 789 msn_soap_close_handler( &(soapconn->input_handler) );
669 790 msn_soap_close_handler( &(soapconn->output_handler) );
670 /*if connected, what we only needed to do is to queue the request, 791 msn_soap_close(soapconn);
671 * when SOAP request in the queue processed done, will do this command. 792 }
672 * we just waiting... 793
673 * If we send the request this time,error may occure 794 if (!msn_soap_connected(soapconn) && (soapconn->step == MSN_SOAP_UNCONNECTED)) {
674 */ 795
675 if (soapconn->step == MSN_SOAP_CONNECTED_IDLE){ 796 /*not connected?and we have something to process connect it first*/
676 msn_soap_post_head_request(soapconn); 797 purple_debug_misc("MSN SOAP","No connection to SOAP server. Connecting...\n");
798 head_request = g_queue_peek_head(soapconn->soap_queue);
799
800 if (head_request == NULL) {
801 purple_debug_error("MSN SOAP", "Queue is not empty, but failed to peek the head request!\n");
802 return;
803 }
804
805 if (head_request->connect_init != NULL) {
806 head_request->connect_init(soapconn);
807 }
808 msn_soap_connect(soapconn);
809 return;
810 }
811
812 purple_debug_info("MSN SOAP", "Currently processing another SOAP request\n");
813 } else {
814 purple_debug_info("MSN SOAP", "No requests left to dispatch\n");
677 } 815 }
678 } 816 }
679 817
680 /*Post the soap request action*/ 818 /*Post the soap request action*/
681 void 819 void
682 msn_soap_post_request(MsnSoapConn *soapconn,MsnSoapReq *request) 820 msn_soap_post_request(MsnSoapConn *soapconn, MsnSoapReq *request)
683 { 821 {
684 char * soap_head = NULL; 822 char * soap_head = NULL;
685 char * request_str = NULL; 823 char * request_str = NULL;
686 #ifdef MSN_SOAP_DEBUG 824 #ifdef MSN_SOAP_DEBUG
687 #if !defined(_WIN32) 825 #if !defined(_WIN32)