comparison src/protocols/msn/httpmethod.c @ 7288:ff9127038a5a

[gaim-migrate @ 7869] It doesn't completely work yet, but this is the beginnings of the MSN HTTP port 80 connect method. I don't have it set so it can be enabled, so it's harmless to commit this now, but I want a second set of eyes, and I also want to do other MSN work without dealing with hand-merging patches. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Fri, 17 Oct 2003 14:57:59 +0000
parents
children 414c701ef1ff
comparison
equal deleted inserted replaced
7287:3a41c3f80228 7288:ff9127038a5a
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
56 msn_http_servconn_poll(servconn);
57
58 servconn->http_data->timer = 0;
59
60 return FALSE;
61 }
62
63 static void
64 stop_timer(MsnServConn *servconn)
65 {
66 if (servconn->http_data->timer)
67 {
68 g_source_remove(servconn->http_data->timer);
69 servconn->http_data->timer = 0;
70 }
71 }
72
73 static void
74 start_timer(MsnServConn *servconn)
75 {
76 stop_timer(servconn);
77
78 servconn->http_data->timer = g_timeout_add(5000, http_poll, servconn);
79 }
80
81 size_t
82 msn_http_servconn_write(MsnServConn *servconn, const char *buf, size_t size,
83 const char *server_type)
84 {
85 size_t s;
86 char *params;
87 char *temp;
88 gboolean first;
89
90 g_return_val_if_fail(servconn != NULL, 0);
91 g_return_val_if_fail(buf != NULL, 0);
92 g_return_val_if_fail(size > 0, 0);
93 g_return_val_if_fail(servconn->http_data != NULL, 0);
94
95 if (servconn->http_data->waiting_response ||
96 servconn->http_data->queue != NULL)
97 {
98 MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1);
99
100 queue_data->servconn = servconn;
101 queue_data->buffer = g_strdup(buf);
102 queue_data->size = size;
103 queue_data->server_type = server_type;
104
105 servconn->http_data->queue =
106 g_list_append(servconn->http_data->queue, queue_data);
107
108 return size;
109 }
110
111 first = servconn->http_data->virgin;
112
113 if (first)
114 {
115 if (server_type)
116 {
117 params = g_strdup_printf("Action=open&Server=%s&IP=%s",
118 server_type,
119 servconn->http_data->gateway_ip);
120 }
121 else
122 {
123 params = g_strdup_printf("Action=open&IP=%s",
124 servconn->http_data->gateway_ip);
125 }
126 }
127 else
128 {
129 params = g_strdup_printf("SessionID=%s",
130 servconn->http_data->session_id);
131 }
132
133 temp = g_strdup_printf(
134 "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n"
135 "Accept: */*\r\n"
136 "Accept-Language: en-us\r\n"
137 "User-Agent: MSMSGS\r\n"
138 "Host: %s\r\n"
139 "Proxy-Connection: Keep-Alive\r\n"
140 "Connection: Keep-Alive\r\n"
141 "Pragma: no-cache\r\n"
142 "Content-Type: application/x-msn-messenger\r\n"
143 "Content-Length: %d\r\n"
144 "\r\n"
145 "%s",
146 servconn->http_data->gateway_ip,
147 params,
148 servconn->http_data->gateway_ip,
149 size,
150 buf);
151
152 g_free(params);
153
154 #if 0
155 gaim_debug_misc("msn", "Writing to HTTP: {%s}\n", temp);
156 #endif
157
158 s = write(servconn->fd, temp, strlen(temp));
159
160 g_free(temp);
161
162 servconn->http_data->waiting_response = TRUE;
163
164 servconn->http_data->virgin = FALSE;
165
166 stop_timer(servconn);
167
168 return s;
169 }
170
171 void
172 msn_http_servconn_poll(MsnServConn *servconn)
173 {
174 size_t s;
175 char *temp;
176
177 g_return_if_fail(servconn != NULL);
178 g_return_if_fail(servconn->http_data != NULL);
179
180 if (servconn->http_data->waiting_response ||
181 servconn->http_data->queue != NULL)
182 {
183 return;
184 }
185
186 temp = g_strdup_printf(
187 "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n"
188 "Accept: */*\r\n"
189 "Accept-Language: en-us\r\n"
190 "User-Agent: MSMSGS\r\n"
191 "Host: %s\r\n"
192 "Proxy-Connection: Keep-Alive\r\n"
193 "Connection: Keep-Alive\r\n"
194 "Pragma: no-cache\r\n"
195 "Content-Type: application/x-msn-messenger\r\n"
196 "Content-Length: 0\r\n"
197 "\r\n",
198 servconn->http_data->gateway_ip,
199 servconn->http_data->session_id,
200 servconn->http_data->gateway_ip);
201
202 #if 0
203 gaim_debug_misc("msn", "Writing to HTTP: {%s}\n", temp);
204 #endif
205
206 s = write(servconn->fd, temp, strlen(temp));
207
208 g_free(temp);
209
210 servconn->http_data->waiting_response = TRUE;
211
212 stop_timer(servconn);
213
214 if (s <= 0)
215 gaim_connection_error(servconn->session->account->gc,
216 _("Write error"));
217 }
218
219 gboolean
220 msn_http_servconn_parse_data(MsnServConn *servconn, const char *buf,
221 size_t size, char **ret_buf, size_t *ret_size,
222 gboolean *error)
223 {
224 GaimConnection *gc;
225 const char *s, *c;
226 char *headers, *body;
227 char *tmp;
228 size_t len = 0;
229
230 g_return_val_if_fail(servconn != NULL, FALSE);
231 g_return_val_if_fail(buf != NULL, FALSE);
232 g_return_val_if_fail(size > 0, FALSE);
233 g_return_val_if_fail(ret_buf != NULL, FALSE);
234 g_return_val_if_fail(ret_size != NULL, FALSE);
235 g_return_val_if_fail(error != NULL, FALSE);
236
237 servconn->http_data->waiting_response = FALSE;
238
239 gc = gaim_account_get_connection(servconn->session->account);
240
241 /* Healthy defaults. */
242 *ret_buf = NULL;
243 *ret_size = 0;
244 *error = FALSE;
245
246 /* First, some tests to see if we have a full block of stuff. */
247
248 if (strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0 &&
249 strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)
250 {
251 *error = TRUE;
252
253 return FALSE;
254 }
255
256 if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0)
257 {
258 if ((s = strstr(buf, "\r\n\r\n")) == NULL)
259 return FALSE;
260
261 s += 4;
262
263 if (*s == '\0')
264 {
265 *ret_buf = g_strdup("");
266 *ret_size = 0;
267
268 return TRUE;
269 }
270
271 buf = s;
272 size -= (s - buf);
273 }
274
275 if ((s = strstr(buf, "\r\n\r\n")) == NULL)
276 return FALSE;
277
278 headers = g_strndup(buf, s - buf);
279 s += 4; /* Skip \r\n */
280 body = g_strndup(s, size - (s - buf));
281
282 #if 0
283 gaim_debug_misc("msn", "Incoming HTTP buffer: {%s\r\n%s}", headers, body);
284 #endif
285
286 if ((s = strstr(headers, "Content-Length: ")) != NULL)
287 {
288 s += strlen("Content-Length: ");
289
290 if ((c = strchr(s, '\r')) == NULL)
291 {
292 g_free(headers);
293 g_free(body);
294
295 return FALSE;
296 }
297
298 tmp = g_strndup(s, c - s);
299 len = atoi(tmp);
300 g_free(tmp);
301
302 if (strlen(body) != len)
303 {
304 g_free(headers);
305 g_free(body);
306
307 gaim_debug_warning("msn",
308 "body length (%d) != content length (%d)\n",
309 strlen(body), len);
310 return FALSE;
311 }
312 }
313
314 /* Now we should be able to process the data. */
315 if ((s = strstr(headers, "X-MSN-Messenger: ")) != NULL)
316 {
317 char *session_id, *gw_ip;
318 char *c2, *s2;
319
320 s += strlen("X-MSN-Messenger: ");
321
322 if ((c = strchr(s, '\r')) == NULL)
323 {
324 gaim_connection_error(gc, "Malformed X-MSN-Messenger field.");
325 return FALSE;
326 }
327
328 tmp = g_strndup(s, c - s);
329
330 /* Find the value for the Session ID */
331 if ((s2 = strchr(tmp, '=')) == NULL)
332 {
333 gaim_connection_error(gc, "Malformed X-MSN-Messenger field.");
334 return FALSE;
335 }
336
337 s2++;
338
339 /* Terminate the ; so we can g_strdup it. */
340 if ((c2 = strchr(s2, ';')) == NULL)
341 {
342 gaim_connection_error(gc, "Malformed X-MSN-Messenger field.");
343 return FALSE;
344 }
345
346 *c2 = '\0';
347 c2++;
348
349 /* Now grab that session ID. */
350 session_id = g_strdup(s2);
351
352 /* Continue to the gateway IP */
353 if ((s2 = strchr(c2, '=')) == NULL)
354 {
355 gaim_connection_error(gc, "Malformed X-MSN-Messenger field.");
356 return FALSE;
357 }
358
359 s2++;
360
361 /* Grab the gateway IP */
362 gw_ip = g_strdup(s2);
363
364 g_free(tmp);
365
366 /* Set the new data. */
367 if (servconn->http_data->session_id != NULL)
368 g_free(servconn->http_data->session_id);
369
370 if (servconn->http_data->old_gateway_ip != NULL)
371 g_free(servconn->http_data->old_gateway_ip);
372
373 servconn->http_data->old_gateway_ip = servconn->http_data->gateway_ip;
374
375 servconn->http_data->session_id = session_id;
376 servconn->http_data->gateway_ip = gw_ip;
377 }
378
379 g_free(headers);
380
381 *ret_buf = body;
382 *ret_size = len;
383
384 if (servconn->http_data->queue != NULL)
385 {
386 MsnHttpQueueData *queue_data;
387
388 queue_data = (MsnHttpQueueData *)servconn->http_data->queue->data;
389
390 servconn->http_data->queue =
391 g_list_remove(servconn->http_data->queue, queue_data);
392
393 msn_http_servconn_write(queue_data->servconn,
394 queue_data->buffer,
395 queue_data->size,
396 queue_data->server_type);
397
398 g_free(queue_data->buffer);
399 g_free(queue_data);
400 }
401 else
402 start_timer(servconn);
403
404 return TRUE;
405 }
406