Mercurial > pidgin.yaz
comparison libpurple/protocols/msn/soap2.c @ 20526:915e11fbaeb0
beginning of soap layer rewrite, does that even compile?
author | Ka-Hing Cheung <khc@hxbc.us> |
---|---|
date | Wed, 19 Sep 2007 06:20:08 +0000 |
parents | |
children | 0034d7e89032 |
comparison
equal
deleted
inserted
replaced
20525:5bef3197383a | 20526:915e11fbaeb0 |
---|---|
1 /** | |
2 * @file soap2.c | |
3 * C file for SOAP connection related process | |
4 * | |
5 * purple | |
6 * | |
7 * Purple is the legal property of its developers, whose names are too numerous | |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 | |
26 #include "soap2.h" | |
27 | |
28 #include "xmlnode.h" | |
29 | |
30 #include <glib.h> | |
31 #include <error.h> | |
32 | |
33 static void msn_soap_connection2_destroy_foreach_cb(gpointer item, gpointer data); | |
34 static void msn_soap_connection2_cleanup(MsnSoapConnection2 *conn); | |
35 static gboolean msn_soap_connection2_run(gpointer data); | |
36 | |
37 | |
38 MsnSoapConnection2 * | |
39 msn_soap_connection2_new(MsnSession *session) | |
40 { | |
41 MsnSoapConnection2 *conn = g_new0(MsnSoapConnection2, 1); | |
42 conn->session = session; | |
43 conn->queue = g_queue_new(); | |
44 return conn; | |
45 } | |
46 | |
47 static void | |
48 msn_soap_connected_cb(gpointer data, PurpleSslConnection *ssl, | |
49 PurpleInputCondition cond) | |
50 { | |
51 MsnSoapConnection2 *conn = data; | |
52 | |
53 conn->connected = TRUE; | |
54 | |
55 if (conn->idle_handle == 0) | |
56 conn->idle_handle = g_idle_add(msn_soap_connection2_run, conn); | |
57 } | |
58 | |
59 static void | |
60 msn_soap_error_cb(PurpleSslConnection *ssl, PurpleSslErrorType error, | |
61 gpointer data) | |
62 { | |
63 MsnSoapConnection2 *conn = data; | |
64 | |
65 msn_soap_connection2_cleanup(conn); | |
66 } | |
67 | |
68 static void | |
69 msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond) | |
70 { | |
71 MsnSoapConnection2 *conn = data; | |
72 int count; | |
73 char buf[8192]; | |
74 int linebreak; | |
75 | |
76 g_return_if_fail(cond == PURPLE_INPUT_READ); | |
77 | |
78 count = purple_ssl_read(conn->ssl, buf, sizeof(buf)); | |
79 if (count < 0 && errno == EAGAIN) | |
80 return; | |
81 else if (count <= 0) { | |
82 msn_soap_connection2_cleanup(conn); | |
83 return; | |
84 } | |
85 | |
86 if (conn->buf == NULL) { | |
87 conn->buf = g_memdup(buf, count); | |
88 conn->buf_len = len; | |
89 } else { | |
90 conn->buf = g_realloc(conn->buf, conn->buf_len + count); | |
91 memcpy(conn->buf + conn->buf_len, buf, count); | |
92 conn->buf_len += count; | |
93 } | |
94 | |
95 if (conn->response == NULL) { | |
96 conn->response = msn_soap_message_new(conn->current->action, NULL); | |
97 } | |
98 | |
99 while ((linebreak = strstr(conn->buf + conn->buf_count, "\r\n")) != NULL) { | |
100 | |
101 } | |
102 } | |
103 | |
104 static void | |
105 msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond) | |
106 { | |
107 MsnSoapConnection2 *conn = data; | |
108 int written; | |
109 | |
110 g_return_if_fail(cond == PURPLE_INPUT_WRITE); | |
111 | |
112 written = purple_ssl_write(conn->ssl, conn->buf + conn->buf_count, | |
113 conn->buf_len - conn->buf_count); | |
114 | |
115 if (written < 0 && errno == EAGAIN) | |
116 return; | |
117 else if (written <= 0) { | |
118 msn_soap_connection2_cleanup(conn); | |
119 return; | |
120 } | |
121 | |
122 conn->buf_count += written; | |
123 | |
124 if (conn->buf_count < conn->buf_len) | |
125 return; | |
126 | |
127 /* we are done! */ | |
128 g_free(conn->buf); | |
129 conn->buf_len = 0; | |
130 conn->buf_count = 0; | |
131 | |
132 purple_input_remove(conn->io_handle); | |
133 conn->io_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ, | |
134 msn_soap_read_cb, conn); | |
135 } | |
136 | |
137 static gboolean | |
138 msn_soap_connection2_run(gpointer data) | |
139 { | |
140 MsnSoapConnection2 *conn = data; | |
141 MsnSoapMessage *req = g_queue_peek_head(conn->queue); | |
142 | |
143 if (req) { | |
144 if (conn->ssl) { | |
145 if (strcmp(conn->ssl->host, req->host) != 0 || | |
146 strcmp(conn->path, req->path) != 0) { | |
147 purple_ssl_close(conn->ssl); | |
148 conn->ssl = NULL; | |
149 g_free(conn->path); | |
150 conn->path = NULL; | |
151 } | |
152 } | |
153 | |
154 if (conn->ssl == NULL) { | |
155 conn->ssl = purple_ssl_connect(conn->session->account, req->host, | |
156 443, msn_soap_connected_cb, msn_soap_error_cb, conn); | |
157 conn->path = g_strdup(req->path); | |
158 } else { | |
159 int len = -1; | |
160 char *body = xmlnode_to_str(req->message, &len); | |
161 GString *str = g_string_new(""); | |
162 GSList *iter; | |
163 | |
164 g_queue_pop_head(conn->queue); | |
165 | |
166 g_string_append_printf(str, | |
167 "POST %s HTTP/1.1\r\n" | |
168 "SOAPAction: %s\r\n" | |
169 "Content-Type:text/xml; charset=utf-8\r\n" | |
170 "Cookie: MSPAuth=%s\r\n" | |
171 "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n" | |
172 "Accept: */*\r\n" | |
173 "Host: %s\r\n" | |
174 "Content-Length: %d\r\n" | |
175 "Connection: Keep-Alive\r\n" | |
176 "Cache-Control: no-cache\r\n", | |
177 req->path, req->action, | |
178 conn->session->passport_info.mspauth, | |
179 req->host, len); | |
180 | |
181 for (iter = req->headers; iter; iter = iter->next) { | |
182 g_string_append(str, (char *)iter->data); | |
183 g_string_append(str, "\r\n"); | |
184 } | |
185 | |
186 g_string_append(str, "\r\n"); | |
187 g_string_append(str, body); | |
188 | |
189 conn->buf_len = str->len; | |
190 conn->buf = g_string_free(str, FALSE); | |
191 conn->buf_count = 0; | |
192 conn->current = req; | |
193 | |
194 conn->io_handle = purple_input_add(conn->ssl->fd, | |
195 PURPLE_INPUT_WRITE, msn_soap_write_cb, conn); | |
196 msn_soap_write_cb(conn, conn->ssl->fd, PURPLE_INPUT_WRITE); | |
197 } | |
198 } | |
199 | |
200 conn->idle_handle = 0; | |
201 return FALSE; | |
202 } | |
203 | |
204 void | |
205 msn_soap_connection2_post(MsnSoapConnection2 *conn, MsnSoapMessage *req, | |
206 const char *host, const char *path, MsnSoapCallback cb, gpointer data) | |
207 { | |
208 req->cb = cb; | |
209 req->data = data; | |
210 req->host = g_strdup(host); | |
211 req->path = g_strdup(path); | |
212 | |
213 g_queue_push_tail(conn->queue, req); | |
214 | |
215 if (conn->idle_handle == 0) | |
216 conn->idle_handle = g_idle_add(msn_soap_connection2_run, conn); | |
217 } | |
218 | |
219 static void | |
220 msn_soap_connection2_destroy_foreach_cb(gpointer item, gpointer data) | |
221 { | |
222 MsnSoapMessage *req = item; | |
223 MsnSoapConnection2 *conn = data; | |
224 | |
225 if (req->cb) | |
226 req->cb(conn, req, NULL, req->data); | |
227 | |
228 msn_soap_message_destroy(req); | |
229 } | |
230 | |
231 static void | |
232 msn_soap_connection2_cleanup(MsnSoapConnection2 *conn) | |
233 { | |
234 g_queue_foreach(conn->queue, msn_soap_connection2_destroy_foreach_cb, conn); | |
235 if (conn->current) { | |
236 msn_soap_connection2_destroy_foreach_cb(conn->current, conn); | |
237 conn->current = NULL; | |
238 } | |
239 | |
240 purple_input_remove(conn->io_handle); | |
241 conn->io_handle = 0; | |
242 g_source_remove(conn->idle_handle); | |
243 conn->idle_handle = 0; | |
244 | |
245 g_free(conn->buf); | |
246 conn->buf_len = 0; | |
247 conn->buf_count = 0; | |
248 | |
249 if (conn->ssl) { | |
250 purple_ssl_close(conn->ssl); | |
251 conn->ssl = NULL; | |
252 } | |
253 | |
254 while (g_queue_pop_head(conn->queue) != NULL); | |
255 | |
256 g_free(conn->path); | |
257 } | |
258 | |
259 void | |
260 msn_soap_connection2_destroy(MsnSoapConnection2 *conn) | |
261 { | |
262 msn_soap_connection2_cleanup(conn); | |
263 g_queue_free(conn->queue); | |
264 g_free(conn); | |
265 } | |
266 | |
267 MsnSoapMessage * | |
268 msn_soap_message_new(const char *action, xmlnode *message) | |
269 { | |
270 MsnSoapMessage *req = g_new0(MsnSoapMessage, 1); | |
271 | |
272 req->action = g_strdup(action); | |
273 req->message = message; | |
274 | |
275 return req; | |
276 } | |
277 | |
278 void | |
279 msn_soap_message_destroy(MsnSoapMessage *req) | |
280 { | |
281 g_free(req->action); | |
282 g_slist_foreach(req->headers, (GFunc)g_free, NULL); | |
283 g_free(req->host); | |
284 g_free(req->path); | |
285 g_free(req); | |
286 } | |
287 | |
288 void | |
289 msn_soap_message_add_header(MsnSoapMessage *req, | |
290 const char *name, const char *value) | |
291 { | |
292 char *header = g_strdup_printf("%s: %s\r\n", name, value); | |
293 | |
294 req->headers = g_slist_prepend(req->headers, header); | |
295 } |