Mercurial > pidgin
annotate src/protocols/msn/httpconn.c @ 13918:61ba85cf05a6
[gaim-migrate @ 16421]
Paco-Paco thinks it would be good to make libgnt configure look for ncursesw.
Thanks to rekkanoryo and grim, we can do that.
committer: Tailor Script <tailor@pidgin.im>
| author | Sadrul Habib Chowdhury <imadil@gmail.com> |
|---|---|
| date | Tue, 04 Jul 2006 18:49:13 +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 } |
