Mercurial > pidgin.yaz
annotate src/protocols/msn/httpconn.c @ 19760:cabf9165c9ce
[gaim-migrate @ 16873]
change the SOAP process Framework
a initial version,can work now
committed by Ma Yuan<mayuan2006@gmail.com>
committer: Ethan Blanton <elb@pidgin.im>
author | Ma Yuan <mayuan2006@gmail.com> |
---|---|
date | Sat, 19 Aug 2006 05:52:13 +0000 |
parents | 967ef719cb62 |
children | 3ae8a3935406 |
rev | line source |
---|---|
10463 | 1 /** |
2 * @file httpmethod.c HTTP connection method | |
3 * | |
4 * gaim | |
5 * | |
6 * Gaim is the legal property of its developers, whose names are too numerous | |
7 * to list here. Please refer to the COPYRIGHT file distributed with this | |
8 * source distribution. | |
9 * | |
10 * This program is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 */ | |
24 #include "msn.h" | |
25 #include "debug.h" | |
26 #include "httpconn.h" | |
27 | |
28 static void read_cb(gpointer data, gint source, GaimInputCondition cond); | |
29 gboolean msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf, | |
30 size_t size, char **ret_buf, size_t *ret_size, | |
31 gboolean *error); | |
32 | |
33 MsnHttpConn * | |
34 msn_httpconn_new(MsnServConn *servconn) | |
35 { | |
36 MsnHttpConn *httpconn; | |
37 | |
38 g_return_val_if_fail(servconn != NULL, NULL); | |
39 | |
40 httpconn = g_new0(MsnHttpConn, 1); | |
41 | |
10481 | 42 gaim_debug_info("msn", "new httpconn (%p)\n", httpconn); |
43 | |
10463 | 44 /* TODO: Remove this */ |
45 httpconn->session = servconn->session; | |
46 | |
47 httpconn->servconn = servconn; | |
48 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
49 httpconn->tx_buf = gaim_circ_buffer_new(MSN_BUF_LEN); |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
50 httpconn->tx_handler = 0; |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
51 |
10463 | 52 return httpconn; |
53 } | |
54 | |
55 void | |
56 msn_httpconn_destroy(MsnHttpConn *httpconn) | |
57 { | |
58 g_return_if_fail(httpconn != NULL); | |
59 | |
10481 | 60 gaim_debug_info("msn", "destroy httpconn (%p)\n", httpconn); |
61 | |
10463 | 62 if (httpconn->connected) |
63 msn_httpconn_disconnect(httpconn); | |
64 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
65 g_free(httpconn->full_session_id); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
66 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
67 g_free(httpconn->session_id); |
10504 | 68 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
69 g_free(httpconn->host); |
10504 | 70 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
71 gaim_circ_buffer_destroy(httpconn->tx_buf); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
72 if (httpconn->tx_handler > 0) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
73 gaim_input_remove(httpconn->tx_handler); |
10504 | 74 |
10463 | 75 g_free(httpconn); |
76 } | |
77 | |
10568 | 78 static char * |
79 msn_httpconn_proxy_auth(MsnHttpConn *httpconn) | |
80 { | |
81 GaimAccount *account; | |
82 GaimProxyInfo *gpi; | |
83 const char *username, *password; | |
84 char *auth = NULL; | |
85 | |
86 account = httpconn->session->account; | |
87 | |
88 if (gaim_account_get_proxy_info(account) == NULL) | |
89 gpi = gaim_global_proxy_get_info(); | |
90 else | |
91 gpi = gaim_account_get_proxy_info(account); | |
92 | |
93 if (gpi == NULL || !(gaim_proxy_info_get_type(gpi) == GAIM_PROXY_HTTP || | |
94 gaim_proxy_info_get_type(gpi) == GAIM_PROXY_USE_ENVVAR)) | |
95 return NULL; | |
96 | |
97 username = gaim_proxy_info_get_username(gpi); | |
98 password = gaim_proxy_info_get_password(gpi); | |
99 | |
100 if (username != NULL) { | |
101 char *tmp; | |
102 auth = g_strdup_printf("%s:%s", username, password ? password : ""); | |
11137 | 103 tmp = gaim_base64_encode((const guchar *)auth, strlen(auth)); |
10568 | 104 g_free(auth); |
105 auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp); | |
106 g_free(tmp); | |
107 } | |
108 | |
109 return auth; | |
110 } | |
111 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
112 static void |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
113 httpconn_write_cb(gpointer data, gint source, GaimInputCondition cond) |
10463 | 114 { |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
115 MsnHttpConn *httpconn = data; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
116 int ret, writelen; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
117 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
118 if (httpconn->waiting_response) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
119 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
120 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
121 writelen = gaim_circ_buffer_get_max_read(httpconn->tx_buf); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
122 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
123 if (writelen == 0) { |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
124 httpconn->waiting_response = TRUE; |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
125 gaim_input_remove(httpconn->tx_handler); |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
126 httpconn->tx_handler = 0; |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
127 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
128 } |
10463 | 129 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
130 ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
131 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
132 if (ret < 0 && errno == EAGAIN) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
133 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
134 else if (ret <= 0) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
135 msn_servconn_got_error(httpconn->servconn, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
136 MSN_SERVCONN_ERROR_WRITE); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
137 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
138 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
139 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
140 gaim_circ_buffer_mark_read(httpconn->tx_buf, ret); |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
141 |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
142 if (ret == writelen) |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
143 httpconn_write_cb(data, source, cond); |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
144 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
145 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
146 static ssize_t |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
147 write_raw(MsnHttpConn *httpconn, const char *data, size_t data_len) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
148 { |
10463 | 149 ssize_t res; /* result of the write operation */ |
150 | |
151 #ifdef MSN_DEBUG_HTTP | |
10481 | 152 gaim_debug_misc("msn", "Writing HTTP (header): {%s}\n", header); |
10463 | 153 #endif |
154 | |
10481 | 155 |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
156 if (httpconn->tx_handler == 0 && !httpconn->waiting_response) |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
157 res = write(httpconn->fd, data, data_len); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
158 else |
10481 | 159 { |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
160 res = -1; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
161 errno = EAGAIN; |
10481 | 162 } |
163 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
164 if (res <= 0 && errno != EAGAIN) |
10463 | 165 { |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
166 msn_servconn_got_error(httpconn->servconn, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
167 MSN_SERVCONN_ERROR_WRITE); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
168 return -1; |
13277
2a9580fc922b
[gaim-migrate @ 15643]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13270
diff
changeset
|
169 } else if (res < 0 || res < data_len) { |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
170 if (res < 0) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
171 res = 0; |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
172 if (httpconn->tx_handler == 0 && httpconn->fd) |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
173 httpconn->tx_handler = gaim_input_add(httpconn->fd, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
174 GAIM_INPUT_WRITE, httpconn_write_cb, httpconn); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
175 gaim_circ_buffer_append(httpconn->tx_buf, data + res, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
176 data_len - res); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
177 } |
10481 | 178 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
179 return res; |
10463 | 180 } |
181 | |
12323
fc464a0abccc
[gaim-migrate @ 14627]
Richard Laager <rlaager@wiktel.com>
parents:
12213
diff
changeset
|
182 static void |
10463 | 183 msn_httpconn_poll(MsnHttpConn *httpconn) |
184 { | |
10481 | 185 char *header; |
10568 | 186 char *auth; |
10463 | 187 int r; |
188 | |
189 g_return_if_fail(httpconn != NULL); | |
190 | |
191 if (httpconn->waiting_response || | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
192 httpconn->tx_handler > 0) |
10463 | 193 { |
194 return; | |
195 } | |
196 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
197 /* It is OK if this is buffered because it will only be buffered if |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
198 nothing else is in the buffer */ |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
199 |
10568 | 200 auth = msn_httpconn_proxy_auth(httpconn); |
201 | |
10481 | 202 header = g_strdup_printf( |
10463 | 203 "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n" |
204 "Accept: */*\r\n" | |
205 "Accept-Language: en-us\r\n" | |
206 "User-Agent: MSMSGS\r\n" | |
207 "Host: %s\r\n" | |
208 "Proxy-Connection: Keep-Alive\r\n" | |
10568 | 209 "%s" /* Proxy auth */ |
10463 | 210 "Connection: Keep-Alive\r\n" |
211 "Pragma: no-cache\r\n" | |
212 "Content-Type: application/x-msn-messenger\r\n" | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
213 "Content-Length: 0\r\n\r\n", |
10463 | 214 httpconn->host, |
215 httpconn->full_session_id, | |
10568 | 216 httpconn->host, |
217 auth ? auth : ""); | |
218 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
219 g_free(auth); |
10463 | 220 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
221 r = write_raw(httpconn, header, strlen(header)); |
10463 | 222 |
10481 | 223 g_free(header); |
10463 | 224 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
225 if (r >= 0) |
10463 | 226 { |
227 httpconn->waiting_response = TRUE; | |
228 httpconn->dirty = FALSE; | |
229 } | |
230 } | |
231 | |
232 static gboolean | |
10543 | 233 do_poll(gpointer data) |
10463 | 234 { |
235 MsnHttpConn *httpconn; | |
236 | |
237 httpconn = data; | |
238 | |
10568 | 239 g_return_val_if_fail(httpconn != NULL, TRUE); |
240 | |
10463 | 241 #if 0 |
242 gaim_debug_info("msn", "polling from %s\n", httpconn->session_id); | |
243 #endif | |
244 | |
10568 | 245 if ((httpconn->host == NULL) || (httpconn->full_session_id == NULL)) |
246 { | |
247 gaim_debug_warning("msn", "Attempted HTTP poll before session is established\n"); | |
248 return TRUE; | |
249 } | |
250 | |
10463 | 251 if (httpconn->dirty) |
252 msn_httpconn_poll(httpconn); | |
253 | |
254 return TRUE; | |
255 } | |
256 | |
257 static void | |
258 connect_cb(gpointer data, gint source, GaimInputCondition cond) | |
259 { | |
260 MsnHttpConn *httpconn = data; | |
261 | |
262 httpconn->fd = source; | |
263 | |
264 if (source > 0) | |
265 { | |
266 httpconn->inpa = gaim_input_add(httpconn->fd, GAIM_INPUT_READ, | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
267 read_cb, data); |
10463 | 268 |
10543 | 269 httpconn->timer = gaim_timeout_add(2000, do_poll, httpconn); |
10463 | 270 |
271 httpconn->waiting_response = FALSE; | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
272 if (httpconn->tx_handler > 0) |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
273 gaim_input_remove(httpconn->tx_handler); |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
274 |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
275 httpconn->tx_handler = gaim_input_add(source, |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
276 GAIM_INPUT_WRITE, httpconn_write_cb, httpconn); |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
277 |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
278 httpconn_write_cb(httpconn, source, GAIM_INPUT_WRITE); |
10463 | 279 } |
280 else | |
281 { | |
282 gaim_debug_error("msn", "HTTP: Connection error\n"); | |
10481 | 283 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT); |
10463 | 284 } |
285 } | |
286 | |
287 gboolean | |
288 msn_httpconn_connect(MsnHttpConn *httpconn, const char *host, int port) | |
289 { | |
290 int r; | |
291 | |
292 g_return_val_if_fail(httpconn != NULL, FALSE); | |
293 g_return_val_if_fail(host != NULL, FALSE); | |
294 g_return_val_if_fail(port > 0, FALSE); | |
295 | |
296 if (httpconn->connected) | |
297 msn_httpconn_disconnect(httpconn); | |
298 | |
299 r = gaim_proxy_connect(httpconn->session->account, | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
300 "gateway.messenger.hotmail.com", 80, connect_cb, httpconn); |
10463 | 301 |
302 if (r == 0) | |
303 { | |
304 httpconn->waiting_response = TRUE; | |
305 httpconn->connected = TRUE; | |
306 } | |
307 | |
308 return httpconn->connected; | |
309 } | |
310 | |
311 void | |
312 msn_httpconn_disconnect(MsnHttpConn *httpconn) | |
313 { | |
314 g_return_if_fail(httpconn != NULL); | |
10481 | 315 |
316 if (!httpconn->connected) | |
317 return; | |
10463 | 318 |
319 if (httpconn->timer) | |
320 gaim_timeout_remove(httpconn->timer); | |
321 | |
322 httpconn->timer = 0; | |
323 | |
324 if (httpconn->inpa > 0) | |
325 { | |
326 gaim_input_remove(httpconn->inpa); | |
327 httpconn->inpa = 0; | |
328 } | |
329 | |
330 close(httpconn->fd); | |
331 | |
13630
bbc56ff2bd62
[gaim-migrate @ 16017]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13516
diff
changeset
|
332 g_free(httpconn->rx_buf); |
10463 | 333 httpconn->rx_buf = NULL; |
334 httpconn->rx_len = 0; | |
335 | |
336 httpconn->connected = FALSE; | |
337 | |
338 /* msn_servconn_disconnect(httpconn->servconn); */ | |
339 } | |
340 | |
341 static void | |
342 read_cb(gpointer data, gint source, GaimInputCondition cond) | |
343 { | |
344 MsnHttpConn *httpconn; | |
345 MsnServConn *servconn; | |
346 MsnSession *session; | |
347 char buf[MSN_BUF_LEN]; | |
348 char *cur, *end, *old_rx_buf; | |
349 int len, cur_len; | |
350 char *result_msg = NULL; | |
351 size_t result_len = 0; | |
352 gboolean error; | |
353 | |
354 httpconn = data; | |
355 servconn = NULL; | |
356 session = httpconn->session; | |
357 | |
358 len = read(httpconn->fd, buf, sizeof(buf) - 1); | |
359 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
360 if (len < 0 && errno == EAGAIN) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
361 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
362 else if (len <= 0) |
10463 | 363 { |
364 gaim_debug_error("msn", "HTTP: Read error\n"); | |
10481 | 365 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); |
10463 | 366 |
367 return; | |
368 } | |
369 | |
370 buf[len] = '\0'; | |
371 | |
372 httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1); | |
373 memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1); | |
374 httpconn->rx_len += len; | |
375 | |
376 if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len, | |
377 &result_msg, &result_len, &error)) | |
378 { | |
10568 | 379 /* We must wait for more input, or something went wrong */ |
380 if (error) | |
381 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); | |
10463 | 382 |
383 return; | |
384 } | |
385 | |
386 httpconn->servconn->processing = FALSE; | |
387 | |
388 servconn = httpconn->servconn; | |
389 | |
390 if (error) | |
391 { | |
392 gaim_debug_error("msn", "HTTP: Special error\n"); | |
10481 | 393 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); |
10463 | 394 |
395 return; | |
396 } | |
397 | |
13630
bbc56ff2bd62
[gaim-migrate @ 16017]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13516
diff
changeset
|
398 g_free(httpconn->rx_buf); |
10533 | 399 httpconn->rx_buf = NULL; |
400 httpconn->rx_len = 0; | |
401 | |
10463 | 402 if (result_len == 0) |
403 { | |
404 /* Nothing to do here */ | |
405 #if 0 | |
406 gaim_debug_info("msn", "HTTP: nothing to do here\n"); | |
407 #endif | |
10481 | 408 g_free(result_msg); |
10463 | 409 return; |
410 } | |
411 | |
13270
8754a0fe2297
[gaim-migrate @ 15636]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13200
diff
changeset
|
412 g_free(servconn->rx_buf); |
10463 | 413 servconn->rx_buf = result_msg; |
414 servconn->rx_len = result_len; | |
415 | |
416 end = old_rx_buf = servconn->rx_buf; | |
417 | |
418 servconn->processing = TRUE; | |
419 | |
420 do | |
421 { | |
422 cur = end; | |
423 | |
424 if (servconn->payload_len) | |
425 { | |
426 if (servconn->payload_len > servconn->rx_len) | |
427 /* The payload is still not complete. */ | |
428 break; | |
429 | |
430 cur_len = servconn->payload_len; | |
431 end += cur_len; | |
432 } | |
433 else | |
434 { | |
435 end = strstr(cur, "\r\n"); | |
436 | |
437 if (end == NULL) | |
438 /* The command is still not complete. */ | |
439 break; | |
440 | |
441 *end = '\0'; | |
442 end += 2; | |
443 cur_len = end - cur; | |
444 } | |
445 | |
446 servconn->rx_len -= cur_len; | |
447 | |
448 if (servconn->payload_len) | |
449 { | |
450 msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len); | |
451 servconn->payload_len = 0; | |
452 } | |
453 else | |
454 { | |
455 msn_cmdproc_process_cmd_text(servconn->cmdproc, cur); | |
456 } | |
457 } while (servconn->connected && servconn->rx_len > 0); | |
458 | |
459 if (servconn->connected) | |
460 { | |
461 if (servconn->rx_len > 0) | |
462 servconn->rx_buf = g_memdup(cur, servconn->rx_len); | |
463 else | |
464 servconn->rx_buf = NULL; | |
465 } | |
466 | |
467 servconn->processing = FALSE; | |
468 | |
469 if (servconn->wasted) | |
470 msn_servconn_destroy(servconn); | |
471 | |
472 g_free(old_rx_buf); | |
473 } | |
474 | |
13270
8754a0fe2297
[gaim-migrate @ 15636]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13200
diff
changeset
|
475 ssize_t |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
476 msn_httpconn_write(MsnHttpConn *httpconn, const char *body, size_t size) |
10463 | 477 { |
478 char *params; | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
479 char *data; |
10568 | 480 char *auth; |
10463 | 481 const char *server_types[] = { "NS", "SB" }; |
482 const char *server_type; | |
13270
8754a0fe2297
[gaim-migrate @ 15636]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13200
diff
changeset
|
483 ssize_t r; /* result of the write operation */ |
10463 | 484 char *host; |
485 MsnServConn *servconn; | |
486 | |
487 /* TODO: remove http data from servconn */ | |
488 | |
489 g_return_val_if_fail(httpconn != NULL, 0); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
490 g_return_val_if_fail(body != NULL, 0); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
491 g_return_val_if_fail(size > 0, 0); |
10463 | 492 |
493 servconn = httpconn->servconn; | |
494 | |
495 server_type = server_types[servconn->type]; | |
496 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
497 if (httpconn->virgin) |
10463 | 498 { |
499 host = "gateway.messenger.hotmail.com"; | |
500 | |
501 /* The first time servconn->host is the host we should connect to. */ | |
502 params = g_strdup_printf("Action=open&Server=%s&IP=%s", | |
503 server_type, | |
504 servconn->host); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
505 httpconn->virgin = FALSE; |
10463 | 506 } |
507 else | |
508 { | |
509 /* The rest of the times servconn->host is the gateway host. */ | |
510 host = httpconn->host; | |
511 | |
10568 | 512 if (host == NULL || httpconn->full_session_id == NULL) |
513 { | |
514 gaim_debug_warning("msn", "Attempted HTTP write before session is established\n"); | |
515 return -1; | |
516 } | |
517 | |
10463 | 518 params = g_strdup_printf("SessionID=%s", |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
519 httpconn->full_session_id); |
10463 | 520 } |
521 | |
10568 | 522 auth = msn_httpconn_proxy_auth(httpconn); |
523 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
524 data = g_strdup_printf( |
10463 | 525 "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n" |
526 "Accept: */*\r\n" | |
527 "Accept-Language: en-us\r\n" | |
528 "User-Agent: MSMSGS\r\n" | |
529 "Host: %s\r\n" | |
530 "Proxy-Connection: Keep-Alive\r\n" | |
10568 | 531 "%s" /* Proxy auth */ |
10463 | 532 "Connection: Keep-Alive\r\n" |
533 "Pragma: no-cache\r\n" | |
534 "Content-Type: application/x-msn-messenger\r\n" | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
535 "Content-Length: %d\r\n\r\n" |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
536 "%s", |
10463 | 537 host, |
538 params, | |
539 host, | |
10568 | 540 auth ? auth : "", |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
541 (int) size, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
542 body ? body : ""); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
543 |
10463 | 544 |
545 g_free(params); | |
546 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
547 g_free(auth); |
10568 | 548 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
549 r = write_raw(httpconn, data, strlen(data)); |
10463 | 550 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
551 g_free(data); |
10463 | 552 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
553 if (r >= 0) |
10463 | 554 { |
555 httpconn->waiting_response = TRUE; | |
556 httpconn->dirty = FALSE; | |
557 } | |
558 | |
559 return r; | |
560 } | |
561 | |
562 gboolean | |
563 msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf, | |
564 size_t size, char **ret_buf, size_t *ret_size, | |
565 gboolean *error) | |
566 { | |
567 const char *s, *c; | |
10481 | 568 char *header, *body; |
10463 | 569 const char *body_start; |
570 char *tmp; | |
571 size_t body_len = 0; | |
572 gboolean wasted = FALSE; | |
573 | |
574 g_return_val_if_fail(httpconn != NULL, FALSE); | |
575 g_return_val_if_fail(buf != NULL, FALSE); | |
576 g_return_val_if_fail(size > 0, FALSE); | |
577 g_return_val_if_fail(ret_buf != NULL, FALSE); | |
578 g_return_val_if_fail(ret_size != NULL, FALSE); | |
579 g_return_val_if_fail(error != NULL, FALSE); | |
580 | |
581 #if 0 | |
582 gaim_debug_info("msn", "HTTP: parsing data {%s}\n", buf); | |
583 #endif | |
584 | |
585 httpconn->waiting_response = FALSE; | |
586 | |
587 /* Healthy defaults. */ | |
588 body = NULL; | |
589 | |
590 *ret_buf = NULL; | |
591 *ret_size = 0; | |
592 *error = FALSE; | |
593 | |
594 /* First, some tests to see if we have a full block of stuff. */ | |
595 if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) && | |
596 (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) && | |
597 ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) && | |
598 (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0))) | |
599 { | |
600 *error = TRUE; | |
601 | |
602 return FALSE; | |
603 } | |
604 | |
605 if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0) | |
606 { | |
607 if ((s = strstr(buf, "\r\n\r\n")) == NULL) | |
608 return FALSE; | |
609 | |
610 s += 4; | |
611 | |
612 if (*s == '\0') | |
613 { | |
614 *ret_buf = g_strdup(""); | |
615 *ret_size = 0; | |
616 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
617 if (httpconn->tx_handler > 0) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
618 httpconn_write_cb(httpconn, httpconn->fd, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
619 GAIM_INPUT_WRITE); |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
620 else |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
621 httpconn->dirty = TRUE; |
10463 | 622 |
623 return TRUE; | |
624 } | |
625 | |
626 buf = s; | |
627 size -= (s - buf); | |
628 } | |
629 | |
630 if ((s = strstr(buf, "\r\n\r\n")) == NULL) | |
631 return FALSE; | |
632 | |
10718 | 633 s += 4; /* Skip \r\n */ |
10481 | 634 header = g_strndup(buf, s - buf); |
10463 | 635 body_start = s; |
636 body_len = size - (body_start - buf); | |
637 | |
12213 | 638 if ((s = gaim_strcasestr(header, "Content-Length: ")) != NULL) |
10463 | 639 { |
640 int tmp_len; | |
641 | |
642 s += strlen("Content-Length: "); | |
643 | |
644 if ((c = strchr(s, '\r')) == NULL) | |
645 { | |
10481 | 646 g_free(header); |
10463 | 647 |
648 return FALSE; | |
649 } | |
650 | |
651 tmp = g_strndup(s, c - s); | |
652 tmp_len = atoi(tmp); | |
653 g_free(tmp); | |
654 | |
655 if (body_len != tmp_len) | |
656 { | |
10481 | 657 g_free(header); |
10463 | 658 |
659 #if 0 | |
660 gaim_debug_warning("msn", | |
661 "body length (%d) != content length (%d)\n", | |
662 body_len, tmp_len); | |
663 #endif | |
664 | |
665 return FALSE; | |
666 } | |
667 } | |
668 | |
10481 | 669 body = g_malloc0(body_len + 1); |
670 memcpy(body, body_start, body_len); | |
10463 | 671 |
672 #ifdef MSN_DEBUG_HTTP | |
10481 | 673 gaim_debug_misc("msn", "Incoming HTTP buffer (header): {%s\r\n}\n", |
674 header); | |
10463 | 675 #endif |
676 | |
677 /* Now we should be able to process the data. */ | |
12213 | 678 if ((s = gaim_strcasestr(header, "X-MSN-Messenger: ")) != NULL) |
10463 | 679 { |
680 char *full_session_id, *gw_ip, *session_action; | |
681 char *t, *session_id; | |
682 char **elems, **cur, **tokens; | |
683 | |
684 full_session_id = gw_ip = session_action = NULL; | |
685 | |
686 s += strlen("X-MSN-Messenger: "); | |
687 | |
688 if ((c = strchr(s, '\r')) == NULL) | |
689 { | |
10481 | 690 msn_session_set_error(httpconn->session, |
691 MSN_ERROR_HTTP_MALFORMED, NULL); | |
10463 | 692 gaim_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}", |
693 buf); | |
694 | |
10481 | 695 g_free(body); |
10463 | 696 return FALSE; |
697 } | |
698 | |
699 tmp = g_strndup(s, c - s); | |
700 | |
701 elems = g_strsplit(tmp, "; ", 0); | |
702 | |
703 for (cur = elems; *cur != NULL; cur++) | |
704 { | |
705 tokens = g_strsplit(*cur, "=", 2); | |
706 | |
707 if (strcmp(tokens[0], "SessionID") == 0) | |
708 full_session_id = tokens[1]; | |
709 else if (strcmp(tokens[0], "GW-IP") == 0) | |
710 gw_ip = tokens[1]; | |
711 else if (strcmp(tokens[0], "Session") == 0) | |
712 session_action = tokens[1]; | |
713 | |
714 g_free(tokens[0]); | |
715 /* Don't free each of the tokens, only the array. */ | |
716 g_free(tokens); | |
717 } | |
718 | |
719 g_strfreev(elems); | |
720 | |
721 g_free(tmp); | |
722 | |
723 if ((session_action != NULL) && (strcmp(session_action, "close") == 0)) | |
724 wasted = TRUE; | |
725 | |
726 g_free(session_action); | |
727 | |
728 t = strchr(full_session_id, '.'); | |
729 session_id = g_strndup(full_session_id, t - full_session_id); | |
730 | |
731 if (!wasted) | |
732 { | |
13630
bbc56ff2bd62
[gaim-migrate @ 16017]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13516
diff
changeset
|
733 g_free(httpconn->full_session_id); |
10463 | 734 |
735 httpconn->full_session_id = full_session_id; | |
736 | |
13630
bbc56ff2bd62
[gaim-migrate @ 16017]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13516
diff
changeset
|
737 g_free(httpconn->session_id); |
10463 | 738 |
739 httpconn->session_id = session_id; | |
740 | |
13630
bbc56ff2bd62
[gaim-migrate @ 16017]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13516
diff
changeset
|
741 g_free(httpconn->host); |
10463 | 742 |
743 httpconn->host = gw_ip; | |
744 } | |
745 else | |
746 { | |
747 MsnServConn *servconn; | |
748 | |
749 /* It's going to die. */ | |
10504 | 750 /* poor thing */ |
10463 | 751 |
752 servconn = httpconn->servconn; | |
753 | |
10533 | 754 /* I'll be honest, I don't fully understand all this, but this |
755 * causes crashes, Stu. */ | |
756 /* if (servconn != NULL) | |
757 servconn->wasted = TRUE; */ | |
10463 | 758 |
759 g_free(full_session_id); | |
10504 | 760 g_free(session_id); |
10463 | 761 g_free(gw_ip); |
762 } | |
763 } | |
764 | |
10481 | 765 g_free(header); |
10463 | 766 |
767 *ret_buf = body; | |
768 *ret_size = body_len; | |
769 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
770 if (httpconn->tx_handler > 0) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
771 httpconn_write_cb(httpconn, httpconn->fd, GAIM_INPUT_WRITE); |
13516
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
772 else |
4279e5b5e9ac
[gaim-migrate @ 15892]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13277
diff
changeset
|
773 httpconn->dirty = TRUE; |
10463 | 774 |
775 return TRUE; | |
776 } |