Mercurial > pidgin
annotate src/protocols/msn/httpconn.c @ 13303:dc396c7dbcf9
[gaim-migrate @ 15669]
There was an attempt to make each Jabber resource have its own conversation
window, which wasn't working, and instead sending outgoing messages to the
wrong resource. Different conversations with each resource breaks the whole
"Send to" one-window-per-person metaphor, so I just changed the behavior to
send messages to whichever resources last messaged you. Perhaps later, when
we're not in a freeze, we can consider an API that allows prpls to populate
the Send To menu themselves, letting you easily switch what resource you're
chatting with in the same window
committer: Tailor Script <tailor@pidgin.im>
| author | Sean Egan <seanegan@gmail.com> |
|---|---|
| date | Thu, 16 Feb 2006 23:02:56 +0000 |
| parents | 2a9580fc922b |
| children | 4279e5b5e9ac |
| 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); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
50 httpconn->tx_handler = -1; |
|
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) { |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
124 gaim_input_remove(httpconn->tx_handler); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
125 httpconn->tx_handler = -1; |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
126 return; |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
127 } |
| 10463 | 128 |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
129 ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
130 |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
131 if (ret < 0 && errno == EAGAIN) |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
132 return; |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
133 else if (ret <= 0) { |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
134 msn_servconn_got_error(httpconn->servconn, |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
135 MSN_SERVCONN_ERROR_WRITE); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
136 return; |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
137 } |
|
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 gaim_circ_buffer_mark_read(httpconn->tx_buf, ret); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
140 } |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
141 |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
142 static ssize_t |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
143 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
|
144 { |
| 10463 | 145 ssize_t res; /* result of the write operation */ |
| 146 | |
| 147 #ifdef MSN_DEBUG_HTTP | |
| 10481 | 148 gaim_debug_misc("msn", "Writing HTTP (header): {%s}\n", header); |
| 10463 | 149 #endif |
| 150 | |
| 10481 | 151 |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
152 if (httpconn->tx_handler == -1 && !httpconn->waiting_response) |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
153 res = write(httpconn->fd, data, data_len); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
154 else |
| 10481 | 155 { |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
156 res = -1; |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
157 errno = EAGAIN; |
| 10481 | 158 } |
| 159 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
160 if (res <= 0 && errno != EAGAIN) |
| 10463 | 161 { |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
162 msn_servconn_got_error(httpconn->servconn, |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
163 MSN_SERVCONN_ERROR_WRITE); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
164 return -1; |
|
13277
2a9580fc922b
[gaim-migrate @ 15643]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13270
diff
changeset
|
165 } else if (res < 0 || res < data_len) { |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
166 if (res < 0) |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
167 res = 0; |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
168 if (httpconn->tx_handler == -1) |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
169 httpconn->tx_handler = gaim_input_add(httpconn->fd, |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
170 GAIM_INPUT_WRITE, httpconn_write_cb, httpconn); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
171 gaim_circ_buffer_append(httpconn->tx_buf, data + res, |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
172 data_len - res); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
173 } |
| 10481 | 174 |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
175 return res; |
| 10463 | 176 } |
| 177 | |
|
12323
fc464a0abccc
[gaim-migrate @ 14627]
Richard Laager <rlaager@wiktel.com>
parents:
12213
diff
changeset
|
178 static void |
| 10463 | 179 msn_httpconn_poll(MsnHttpConn *httpconn) |
| 180 { | |
| 10481 | 181 char *header; |
| 10568 | 182 char *auth; |
| 10463 | 183 int r; |
| 184 | |
| 185 g_return_if_fail(httpconn != NULL); | |
| 186 | |
| 187 if (httpconn->waiting_response || | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
188 httpconn->tx_handler > 0) |
| 10463 | 189 { |
| 190 return; | |
| 191 } | |
| 192 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
193 /* 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
|
194 nothing else is in the buffer */ |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
195 |
| 10568 | 196 auth = msn_httpconn_proxy_auth(httpconn); |
| 197 | |
| 10481 | 198 header = g_strdup_printf( |
| 10463 | 199 "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n" |
| 200 "Accept: */*\r\n" | |
| 201 "Accept-Language: en-us\r\n" | |
| 202 "User-Agent: MSMSGS\r\n" | |
| 203 "Host: %s\r\n" | |
| 204 "Proxy-Connection: Keep-Alive\r\n" | |
| 10568 | 205 "%s" /* Proxy auth */ |
| 10463 | 206 "Connection: Keep-Alive\r\n" |
| 207 "Pragma: no-cache\r\n" | |
| 208 "Content-Type: application/x-msn-messenger\r\n" | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
209 "Content-Length: 0\r\n\r\n", |
| 10463 | 210 httpconn->host, |
| 211 httpconn->full_session_id, | |
| 10568 | 212 httpconn->host, |
| 213 auth ? auth : ""); | |
| 214 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
215 g_free(auth); |
| 10463 | 216 |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
217 r = write_raw(httpconn, header, strlen(header)); |
| 10463 | 218 |
| 10481 | 219 g_free(header); |
| 10463 | 220 |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
221 if (r >= 0) |
| 10463 | 222 { |
| 223 httpconn->waiting_response = TRUE; | |
| 224 httpconn->dirty = FALSE; | |
| 225 } | |
| 226 } | |
| 227 | |
| 228 static gboolean | |
| 10543 | 229 do_poll(gpointer data) |
| 10463 | 230 { |
| 231 MsnHttpConn *httpconn; | |
| 232 | |
| 233 httpconn = data; | |
| 234 | |
| 10568 | 235 g_return_val_if_fail(httpconn != NULL, TRUE); |
| 236 | |
| 10463 | 237 #if 0 |
| 238 gaim_debug_info("msn", "polling from %s\n", httpconn->session_id); | |
| 239 #endif | |
| 240 | |
| 10568 | 241 if ((httpconn->host == NULL) || (httpconn->full_session_id == NULL)) |
| 242 { | |
| 243 gaim_debug_warning("msn", "Attempted HTTP poll before session is established\n"); | |
| 244 return TRUE; | |
| 245 } | |
| 246 | |
| 10463 | 247 if (httpconn->dirty) |
| 248 msn_httpconn_poll(httpconn); | |
| 249 | |
| 250 return TRUE; | |
| 251 } | |
| 252 | |
| 253 static void | |
| 254 connect_cb(gpointer data, gint source, GaimInputCondition cond) | |
| 255 { | |
| 256 MsnHttpConn *httpconn = data; | |
| 257 | |
| 258 httpconn->fd = source; | |
| 259 | |
| 260 if (source > 0) | |
| 261 { | |
| 262 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
|
263 read_cb, data); |
| 10463 | 264 |
| 10543 | 265 httpconn->timer = gaim_timeout_add(2000, do_poll, httpconn); |
| 10463 | 266 |
| 267 httpconn->waiting_response = FALSE; | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
268 if (httpconn->tx_handler > 0) |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
269 httpconn_write_cb(httpconn, source, GAIM_INPUT_WRITE); |
| 10463 | 270 } |
| 271 else | |
| 272 { | |
| 273 gaim_debug_error("msn", "HTTP: Connection error\n"); | |
| 10481 | 274 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT); |
| 10463 | 275 } |
| 276 } | |
| 277 | |
| 278 gboolean | |
| 279 msn_httpconn_connect(MsnHttpConn *httpconn, const char *host, int port) | |
| 280 { | |
| 281 int r; | |
| 282 | |
| 283 g_return_val_if_fail(httpconn != NULL, FALSE); | |
| 284 g_return_val_if_fail(host != NULL, FALSE); | |
| 285 g_return_val_if_fail(port > 0, FALSE); | |
| 286 | |
| 287 if (httpconn->connected) | |
| 288 msn_httpconn_disconnect(httpconn); | |
| 289 | |
| 290 r = gaim_proxy_connect(httpconn->session->account, | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
291 "gateway.messenger.hotmail.com", 80, connect_cb, httpconn); |
| 10463 | 292 |
| 293 if (r == 0) | |
| 294 { | |
| 295 httpconn->waiting_response = TRUE; | |
| 296 httpconn->connected = TRUE; | |
| 297 } | |
| 298 | |
| 299 return httpconn->connected; | |
| 300 } | |
| 301 | |
| 302 void | |
| 303 msn_httpconn_disconnect(MsnHttpConn *httpconn) | |
| 304 { | |
| 305 g_return_if_fail(httpconn != NULL); | |
| 10481 | 306 |
| 307 if (!httpconn->connected) | |
| 308 return; | |
| 10463 | 309 |
| 310 if (httpconn->timer) | |
| 311 gaim_timeout_remove(httpconn->timer); | |
| 312 | |
| 313 httpconn->timer = 0; | |
| 314 | |
| 315 if (httpconn->inpa > 0) | |
| 316 { | |
| 317 gaim_input_remove(httpconn->inpa); | |
| 318 httpconn->inpa = 0; | |
| 319 } | |
| 320 | |
| 321 close(httpconn->fd); | |
| 322 | |
| 323 httpconn->rx_buf = NULL; | |
| 324 httpconn->rx_len = 0; | |
| 325 | |
| 326 httpconn->connected = FALSE; | |
| 327 | |
| 328 /* msn_servconn_disconnect(httpconn->servconn); */ | |
| 329 } | |
| 330 | |
| 331 static void | |
| 332 read_cb(gpointer data, gint source, GaimInputCondition cond) | |
| 333 { | |
| 334 MsnHttpConn *httpconn; | |
| 335 MsnServConn *servconn; | |
| 336 MsnSession *session; | |
| 337 char buf[MSN_BUF_LEN]; | |
| 338 char *cur, *end, *old_rx_buf; | |
| 339 int len, cur_len; | |
| 340 char *result_msg = NULL; | |
| 341 size_t result_len = 0; | |
| 342 gboolean error; | |
| 343 | |
| 344 httpconn = data; | |
| 345 servconn = NULL; | |
| 346 session = httpconn->session; | |
| 347 | |
| 348 len = read(httpconn->fd, buf, sizeof(buf) - 1); | |
| 349 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
350 if (len < 0 && errno == EAGAIN) |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
351 return; |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
352 else if (len <= 0) |
| 10463 | 353 { |
| 354 gaim_debug_error("msn", "HTTP: Read error\n"); | |
| 10481 | 355 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); |
| 10463 | 356 |
| 357 return; | |
| 358 } | |
| 359 | |
| 360 buf[len] = '\0'; | |
| 361 | |
| 362 httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1); | |
| 363 memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1); | |
| 364 httpconn->rx_len += len; | |
| 365 | |
| 366 if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len, | |
| 367 &result_msg, &result_len, &error)) | |
| 368 { | |
| 10568 | 369 /* We must wait for more input, or something went wrong */ |
| 370 if (error) | |
| 371 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); | |
| 10463 | 372 |
| 373 return; | |
| 374 } | |
| 375 | |
| 376 httpconn->servconn->processing = FALSE; | |
| 377 | |
| 378 servconn = httpconn->servconn; | |
| 379 | |
| 380 if (error) | |
| 381 { | |
| 382 gaim_debug_error("msn", "HTTP: Special error\n"); | |
| 10481 | 383 msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ); |
| 10463 | 384 |
| 385 return; | |
| 386 } | |
| 387 | |
| 10533 | 388 if (httpconn->rx_buf != NULL) |
| 389 g_free(httpconn->rx_buf); | |
| 390 httpconn->rx_buf = NULL; | |
| 391 httpconn->rx_len = 0; | |
| 392 | |
| 10463 | 393 if (result_len == 0) |
| 394 { | |
| 395 /* Nothing to do here */ | |
| 396 #if 0 | |
| 397 gaim_debug_info("msn", "HTTP: nothing to do here\n"); | |
| 398 #endif | |
| 10481 | 399 g_free(result_msg); |
| 10463 | 400 return; |
| 401 } | |
| 402 | |
|
13270
8754a0fe2297
[gaim-migrate @ 15636]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13200
diff
changeset
|
403 g_free(servconn->rx_buf); |
| 10463 | 404 servconn->rx_buf = result_msg; |
| 405 servconn->rx_len = result_len; | |
| 406 | |
| 407 end = old_rx_buf = servconn->rx_buf; | |
| 408 | |
| 409 servconn->processing = TRUE; | |
| 410 | |
| 411 do | |
| 412 { | |
| 413 cur = end; | |
| 414 | |
| 415 if (servconn->payload_len) | |
| 416 { | |
| 417 if (servconn->payload_len > servconn->rx_len) | |
| 418 /* The payload is still not complete. */ | |
| 419 break; | |
| 420 | |
| 421 cur_len = servconn->payload_len; | |
| 422 end += cur_len; | |
| 423 } | |
| 424 else | |
| 425 { | |
| 426 end = strstr(cur, "\r\n"); | |
| 427 | |
| 428 if (end == NULL) | |
| 429 /* The command is still not complete. */ | |
| 430 break; | |
| 431 | |
| 432 *end = '\0'; | |
| 433 end += 2; | |
| 434 cur_len = end - cur; | |
| 435 } | |
| 436 | |
| 437 servconn->rx_len -= cur_len; | |
| 438 | |
| 439 if (servconn->payload_len) | |
| 440 { | |
| 441 msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len); | |
| 442 servconn->payload_len = 0; | |
| 443 } | |
| 444 else | |
| 445 { | |
| 446 msn_cmdproc_process_cmd_text(servconn->cmdproc, cur); | |
| 447 } | |
| 448 } while (servconn->connected && servconn->rx_len > 0); | |
| 449 | |
| 450 if (servconn->connected) | |
| 451 { | |
| 452 if (servconn->rx_len > 0) | |
| 453 servconn->rx_buf = g_memdup(cur, servconn->rx_len); | |
| 454 else | |
| 455 servconn->rx_buf = NULL; | |
| 456 } | |
| 457 | |
| 458 servconn->processing = FALSE; | |
| 459 | |
| 460 if (servconn->wasted) | |
| 461 msn_servconn_destroy(servconn); | |
| 462 | |
| 463 g_free(old_rx_buf); | |
| 464 } | |
| 465 | |
|
13270
8754a0fe2297
[gaim-migrate @ 15636]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13200
diff
changeset
|
466 ssize_t |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
467 msn_httpconn_write(MsnHttpConn *httpconn, const char *body, size_t size) |
| 10463 | 468 { |
| 469 char *params; | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
470 char *data; |
| 10568 | 471 char *auth; |
| 10463 | 472 const char *server_types[] = { "NS", "SB" }; |
| 473 const char *server_type; | |
|
13270
8754a0fe2297
[gaim-migrate @ 15636]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13200
diff
changeset
|
474 ssize_t r; /* result of the write operation */ |
| 10463 | 475 char *host; |
| 476 MsnServConn *servconn; | |
| 477 | |
| 478 /* TODO: remove http data from servconn */ | |
| 479 | |
| 480 g_return_val_if_fail(httpconn != NULL, 0); | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
481 g_return_val_if_fail(body != NULL, 0); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
482 g_return_val_if_fail(size > 0, 0); |
| 10463 | 483 |
| 484 servconn = httpconn->servconn; | |
| 485 | |
| 486 server_type = server_types[servconn->type]; | |
| 487 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
488 if (httpconn->virgin) |
| 10463 | 489 { |
| 490 host = "gateway.messenger.hotmail.com"; | |
| 491 | |
| 492 /* The first time servconn->host is the host we should connect to. */ | |
| 493 params = g_strdup_printf("Action=open&Server=%s&IP=%s", | |
| 494 server_type, | |
| 495 servconn->host); | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
496 httpconn->virgin = FALSE; |
| 10463 | 497 } |
| 498 else | |
| 499 { | |
| 500 /* The rest of the times servconn->host is the gateway host. */ | |
| 501 host = httpconn->host; | |
| 502 | |
| 10568 | 503 if (host == NULL || httpconn->full_session_id == NULL) |
| 504 { | |
| 505 gaim_debug_warning("msn", "Attempted HTTP write before session is established\n"); | |
| 506 return -1; | |
| 507 } | |
| 508 | |
| 10463 | 509 params = g_strdup_printf("SessionID=%s", |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
510 httpconn->full_session_id); |
| 10463 | 511 } |
| 512 | |
| 10568 | 513 auth = msn_httpconn_proxy_auth(httpconn); |
| 514 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
515 data = g_strdup_printf( |
| 10463 | 516 "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n" |
| 517 "Accept: */*\r\n" | |
| 518 "Accept-Language: en-us\r\n" | |
| 519 "User-Agent: MSMSGS\r\n" | |
| 520 "Host: %s\r\n" | |
| 521 "Proxy-Connection: Keep-Alive\r\n" | |
| 10568 | 522 "%s" /* Proxy auth */ |
| 10463 | 523 "Connection: Keep-Alive\r\n" |
| 524 "Pragma: no-cache\r\n" | |
| 525 "Content-Type: application/x-msn-messenger\r\n" | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
526 "Content-Length: %d\r\n\r\n" |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
527 "%s", |
| 10463 | 528 host, |
| 529 params, | |
| 530 host, | |
| 10568 | 531 auth ? auth : "", |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
532 (int) size, |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
533 body ? body : ""); |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
534 |
| 10463 | 535 |
| 536 g_free(params); | |
| 537 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
538 g_free(auth); |
| 10568 | 539 |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
540 r = write_raw(httpconn, data, strlen(data)); |
| 10463 | 541 |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
542 g_free(data); |
| 10463 | 543 |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
544 if (r >= 0) |
| 10463 | 545 { |
| 546 httpconn->waiting_response = TRUE; | |
| 547 httpconn->dirty = FALSE; | |
| 548 } | |
| 549 | |
| 550 return r; | |
| 551 } | |
| 552 | |
| 553 gboolean | |
| 554 msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf, | |
| 555 size_t size, char **ret_buf, size_t *ret_size, | |
| 556 gboolean *error) | |
| 557 { | |
| 558 GaimConnection *gc; | |
| 559 const char *s, *c; | |
| 10481 | 560 char *header, *body; |
| 10463 | 561 const char *body_start; |
| 562 char *tmp; | |
| 563 size_t body_len = 0; | |
| 564 gboolean wasted = FALSE; | |
| 565 | |
| 566 g_return_val_if_fail(httpconn != NULL, FALSE); | |
| 567 g_return_val_if_fail(buf != NULL, FALSE); | |
| 568 g_return_val_if_fail(size > 0, FALSE); | |
| 569 g_return_val_if_fail(ret_buf != NULL, FALSE); | |
| 570 g_return_val_if_fail(ret_size != NULL, FALSE); | |
| 571 g_return_val_if_fail(error != NULL, FALSE); | |
| 572 | |
| 573 #if 0 | |
| 574 gaim_debug_info("msn", "HTTP: parsing data {%s}\n", buf); | |
| 575 #endif | |
| 576 | |
| 577 httpconn->waiting_response = FALSE; | |
| 578 | |
| 579 gc = gaim_account_get_connection(httpconn->session->account); | |
| 580 | |
| 581 /* Healthy defaults. */ | |
| 582 body = NULL; | |
| 583 | |
| 584 *ret_buf = NULL; | |
| 585 *ret_size = 0; | |
| 586 *error = FALSE; | |
| 587 | |
| 588 /* First, some tests to see if we have a full block of stuff. */ | |
| 589 if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) && | |
| 590 (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) && | |
| 591 ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) && | |
| 592 (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0))) | |
| 593 { | |
| 594 *error = TRUE; | |
| 595 | |
| 596 return FALSE; | |
| 597 } | |
| 598 | |
| 599 if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0) | |
| 600 { | |
| 601 if ((s = strstr(buf, "\r\n\r\n")) == NULL) | |
| 602 return FALSE; | |
| 603 | |
| 604 s += 4; | |
| 605 | |
| 606 if (*s == '\0') | |
| 607 { | |
| 608 *ret_buf = g_strdup(""); | |
| 609 *ret_size = 0; | |
| 610 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
611 if (httpconn->tx_handler > 0) |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
612 httpconn_write_cb(httpconn, httpconn->fd, |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
613 GAIM_INPUT_WRITE); |
| 10463 | 614 |
| 615 return TRUE; | |
| 616 } | |
| 617 | |
| 618 buf = s; | |
| 619 size -= (s - buf); | |
| 620 } | |
| 621 | |
| 622 if ((s = strstr(buf, "\r\n\r\n")) == NULL) | |
| 623 return FALSE; | |
| 624 | |
| 10718 | 625 s += 4; /* Skip \r\n */ |
| 10481 | 626 header = g_strndup(buf, s - buf); |
| 10463 | 627 body_start = s; |
| 628 body_len = size - (body_start - buf); | |
| 629 | |
| 12213 | 630 if ((s = gaim_strcasestr(header, "Content-Length: ")) != NULL) |
| 10463 | 631 { |
| 632 int tmp_len; | |
| 633 | |
| 634 s += strlen("Content-Length: "); | |
| 635 | |
| 636 if ((c = strchr(s, '\r')) == NULL) | |
| 637 { | |
| 10481 | 638 g_free(header); |
| 10463 | 639 |
| 640 return FALSE; | |
| 641 } | |
| 642 | |
| 643 tmp = g_strndup(s, c - s); | |
| 644 tmp_len = atoi(tmp); | |
| 645 g_free(tmp); | |
| 646 | |
| 647 if (body_len != tmp_len) | |
| 648 { | |
| 10481 | 649 g_free(header); |
| 10463 | 650 |
| 651 #if 0 | |
| 652 gaim_debug_warning("msn", | |
| 653 "body length (%d) != content length (%d)\n", | |
| 654 body_len, tmp_len); | |
| 655 #endif | |
| 656 | |
| 657 return FALSE; | |
| 658 } | |
| 659 } | |
| 660 | |
| 10481 | 661 body = g_malloc0(body_len + 1); |
| 662 memcpy(body, body_start, body_len); | |
| 10463 | 663 |
| 664 #ifdef MSN_DEBUG_HTTP | |
| 10481 | 665 gaim_debug_misc("msn", "Incoming HTTP buffer (header): {%s\r\n}\n", |
| 666 header); | |
| 10463 | 667 #endif |
| 668 | |
| 669 /* Now we should be able to process the data. */ | |
| 12213 | 670 if ((s = gaim_strcasestr(header, "X-MSN-Messenger: ")) != NULL) |
| 10463 | 671 { |
| 672 char *full_session_id, *gw_ip, *session_action; | |
| 673 char *t, *session_id; | |
| 674 char **elems, **cur, **tokens; | |
| 675 | |
| 676 full_session_id = gw_ip = session_action = NULL; | |
| 677 | |
| 678 s += strlen("X-MSN-Messenger: "); | |
| 679 | |
| 680 if ((c = strchr(s, '\r')) == NULL) | |
| 681 { | |
| 10481 | 682 msn_session_set_error(httpconn->session, |
| 683 MSN_ERROR_HTTP_MALFORMED, NULL); | |
| 10463 | 684 gaim_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}", |
| 685 buf); | |
| 686 | |
| 10481 | 687 g_free(body); |
| 10463 | 688 return FALSE; |
| 689 } | |
| 690 | |
| 691 tmp = g_strndup(s, c - s); | |
| 692 | |
| 693 elems = g_strsplit(tmp, "; ", 0); | |
| 694 | |
| 695 for (cur = elems; *cur != NULL; cur++) | |
| 696 { | |
| 697 tokens = g_strsplit(*cur, "=", 2); | |
| 698 | |
| 699 if (strcmp(tokens[0], "SessionID") == 0) | |
| 700 full_session_id = tokens[1]; | |
| 701 else if (strcmp(tokens[0], "GW-IP") == 0) | |
| 702 gw_ip = tokens[1]; | |
| 703 else if (strcmp(tokens[0], "Session") == 0) | |
| 704 session_action = tokens[1]; | |
| 705 | |
| 706 g_free(tokens[0]); | |
| 707 /* Don't free each of the tokens, only the array. */ | |
| 708 g_free(tokens); | |
| 709 } | |
| 710 | |
| 711 g_strfreev(elems); | |
| 712 | |
| 713 g_free(tmp); | |
| 714 | |
| 715 if ((session_action != NULL) && (strcmp(session_action, "close") == 0)) | |
| 716 wasted = TRUE; | |
| 717 | |
| 718 g_free(session_action); | |
| 719 | |
| 720 t = strchr(full_session_id, '.'); | |
| 721 session_id = g_strndup(full_session_id, t - full_session_id); | |
| 722 | |
| 723 if (!wasted) | |
| 724 { | |
| 10504 | 725 if (httpconn->full_session_id != NULL) |
| 10463 | 726 g_free(httpconn->full_session_id); |
| 727 | |
| 728 httpconn->full_session_id = full_session_id; | |
| 729 | |
| 10504 | 730 if (httpconn->session_id != NULL) |
| 10463 | 731 g_free(httpconn->session_id); |
| 732 | |
| 733 httpconn->session_id = session_id; | |
| 734 | |
| 10504 | 735 if (httpconn->host != NULL) |
| 10463 | 736 g_free(httpconn->host); |
| 737 | |
| 738 httpconn->host = gw_ip; | |
| 739 } | |
| 740 else | |
| 741 { | |
| 742 MsnServConn *servconn; | |
| 743 | |
| 744 /* It's going to die. */ | |
| 10504 | 745 /* poor thing */ |
| 10463 | 746 |
| 747 servconn = httpconn->servconn; | |
| 748 | |
| 10533 | 749 /* I'll be honest, I don't fully understand all this, but this |
| 750 * causes crashes, Stu. */ | |
| 751 /* if (servconn != NULL) | |
| 752 servconn->wasted = TRUE; */ | |
| 10463 | 753 |
| 754 g_free(full_session_id); | |
| 10504 | 755 g_free(session_id); |
| 10463 | 756 g_free(gw_ip); |
| 757 } | |
| 758 } | |
| 759 | |
| 10481 | 760 g_free(header); |
| 10463 | 761 |
| 762 *ret_buf = body; | |
| 763 *ret_size = body_len; | |
| 764 | |
|
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
765 if (httpconn->tx_handler > 0) |
|
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12323
diff
changeset
|
766 httpconn_write_cb(httpconn, httpconn->fd, GAIM_INPUT_WRITE); |
| 10463 | 767 |
| 768 return TRUE; | |
| 769 } |
