Mercurial > pidgin
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 } |