Mercurial > pidgin.yaz
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) |