comparison libpurple/protocols/msn/soap2.c @ 20528:06527cc0f79b

removes public handle to soap connection, instead a connection is looked up from session
author Ka-Hing Cheung <khc@hxbc.us>
date Mon, 24 Sep 2007 05:29:07 +0000
parents 0034d7e89032
children 1180920ffcec
comparison
equal deleted inserted replaced
20527:0034d7e89032 20528:06527cc0f79b
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */ 24 */
25 25
26 #include "soap2.h" 26 #include "soap2.h"
27 27
28 #include "session.h"
29
28 #include "debug.h" 30 #include "debug.h"
29 #include "xmlnode.h" 31 #include "xmlnode.h"
30 32
31 #include <glib.h> 33 #include <glib.h>
32 #include <error.h> 34 #include <error.h>
33 35
34 static void msn_soap_connection2_destroy_foreach_cb(gpointer item, gpointer data); 36 static GHashTable *conn_table = NULL;
35 static void msn_soap_connection2_cleanup(MsnSoapConnection2 *conn); 37
36 static gboolean msn_soap_connection2_run(gpointer data); 38 typedef struct _MsnSoapRequest {
37 39 char *path;
38 40 MsnSoapMessage *message;
39 MsnSoapConnection2 * 41 MsnSoapCallback cb;
40 msn_soap_connection2_new(MsnSession *session) 42 gpointer cb_data;
41 { 43 } MsnSoapRequest;
42 MsnSoapConnection2 *conn = g_new0(MsnSoapConnection2, 1); 44
45 typedef struct _MsnSoapConnection {
46 MsnSession *session;
47 char *host;
48
49 PurpleSslConnection *ssl;
50 gboolean connected;
51
52 guint event_handle;
53 GString *buf;
54 gsize handled_len;
55 gsize body_len;
56 int response_code;
57 gboolean headers_done;
58 MsnSoapMessage *message;
59
60 GQueue *queue;
61 MsnSoapRequest *current_request;
62 } MsnSoapConnection;
63
64 static void msn_soap_connection_destroy_foreach_cb(gpointer item, gpointer data);
65 static gboolean msn_soap_connection_run(gpointer data);
66
67 static MsnSoapConnection *msn_soap_connection_new(MsnSession *session,
68 const char *host);
69 static void msn_soap_connection_handle_next(MsnSoapConnection *conn);
70 static void msn_soap_connection_destroy(MsnSoapConnection *conn);
71
72 static void msn_soap_message_send_internal(MsnSession *session,
73 MsnSoapMessage *message, const char *host, const char *path,
74 MsnSoapCallback cb, gpointer cb_data, gboolean first);
75
76 static void msn_soap_request_destroy(MsnSoapRequest *req);
77
78
79 static MsnSoapConnection *
80 msn_soap_get_connection(MsnSession *session, const char *host)
81 {
82 MsnSoapConnection *conn = NULL;
83
84 if (session->soap_table) {
85 conn = g_hash_table_lookup(conn_table, host);
86 } else {
87 session->soap_table = g_hash_table_new_full(g_str_hash, g_str_equal,
88 NULL, (GDestroyNotify)msn_soap_connection_destroy);
89 }
90
91 if (conn == NULL) {
92 conn = msn_soap_connection_new(session, host);
93 g_hash_table_insert(session->soap_table, conn->host, conn);
94 }
95
96 return conn;
97 }
98
99 static MsnSoapConnection *
100 msn_soap_connection_new(MsnSession *session, const char *host)
101 {
102 MsnSoapConnection *conn = g_new0(MsnSoapConnection, 1);
43 conn->session = session; 103 conn->session = session;
104 conn->host = g_strdup(host);
44 conn->queue = g_queue_new(); 105 conn->queue = g_queue_new();
45 return conn; 106 return conn;
46 } 107 }
47 108
48 static void 109 static void
49 msn_soap_connected_cb(gpointer data, PurpleSslConnection *ssl, 110 msn_soap_connected_cb(gpointer data, PurpleSslConnection *ssl,
50 PurpleInputCondition cond) 111 PurpleInputCondition cond)
51 { 112 {
52 MsnSoapConnection2 *conn = data; 113 MsnSoapConnection *conn = data;
53 114
54 conn->connected = TRUE; 115 conn->connected = TRUE;
55 116
56 if (conn->idle_handle == 0) 117 if (conn->event_handle == 0)
57 conn->idle_handle = g_idle_add(msn_soap_connection2_run, conn); 118 conn->event_handle = g_idle_add(msn_soap_connection_run, conn);
58 } 119 }
59 120
60 static void 121 static void
61 msn_soap_error_cb(PurpleSslConnection *ssl, PurpleSslErrorType error, 122 msn_soap_error_cb(PurpleSslConnection *ssl, PurpleSslErrorType error,
62 gpointer data) 123 gpointer data)
63 { 124 {
64 MsnSoapConnection2 *conn = data; 125 MsnSoapConnection *conn = data;
65 126
66 msn_soap_connection2_cleanup(conn); 127 g_hash_table_remove(conn->session->soap_table, conn->host);
67 } 128 }
68 129
69 static gboolean 130 static gboolean
70 msn_soap_handle_redirect(MsnSoapConnection2 *conn, const char *url) 131 msn_soap_handle_redirect(MsnSoapConnection *conn, const char *url)
71 { 132 {
72 char *c; 133 char *c;
73 134
74 /* Skip the http:// */ 135 /* Skip the http:// */
75 if ((c = strchr(url, '/')) != NULL) 136 if ((c = strchr(url, '/')) != NULL)
76 url += 2; 137 url += 2;
77 138
78 if ((c = strchr(url, '/')) != NULL) { 139 if ((c = strchr(url, '/')) != NULL) {
79 g_free(conn->request->host); 140 char *host, *path;
80 g_free(conn->request->path); 141
81 142 host = g_strndup(url, c - url);
82 conn->request->host = g_strndup(url, c - url); 143 path = g_strdup(c);
83 conn->request->path = g_strdup(c); 144
84 145 msn_soap_message_send_internal(conn->session,
85 purple_input_remove(conn->io_handle); 146 conn->current_request->message, host, path,
86 conn->io_handle = 0; 147 conn->current_request->cb, conn->current_request->cb_data, TRUE);
87 148
88 msn_soap_connection2_post(conn, conn->request, 149 msn_soap_request_destroy(conn->current_request);
89 conn->request->cb, conn->request->data); 150 conn->current_request = NULL;
151
152 g_free(host);
153 g_free(path);
90 154
91 return TRUE; 155 return TRUE;
92 } 156 }
93 157
94 return FALSE; 158 return FALSE;
95 } 159 }
96 160
97 static gboolean 161 static gboolean
98 msn_soap_handle_body(MsnSoapConnection2 *conn, MsnSoapResponse *response) 162 msn_soap_handle_body(MsnSoapConnection *conn, MsnSoapMessage *response)
99 { 163 {
100 xmlnode *node = response->message->xml; 164 xmlnode *node = response->xml;
101 165
102 if (strcmp(node->name, "Envelop") == 0 && 166 if (strcmp(node->name, "Envelop") == 0 &&
103 node->child && strcmp(node->child->name, "Header") == 0 && 167 node->child && strcmp(node->child->name, "Header") == 0 &&
104 node->child->next) { 168 node->child->next) {
105 xmlnode *body = node->child->next; 169 xmlnode *body = node->child->next;
107 if (strcmp(body->name, "Fault")) { 171 if (strcmp(body->name, "Fault")) {
108 xmlnode *fault = xmlnode_get_child(body, "faultcode"); 172 xmlnode *fault = xmlnode_get_child(body, "faultcode");
109 173
110 if (fault != NULL) { 174 if (fault != NULL) {
111 if (strcmp(fault->data, "psf:Redirect") == 0) { 175 if (strcmp(fault->data, "psf:Redirect") == 0) {
112 xmlnode *url = xmlnode_get_child(fault, "redirectUrl"); 176 xmlnode *url = xmlnode_get_child(body, "redirectUrl");
113 177
114 if (url && !msn_soap_handle_redirect(conn, url->data)) { 178 if (url) {
115 return TRUE; 179 msn_soap_handle_redirect(conn, url->data);
116 } 180 }
181
182 return TRUE;
117 } else if (strcmp(fault->data, "wsse:FailedAuthentication")) { 183 } else if (strcmp(fault->data, "wsse:FailedAuthentication")) {
118 xmlnode *reason = xmlnode_get_child(fault, "faultstring"); 184 xmlnode *reason = xmlnode_get_child(body, "faultstring");
119 185
120 msn_session_set_error(conn->session, MSN_ERROR_AUTH, 186 msn_session_set_error(conn->session, MSN_ERROR_AUTH,
121 reason ? reason->data : NULL); 187 reason ? reason->data : NULL);
122 188
123 return TRUE; 189 return FALSE;
124 } 190 }
125 } 191 }
126 192
127 conn->request->cb(conn, conn->request, conn->response, 193 conn->current_request->cb(conn->current_request->message, response,
128 conn->request->data); 194 conn->current_request->cb_data);
129 195 msn_soap_request_destroy(conn->current_request);
130 return TRUE; 196 conn->current_request = NULL;
131 } 197 }
132 } 198 }
133 199
134 return FALSE; 200 return TRUE;
135 } 201 }
136 202
137 static void 203 static void
138 msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond) 204 msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
139 { 205 {
140 MsnSoapConnection2 *conn = data; 206 MsnSoapConnection *conn = data;
141 MsnSoapMessage *message;
142 int count; 207 int count;
143 char buf[8192]; 208 char buf[8192];
144 char *linebreak; 209 char *linebreak;
210 char *cursor;
211 gboolean handled = FALSE;
145 212
146 g_return_if_fail(cond == PURPLE_INPUT_READ); 213 g_return_if_fail(cond == PURPLE_INPUT_READ);
147 214
148 count = purple_ssl_read(conn->ssl, buf, sizeof(buf)); 215 count = purple_ssl_read(conn->ssl, buf, sizeof(buf));
149 if (count < 0 && errno == EAGAIN) 216 if (count < 0 && errno == EAGAIN)
150 return; 217 return;
151 else if (count <= 0) { 218 else if (count <= 0) {
152 msn_soap_connection2_cleanup(conn); 219 msn_soap_connection_handle_next(conn);
220 purple_ssl_close(conn->ssl);
221 conn->ssl = NULL;
153 return; 222 return;
154 } 223 }
155 224
156 if (conn->response == NULL) { 225 if (conn->message == NULL) {
157 conn->response = msn_soap_response_new(); 226 conn->message = msn_soap_message_new(NULL, NULL);
158 conn->response->message = msn_soap_message_new(); 227 }
159 } 228
160 229 if (conn->buf == NULL) {
161 message = conn->response->message; 230 conn->buf = g_string_new_len(buf, count);
162
163 if (message->buf == NULL) {
164 message->buf = g_memdup(buf, count);
165 message->buf_len = count;
166 } else { 231 } else {
167 message->buf = g_realloc(message->buf, message->buf_len + count); 232 g_string_append_len(conn->buf, buf, count);
168 memcpy(message->buf + message->buf_len, buf, count); 233 }
169 message->buf_len += count; 234
170 } 235 cursor = conn->buf->str + conn->handled_len;
171 236
172 if (conn->response->seen_newline) { 237 if (conn->headers_done) {
173 if (message->buf_len - message->buf_count >= 238 if (conn->buf->len - conn->handled_len >=
174 conn->response->body_len) { 239 conn->body_len) {
175 xmlnode *node = xmlnode_from_str( 240 xmlnode *node = xmlnode_from_str(cursor, conn->body_len);
176 message->buf + message->buf_count, conn->response->body_len);
177 241
178 if (node == NULL) { 242 if (node == NULL) {
179 purple_debug_info("soap", "Malformed SOAP response: %s\n", 243 purple_debug_info("soap", "Malformed SOAP response: %s\n",
180 message->buf + message->buf_count); 244 cursor);
181 } else { 245 } else {
182 conn->response->message->xml = node; 246 MsnSoapMessage *message = conn->message;
183 msn_soap_handle_body(conn, conn->response); 247 conn->message = NULL;
248 message->xml = node;
249
250 if (!msn_soap_handle_body(conn, message))
251 return;
184 } 252 }
253
254 msn_soap_connection_handle_next(conn);
185 } 255 }
186 256
187 return; 257 return;
188 } 258 }
189 259
190 while ((linebreak = strstr(message->buf + message->buf_count, "\r\n")) 260 while ((linebreak = strstr(cursor, "\r\n")) != NULL) {
191 != NULL) { 261 conn->handled_len = linebreak - conn->buf->str + 2;
192 message->buf_count = linebreak - message->buf + 2; 262
193 263 if (conn->response_code == 0) {
194 if (conn->response->code == -1) { 264 if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) {
195 if (sscanf(message->buf + message->buf_count, "HTTP/1.1 %d",
196 &conn->response->code) != 1) {
197 /* something horribly wrong */ 265 /* something horribly wrong */
198 msn_soap_connection2_destroy_foreach_cb(conn->request, conn); 266 msn_soap_connection_handle_next(conn);
199 conn->request = NULL; 267 purple_ssl_close(conn->ssl);
200 } else if (conn->response->code == 503) { 268 conn->ssl = NULL;
269 handled = TRUE;
270 break;
271 } else if (conn->response_code == 503) {
201 msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL); 272 msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
273 return;
202 } 274 }
203 } else if (message->buf + message->buf_count == linebreak) { 275 } else if (cursor == linebreak) {
204 /* blank line */ 276 /* blank line */
205 conn->response->seen_newline = TRUE; 277 conn->headers_done = TRUE;
206 } else { 278 } else {
207 char *sep = strstr(message->buf + message->buf_count, ": "); 279 char *sep = strstr(cursor, ": ");
208 char *key = message->buf + message->buf_count; 280 char *key = cursor;
209 char *value = sep + 2; 281 char *value = sep + 2;
210 282
211 *sep = '\0'; 283 *sep = '\0';
212 *linebreak = '\0'; 284 *linebreak = '\0';
213 msn_soap_message_add_header(message, key, value); 285 msn_soap_message_add_header(conn->message, key, value);
214 286
215 if ((conn->response->code == 301 || conn->response->code == 300) 287 if ((conn->response_code == 301 || conn->response_code == 300)
216 && strcmp(key, "Location") == 0) { 288 && strcmp(key, "Location") == 0) {
217 289
218 if (msn_soap_handle_redirect(conn, value)) { 290 if (!msn_soap_handle_redirect(conn, value) &&
219 291 conn->current_request->cb) {
220 } else if (conn->request->cb) { 292 conn->current_request->cb(conn->current_request->message,
221 conn->request->cb(conn, conn->request, NULL, 293 NULL, conn->current_request->cb_data);
222 conn->request->data);
223 } 294 }
224 } else if (conn->response->code == 401 && 295
296 handled = TRUE;
297 break;
298 } else if (conn->response_code == 401 &&
225 strcmp(key, "WWW-Authenticate") == 0) { 299 strcmp(key, "WWW-Authenticate") == 0) {
226 char *error = strstr(value, "cbtxt="); 300 char *error = strstr(value, "cbtxt=");
227 301
228 if (error) { 302 if (error) {
229 error += strlen("cbtxt="); 303 error += strlen("cbtxt=");
230 } 304 }
231 305
232 msn_session_set_error(conn->session, MSN_ERROR_AUTH, 306 msn_session_set_error(conn->session, MSN_ERROR_AUTH,
233 error ? purple_url_decode(error) : NULL); 307 error ? purple_url_decode(error) : NULL);
308
309 return;
234 } else if (strcmp(key, "Content-Length") == 0) { 310 } else if (strcmp(key, "Content-Length") == 0) {
235 conn->response->body_len = atoi(value); 311 conn->body_len = atoi(value);
236 } 312 }
237 } 313 }
238 } 314 }
315
316 if (handled) {
317 msn_soap_connection_handle_next(conn);
318 }
239 } 319 }
240 320
241 static void 321 static void
242 msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond) 322 msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond)
243 { 323 {
244 MsnSoapConnection2 *conn = data; 324 MsnSoapConnection *conn = data;
245 MsnSoapMessage *message = conn->request->message;
246 int written; 325 int written;
247 326
248 g_return_if_fail(cond == PURPLE_INPUT_WRITE); 327 g_return_if_fail(cond == PURPLE_INPUT_WRITE);
249 328
250 written = purple_ssl_write(conn->ssl, message->buf + message->buf_count, 329 written = purple_ssl_write(conn->ssl, conn->buf->str + conn->handled_len,
251 message->buf_len - message->buf_count); 330 conn->buf->len - conn->handled_len);
252 331
253 if (written < 0 && errno == EAGAIN) 332 if (written < 0 && errno == EAGAIN)
254 return; 333 return;
255 else if (written <= 0) { 334 else if (written <= 0) {
256 msn_soap_connection2_cleanup(conn); 335 purple_ssl_close(conn->ssl);
336 conn->ssl = NULL;
337 msn_soap_connection_handle_next(conn);
257 return; 338 return;
258 } 339 }
259 340
260 message->buf_count += written; 341 conn->handled_len += written;
261 342
262 if (message->buf_count < message->buf_len) 343 if (conn->handled_len < conn->buf->len)
263 return; 344 return;
264 345
265 /* we are done! */ 346 /* we are done! */
266 purple_input_remove(conn->io_handle); 347 purple_input_remove(conn->event_handle);
267 conn->io_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ, 348 conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ,
268 msn_soap_read_cb, conn); 349 msn_soap_read_cb, conn);
269 } 350 }
270 351
271 static gboolean 352 static gboolean
272 msn_soap_connection2_run(gpointer data) 353 msn_soap_connection_run(gpointer data)
273 { 354 {
274 MsnSoapConnection2 *conn = data; 355 MsnSoapConnection *conn = data;
275 MsnSoapRequest *req = g_queue_peek_head(conn->queue); 356 MsnSoapRequest *req = g_queue_peek_head(conn->queue);
276 357
358 conn->event_handle = 0;
359
277 if (req) { 360 if (req) {
278 if (conn->ssl) {
279 if (strcmp(conn->ssl->host, req->host) != 0 ||
280 strcmp(conn->path, req->path) != 0) {
281 purple_input_remove(conn->io_handle);
282 conn->io_handle = 0;
283 purple_ssl_close(conn->ssl);
284 conn->ssl = NULL;
285 g_free(conn->path);
286 conn->path = NULL;
287 }
288 }
289
290 if (conn->ssl == NULL) { 361 if (conn->ssl == NULL) {
291 conn->ssl = purple_ssl_connect(conn->session->account, req->host, 362 conn->ssl = purple_ssl_connect(conn->session->account, conn->host,
292 443, msn_soap_connected_cb, msn_soap_error_cb, conn); 363 443, msn_soap_connected_cb, msn_soap_error_cb, conn);
293 conn->path = g_strdup(req->path); 364 } else if (conn->connected) {
294 } else {
295 int len = -1; 365 int len = -1;
296 MsnSoapMessage *message = req->message; 366 char *body = xmlnode_to_str(req->message->xml, &len);
297 char *body = xmlnode_to_str(message->xml, &len);
298 GString *str = g_string_new("");
299 GSList *iter; 367 GSList *iter;
300 368
301 g_queue_pop_head(conn->queue); 369 g_queue_pop_head(conn->queue);
302 370
303 g_string_append_printf(str, 371 conn->buf = g_string_new("");
372
373 g_string_append_printf(conn->buf,
304 "POST %s HTTP/1.1\r\n" 374 "POST %s HTTP/1.1\r\n"
305 "SOAPAction: %s\r\n" 375 "SOAPAction: %s\r\n"
306 "Content-Type:text/xml; charset=utf-8\r\n" 376 "Content-Type:text/xml; charset=utf-8\r\n"
307 "Cookie: MSPAuth=%s\r\n" 377 "Cookie: MSPAuth=%s\r\n"
308 "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n" 378 "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
309 "Accept: */*\r\n" 379 "Accept: */*\r\n"
310 "Host: %s\r\n" 380 "Host: %s\r\n"
311 "Content-Length: %d\r\n" 381 "Content-Length: %d\r\n"
312 "Connection: Keep-Alive\r\n" 382 "Connection: Keep-Alive\r\n"
313 "Cache-Control: no-cache\r\n", 383 "Cache-Control: no-cache\r\n",
314 req->path, req->action, 384 req->path, req->message->action,
315 conn->session->passport_info.mspauth, 385 conn->session->passport_info.mspauth,
316 req->host, len); 386 conn->host, len);
317 387
318 for (iter = req->message->headers; iter; iter = iter->next) { 388 for (iter = req->message->headers; iter; iter = iter->next) {
319 g_string_append(str, (char *)iter->data); 389 g_string_append(conn->buf, (char *)iter->data);
320 g_string_append(str, "\r\n"); 390 g_string_append(conn->buf, "\r\n");
321 } 391 }
322 392
323 g_string_append(str, "\r\n"); 393 g_string_append(conn->buf, "\r\n");
324 g_string_append(str, body); 394 g_string_append(conn->buf, body);
325 395
326 message->buf_len = str->len; 396 conn->handled_len = 0;
327 message->buf = g_string_free(str, FALSE); 397 conn->current_request = req;
328 message->buf_count = 0; 398
329 conn->request = req; 399 conn->event_handle = purple_input_add(conn->ssl->fd,
330
331 conn->io_handle = purple_input_add(conn->ssl->fd,
332 PURPLE_INPUT_WRITE, msn_soap_write_cb, conn); 400 PURPLE_INPUT_WRITE, msn_soap_write_cb, conn);
333 msn_soap_write_cb(conn, conn->ssl->fd, PURPLE_INPUT_WRITE); 401 msn_soap_write_cb(conn, conn->ssl->fd, PURPLE_INPUT_WRITE);
334 } 402 }
335 } 403 }
336 404
337 conn->idle_handle = 0;
338 return FALSE; 405 return FALSE;
339 } 406 }
340 407
341 void 408 void
342 msn_soap_connection2_post(MsnSoapConnection2 *conn, MsnSoapRequest *req, 409 msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
343 MsnSoapCallback cb, gpointer data) 410 const char *host, const char *path,
344 { 411 MsnSoapCallback cb, gpointer cb_data)
412 {
413 msn_soap_message_send_internal(session, message, host, path, cb, cb_data,
414 FALSE);
415 }
416
417 static void
418 msn_soap_message_send_internal(MsnSession *session,
419 MsnSoapMessage *message, const char *host, const char *path,
420 MsnSoapCallback cb, gpointer cb_data, gboolean first)
421 {
422 MsnSoapConnection *conn = msn_soap_get_connection(session, host);
423 MsnSoapRequest *req = g_new0(MsnSoapRequest, 1);
424
425 req->path = g_strdup(path);
426 req->message = message;
345 req->cb = cb; 427 req->cb = cb;
346 req->data = data; 428 req->cb_data = cb_data;
347 429
348 g_queue_push_tail(conn->queue, req); 430 if (first) {
349 431 g_queue_push_head(conn->queue, req);
350 if (conn->idle_handle == 0) 432 } else {
351 conn->idle_handle = g_idle_add(msn_soap_connection2_run, conn); 433 g_queue_push_tail(conn->queue, req);
352 } 434 }
353 435
354 static void 436 if (conn->event_handle == 0)
355 msn_soap_connection2_destroy_foreach_cb(gpointer item, gpointer data) 437 conn->event_handle = purple_timeout_add(0, msn_soap_connection_run,
438 conn);
439 }
440
441 static void
442 msn_soap_connection_handle_next(MsnSoapConnection *conn)
443 {
444 if (conn->current_request) {
445 msn_soap_connection_destroy_foreach_cb(conn->current_request, conn);
446 conn->current_request = NULL;
447 }
448
449 purple_input_remove(conn->event_handle);
450 conn->event_handle = 0;
451
452 msn_soap_message_destroy(conn->message);
453 g_string_free(conn->buf, TRUE);
454
455 conn->event_handle = purple_timeout_add(0, msn_soap_connection_run, conn);
456 }
457
458 static void
459 msn_soap_connection_destroy_foreach_cb(gpointer item, gpointer data)
356 { 460 {
357 MsnSoapRequest *req = item; 461 MsnSoapRequest *req = item;
358 MsnSoapConnection2 *conn = data;
359 462
360 if (req->cb) 463 if (req->cb)
361 req->cb(conn, req, NULL, req->data); 464 req->cb(req->message, NULL, req->cb_data);
362 465
363 msn_soap_request2_destroy(req); 466 msn_soap_request_destroy(req);
364 } 467 }
365 468
366 static void 469 static void
367 msn_soap_connection2_cleanup(MsnSoapConnection2 *conn) 470 msn_soap_connection_destroy(MsnSoapConnection *conn)
368 { 471 {
369 g_queue_foreach(conn->queue, msn_soap_connection2_destroy_foreach_cb, conn); 472 if (conn->current_request) {
370 if (conn->request) { 473 msn_soap_connection_destroy_foreach_cb(conn->current_request, conn);
371 msn_soap_connection2_destroy_foreach_cb(conn->request, conn); 474 conn->current_request = NULL;
372 conn->request = NULL; 475 }
373 } 476
374 477 g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn);
375 purple_input_remove(conn->io_handle); 478
376 conn->io_handle = 0; 479 purple_input_remove(conn->event_handle);
377 g_source_remove(conn->idle_handle); 480 conn->event_handle = 0;
378 conn->idle_handle = 0;
379 481
380 if (conn->ssl) { 482 if (conn->ssl) {
381 purple_ssl_close(conn->ssl); 483 purple_ssl_close(conn->ssl);
382 conn->ssl = NULL; 484 conn->ssl = NULL;
383 } 485 }
384 486
385 while (g_queue_pop_head(conn->queue) != NULL); 487 msn_soap_message_destroy(conn->message);
386 488 g_string_free(conn->buf, TRUE);
387 g_free(conn->path); 489 g_free(conn->host);
388 }
389
390 void
391 msn_soap_connection2_destroy(MsnSoapConnection2 *conn)
392 {
393 msn_soap_connection2_cleanup(conn);
394 g_queue_free(conn->queue); 490 g_queue_free(conn->queue);
395 g_free(conn); 491 g_free(conn);
396 } 492 }
397 493
398 MsnSoapMessage * 494 MsnSoapMessage *
399 msn_soap_message_new() 495 msn_soap_message_new(const char *action, xmlnode *xml)
400 { 496 {
401 MsnSoapMessage *req = g_new0(MsnSoapMessage, 1); 497 MsnSoapMessage *message = g_new0(MsnSoapMessage, 1);
402 498
403 return req; 499 message->action = g_strdup(action);
500 message->xml = xml;
501
502 return message;
404 } 503 }
405 504
406 void 505 void
407 msn_soap_message_destroy(MsnSoapMessage *message) 506 msn_soap_message_destroy(MsnSoapMessage *message)
408 { 507 {
409 g_slist_foreach(message->headers, (GFunc)g_free, NULL); 508 if (message) {
410 g_free(message->buf); 509 g_slist_foreach(message->headers, (GFunc)g_free, NULL);
411 g_free(message); 510 g_slist_free(message->headers);
511 g_free(message->action);
512 xmlnode_free(message->xml);
513 g_free(message);
514 }
412 } 515 }
413 516
414 void 517 void
415 msn_soap_message_add_header(MsnSoapMessage *req, 518 msn_soap_message_add_header(MsnSoapMessage *req,
416 const char *name, const char *value) 519 const char *name, const char *value)
418 char *header = g_strdup_printf("%s: %s\r\n", name, value); 521 char *header = g_strdup_printf("%s: %s\r\n", name, value);
419 522
420 req->headers = g_slist_prepend(req->headers, header); 523 req->headers = g_slist_prepend(req->headers, header);
421 } 524 }
422 525
423 MsnSoapRequest * 526 static void
424 msn_soap_request2_new(const char *host, const char *path, const char *action) 527 msn_soap_request_destroy(MsnSoapRequest *req)
425 { 528 {
426 MsnSoapRequest *req = g_new0(MsnSoapRequest, 1);
427
428 req->host = g_strdup(host);
429 req->path = g_strdup(path);
430 req->action = g_strdup(action);
431
432 return req;
433 }
434
435 void
436 msn_soap_request2_destroy(MsnSoapRequest *req)
437 {
438 g_free(req->action);
439 g_free(req->host);
440 g_free(req->path); 529 g_free(req->path);
441 msn_soap_message_destroy(req->message); 530 msn_soap_message_destroy(req->message);
442 g_free(req); 531 g_free(req);
443 } 532 }
444
445 MsnSoapResponse *
446 msn_soap_response_new(void)
447 {
448 MsnSoapResponse *resp = g_new0(MsnSoapResponse, 1);
449
450 return resp;
451 }
452
453 void
454 msn_soap_response_destroy(MsnSoapResponse *resp)
455 {
456 msn_soap_message_destroy(resp->message);
457 resp->code = -1;
458 resp->body_len = -1;
459 g_free(resp);
460 }