Mercurial > pidgin
annotate src/protocols/msn/httpmethod.c @ 8273:f24172f53650
[gaim-migrate @ 8997]
This is Scott Lamb's eventloop abstraction patch. If it breaks things,
Scott Lamb will be glad to take the punishment. If it doesn't, it should
make integration into other event loops easier. Well, no, not easier,
harder actually, but it'll be done more appropriately and less hackily..
er, hacky. Is hackily a word?
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Tue, 17 Feb 2004 02:17:48 +0000 |
parents | aa44049e8891 |
children | ef881489396e |
rev | line source |
---|---|
7288 | 1 /** |
2 * @file httpmethod.c HTTP connection method | |
3 * | |
4 * gaim | |
5 * | |
6 * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org> | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 */ | |
22 #include "debug.h" | |
23 #include "httpmethod.h" | |
24 | |
25 #define GET_NEXT(tmp) \ | |
26 while (*(tmp) && *(tmp) != ' ' && *(tmp) != '\r') \ | |
27 (tmp)++; \ | |
28 if (*(tmp) != '\0') *(tmp)++ = '\0'; \ | |
29 if (*(tmp) == '\n') (tmp)++; \ | |
30 while (*(tmp) && *(tmp) == ' ') \ | |
31 (tmp)++ | |
32 | |
33 #define GET_NEXT_LINE(tmp) \ | |
34 while (*(tmp) && *(tmp) != '\r') \ | |
35 (tmp)++; \ | |
36 if (*(tmp) != '\0') *(tmp)++ = '\0'; \ | |
37 if (*(tmp) == '\n') (tmp)++ | |
38 | |
39 typedef struct | |
40 { | |
41 MsnServConn *servconn; | |
42 char *buffer; | |
43 size_t size; | |
44 const char *server_type; | |
45 | |
46 } MsnHttpQueueData; | |
47 | |
48 static gboolean | |
49 http_poll(gpointer data) | |
50 { | |
51 MsnServConn *servconn = data; | |
52 | |
53 gaim_debug_info("msn", "Polling server %s.\n", | |
54 servconn->http_data->gateway_ip); | |
55 msn_http_servconn_poll(servconn); | |
56 | |
57 servconn->http_data->timer = 0; | |
58 | |
8207
aa44049e8891
[gaim-migrate @ 8930]
Christian Hammond <chipx86@chipx86.com>
parents:
7834
diff
changeset
|
59 gaim_debug(GAIM_DEBUG_INFO, "msn", "Returning from http_poll\n"); |
aa44049e8891
[gaim-migrate @ 8930]
Christian Hammond <chipx86@chipx86.com>
parents:
7834
diff
changeset
|
60 |
7288 | 61 return FALSE; |
62 } | |
63 | |
64 static void | |
65 stop_timer(MsnServConn *servconn) | |
66 { | |
67 if (servconn->http_data->timer) | |
68 { | |
8207
aa44049e8891
[gaim-migrate @ 8930]
Christian Hammond <chipx86@chipx86.com>
parents:
7834
diff
changeset
|
69 gaim_debug(GAIM_DEBUG_INFO, "msn", "Stopping timer\n"); |
7288 | 70 g_source_remove(servconn->http_data->timer); |
71 servconn->http_data->timer = 0; | |
72 } | |
73 } | |
74 | |
75 static void | |
76 start_timer(MsnServConn *servconn) | |
77 { | |
78 stop_timer(servconn); | |
79 | |
8207
aa44049e8891
[gaim-migrate @ 8930]
Christian Hammond <chipx86@chipx86.com>
parents:
7834
diff
changeset
|
80 gaim_debug(GAIM_DEBUG_INFO, "msn", "Starting timer\n"); |
8273
f24172f53650
[gaim-migrate @ 8997]
Christian Hammond <chipx86@chipx86.com>
parents:
8207
diff
changeset
|
81 servconn->http_data->timer = gaim_timeout_add(5000, http_poll, servconn); |
7288 | 82 } |
83 | |
84 size_t | |
85 msn_http_servconn_write(MsnServConn *servconn, const char *buf, size_t size, | |
86 const char *server_type) | |
87 { | |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
88 size_t s, needed; |
7288 | 89 char *params; |
90 char *temp; | |
91 gboolean first; | |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
92 int res; /* result of the write operation */ |
7288 | 93 |
94 g_return_val_if_fail(servconn != NULL, 0); | |
95 g_return_val_if_fail(buf != NULL, 0); | |
96 g_return_val_if_fail(size > 0, 0); | |
97 g_return_val_if_fail(servconn->http_data != NULL, 0); | |
98 | |
99 if (servconn->http_data->waiting_response || | |
100 servconn->http_data->queue != NULL) | |
101 { | |
102 MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1); | |
103 | |
104 queue_data->servconn = servconn; | |
105 queue_data->buffer = g_strdup(buf); | |
106 queue_data->size = size; | |
107 queue_data->server_type = server_type; | |
108 | |
109 servconn->http_data->queue = | |
110 g_list_append(servconn->http_data->queue, queue_data); | |
111 | |
112 return size; | |
113 } | |
114 | |
115 first = servconn->http_data->virgin; | |
116 | |
117 if (first) | |
118 { | |
119 if (server_type) | |
120 { | |
121 params = g_strdup_printf("Action=open&Server=%s&IP=%s", | |
122 server_type, | |
123 servconn->http_data->gateway_ip); | |
124 } | |
125 else | |
126 { | |
127 params = g_strdup_printf("Action=open&IP=%s", | |
128 servconn->http_data->gateway_ip); | |
129 } | |
130 } | |
131 else | |
132 { | |
133 params = g_strdup_printf("SessionID=%s", | |
134 servconn->http_data->session_id); | |
135 } | |
136 | |
137 temp = g_strdup_printf( | |
138 "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n" | |
139 "Accept: */*\r\n" | |
140 "Accept-Language: en-us\r\n" | |
141 "User-Agent: MSMSGS\r\n" | |
142 "Host: %s\r\n" | |
143 "Proxy-Connection: Keep-Alive\r\n" | |
144 "Connection: Keep-Alive\r\n" | |
145 "Pragma: no-cache\r\n" | |
146 "Content-Type: application/x-msn-messenger\r\n" | |
147 "Content-Length: %d\r\n" | |
148 "\r\n" | |
149 "%s", | |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
150 ((strcmp(server_type, "SB") == 0) && first |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
151 ? "gateway.messenger.hotmail.com" |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
152 : servconn->http_data->gateway_ip), |
7288 | 153 params, |
154 servconn->http_data->gateway_ip, | |
7386 | 155 (int)size, |
7288 | 156 buf); |
157 | |
158 g_free(params); | |
159 | |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
160 #if 1 |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
161 gaim_debug_misc("msn", "Writing HTTP to fd %d: {%s}\n", |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
162 servconn->fd, temp); |
7288 | 163 #endif |
164 | |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
165 s = 0; |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
166 needed = strlen(temp); |
8207
aa44049e8891
[gaim-migrate @ 8930]
Christian Hammond <chipx86@chipx86.com>
parents:
7834
diff
changeset
|
167 |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
168 do { |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
169 res = write(servconn->fd, temp, needed); |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
170 if (res >= 0) |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
171 s += res; |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
172 else if (errno != EAGAIN) { |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
173 char *msg = g_strdup_printf("Unable to write to MSN server via HTTP (error %d)", errno); |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
174 gaim_connection_error(servconn->session->account->gc, msg); |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
175 g_free(msg); |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
176 return -1; |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
177 } |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
178 } while (s < needed); |
8207
aa44049e8891
[gaim-migrate @ 8930]
Christian Hammond <chipx86@chipx86.com>
parents:
7834
diff
changeset
|
179 |
7288 | 180 g_free(temp); |
181 | |
182 servconn->http_data->waiting_response = TRUE; | |
183 | |
184 servconn->http_data->virgin = FALSE; | |
185 | |
186 stop_timer(servconn); | |
187 | |
188 return s; | |
189 } | |
190 | |
191 void | |
192 msn_http_servconn_poll(MsnServConn *servconn) | |
193 { | |
194 size_t s; | |
195 char *temp; | |
196 | |
197 g_return_if_fail(servconn != NULL); | |
198 g_return_if_fail(servconn->http_data != NULL); | |
199 | |
200 if (servconn->http_data->waiting_response || | |
201 servconn->http_data->queue != NULL) | |
202 { | |
203 return; | |
204 } | |
205 | |
206 temp = g_strdup_printf( | |
207 "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n" | |
208 "Accept: */*\r\n" | |
209 "Accept-Language: en-us\r\n" | |
210 "User-Agent: MSMSGS\r\n" | |
211 "Host: %s\r\n" | |
212 "Proxy-Connection: Keep-Alive\r\n" | |
213 "Connection: Keep-Alive\r\n" | |
214 "Pragma: no-cache\r\n" | |
215 "Content-Type: application/x-msn-messenger\r\n" | |
216 "Content-Length: 0\r\n" | |
217 "\r\n", | |
218 servconn->http_data->gateway_ip, | |
219 servconn->http_data->session_id, | |
220 servconn->http_data->gateway_ip); | |
221 | |
222 gaim_debug_misc("msn", "Writing to HTTP: {%s}\n", temp); | |
223 | |
224 s = write(servconn->fd, temp, strlen(temp)); | |
225 | |
226 g_free(temp); | |
227 | |
228 servconn->http_data->waiting_response = TRUE; | |
229 | |
230 stop_timer(servconn); | |
231 | |
232 if (s <= 0) | |
233 gaim_connection_error(servconn->session->account->gc, | |
234 _("Write error")); | |
235 } | |
236 | |
237 gboolean | |
238 msn_http_servconn_parse_data(MsnServConn *servconn, const char *buf, | |
239 size_t size, char **ret_buf, size_t *ret_size, | |
240 gboolean *error) | |
241 { | |
242 GaimConnection *gc; | |
243 const char *s, *c; | |
244 char *headers, *body; | |
245 char *tmp; | |
246 size_t len = 0; | |
247 | |
248 g_return_val_if_fail(servconn != NULL, FALSE); | |
249 g_return_val_if_fail(buf != NULL, FALSE); | |
250 g_return_val_if_fail(size > 0, FALSE); | |
251 g_return_val_if_fail(ret_buf != NULL, FALSE); | |
252 g_return_val_if_fail(ret_size != NULL, FALSE); | |
253 g_return_val_if_fail(error != NULL, FALSE); | |
254 | |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
255 gaim_debug_info("msn", "parsing data {%s} from fd %d\n", buf, servconn->fd); |
7288 | 256 servconn->http_data->waiting_response = FALSE; |
257 | |
258 gc = gaim_account_get_connection(servconn->session->account); | |
259 | |
260 /* Healthy defaults. */ | |
261 *ret_buf = NULL; | |
262 *ret_size = 0; | |
263 *error = FALSE; | |
264 | |
265 /* First, some tests to see if we have a full block of stuff. */ | |
7834
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
266 if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) && |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
267 (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) && |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
268 ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) && |
99ffabc6ce73
[gaim-migrate @ 8487]
Christian Hammond <chipx86@chipx86.com>
parents:
7386
diff
changeset
|
269 (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0))) |
7288 | 270 { |
271 *error = TRUE; | |
272 return FALSE; | |
273 } | |
274 | |
275 if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0) | |
276 { | |
277 if ((s = strstr(buf, "\r\n\r\n")) == NULL) | |
278 return FALSE; | |
279 | |
280 s += 4; | |
281 | |
282 if (*s == '\0') | |
283 { | |
284 *ret_buf = g_strdup(""); | |
285 *ret_size = 0; | |
286 | |
287 return TRUE; | |
288 } | |
289 | |
290 buf = s; | |
291 size -= (s - buf); | |
292 } | |
293 | |
294 if ((s = strstr(buf, "\r\n\r\n")) == NULL) | |
295 return FALSE; | |
296 | |
297 headers = g_strndup(buf, s - buf); | |
298 s += 4; /* Skip \r\n */ | |
299 body = g_strndup(s, size - (s - buf)); | |
300 | |
301 gaim_debug_misc("msn", "Incoming HTTP buffer: {%s\r\n%s}", headers, body); | |
302 | |
303 if ((s = strstr(headers, "Content-Length: ")) != NULL) | |
304 { | |
305 s += strlen("Content-Length: "); | |
306 | |
307 if ((c = strchr(s, '\r')) == NULL) | |
308 { | |
309 g_free(headers); | |
310 g_free(body); | |
311 | |
312 return FALSE; | |
313 } | |
314 | |
315 tmp = g_strndup(s, c - s); | |
316 len = atoi(tmp); | |
317 g_free(tmp); | |
318 | |
319 if (strlen(body) != len) | |
320 { | |
321 g_free(headers); | |
322 g_free(body); | |
323 | |
324 gaim_debug_warning("msn", | |
325 "body length (%d) != content length (%d)\n", | |
326 strlen(body), len); | |
327 return FALSE; | |
328 } | |
329 } | |
330 | |
331 /* Now we should be able to process the data. */ | |
332 if ((s = strstr(headers, "X-MSN-Messenger: ")) != NULL) | |
333 { | |
334 char *session_id, *gw_ip; | |
335 char *c2, *s2; | |
336 | |
337 s += strlen("X-MSN-Messenger: "); | |
338 | |
339 if ((c = strchr(s, '\r')) == NULL) | |
340 { | |
341 gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); | |
342 return FALSE; | |
343 } | |
344 | |
345 tmp = g_strndup(s, c - s); | |
346 | |
347 /* Find the value for the Session ID */ | |
348 if ((s2 = strchr(tmp, '=')) == NULL) | |
349 { | |
350 gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); | |
351 return FALSE; | |
352 } | |
353 | |
354 s2++; | |
355 | |
356 /* Terminate the ; so we can g_strdup it. */ | |
357 if ((c2 = strchr(s2, ';')) == NULL) | |
358 { | |
359 gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); | |
360 return FALSE; | |
361 } | |
362 | |
363 *c2 = '\0'; | |
364 c2++; | |
365 | |
366 /* Now grab that session ID. */ | |
367 session_id = g_strdup(s2); | |
368 | |
369 /* Continue to the gateway IP */ | |
370 if ((s2 = strchr(c2, '=')) == NULL) | |
371 { | |
372 gaim_connection_error(gc, "Malformed X-MSN-Messenger field."); | |
373 return FALSE; | |
374 } | |
375 | |
376 s2++; | |
377 | |
378 /* Grab the gateway IP */ | |
379 gw_ip = g_strdup(s2); | |
380 | |
381 g_free(tmp); | |
382 | |
383 /* Set the new data. */ | |
384 if (servconn->http_data->session_id != NULL) | |
385 g_free(servconn->http_data->session_id); | |
386 | |
387 if (servconn->http_data->old_gateway_ip != NULL) | |
388 g_free(servconn->http_data->old_gateway_ip); | |
389 | |
390 servconn->http_data->old_gateway_ip = servconn->http_data->gateway_ip; | |
391 | |
392 servconn->http_data->session_id = session_id; | |
393 servconn->http_data->gateway_ip = gw_ip; | |
394 } | |
395 | |
396 g_free(headers); | |
397 | |
398 *ret_buf = body; | |
399 *ret_size = len; | |
400 | |
401 if (servconn->http_data->queue != NULL) | |
402 { | |
403 MsnHttpQueueData *queue_data; | |
404 | |
405 queue_data = (MsnHttpQueueData *)servconn->http_data->queue->data; | |
406 | |
407 servconn->http_data->queue = | |
408 g_list_remove(servconn->http_data->queue, queue_data); | |
409 | |
410 msn_http_servconn_write(queue_data->servconn, | |
411 queue_data->buffer, | |
412 queue_data->size, | |
413 queue_data->server_type); | |
414 | |
415 g_free(queue_data->buffer); | |
416 g_free(queue_data); | |
417 } | |
418 else | |
419 start_timer(servconn); | |
420 | |
421 return TRUE; | |
422 } | |
423 |