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