source: protocols/msn/gw.c @ cfeadc3

Last change on this file since cfeadc3 was cfeadc3, checked in by dequis <dx@…>, at 2015-04-10T17:10:40Z

msn: start of the http gateway code

  • Property mode set to 100644
File size: 2.9 KB
Line 
1#include "bitlbee.h"
2#include "lib/http_client.h"
3#include "msn.h"
4
5#define GATEWAY_HOST "geo.gateway.messenger.live.com"
6#define GATEWAY_PORT 443
7
8#define REQUEST_TEMPLATE \
9        "POST /gateway/gateway.dll?SessionID=%s&%s HTTP/1.1\r\n" \
10        "Host: %s\r\n" \
11        "Content-Length: %zd\r\n" \
12        "\r\n" \
13        "%s"
14
15static gboolean msn_gw_poll_timeout(gpointer data, gint source, b_input_condition cond);
16
17struct msn_gw *msn_gw_new(struct msn_data *md)
18{
19        struct msn_gw *gw = g_new0(struct msn_gw, 1);
20        gw->last_host = g_strdup(GATEWAY_HOST);
21        gw->port = GATEWAY_PORT;
22        gw->ssl = (GATEWAY_PORT == 443);
23        gw->poll_timeout = -1;
24        gw->data = md;
25        gw->in = g_byte_array_new();
26        gw->out = g_byte_array_new();
27        return gw;
28}
29
30void msn_gw_free(struct msn_gw *gw)
31{
32        g_byte_array_free(gw->in, TRUE);
33        g_byte_array_free(gw->out, TRUE);
34        g_free(gw->session_id);
35        g_free(gw->last_host);
36        g_free(gw);
37}
38
39static gboolean msn_gw_parse_session_header(struct msn_gw *gw, char *value)
40{
41        int i;
42        char **subvalues;
43        gboolean closed = FALSE;
44
45        subvalues = g_strsplit(value, "; ", 0);
46
47        for (i = 0; subvalues[i]; i++) {
48                if (strcmp(subvalues[i], "Session=close") == 0) {
49                        /* gateway closed, signal the death of the socket */
50                        closed = TRUE;
51                } else if (g_str_has_prefix(subvalues[i], "SessionID=")) {
52                        /* copy the part after the = to session_id*/
53                        g_free(gw->session_id);
54                        gw->session_id = g_strdup(subvalues[i] + 10);
55                }
56        }
57
58        g_strfreev(subvalues);
59
60        return !closed;
61}
62
63void msn_gw_callback(struct http_request *req)
64{
65        char *value;
66        struct msn_gw *gw = req->data;
67
68        if ((value = get_rfc822_header(req->reply_headers, "X-MSN-Messenger", 0))) {
69                if (!msn_gw_parse_session_header(gw, value)) {
70                        /* XXX handle this */
71                }
72                g_free(value);
73        }
74       
75        if ((value = get_rfc822_header(req->reply_headers, "X-MSN-Host", 0))) {
76                g_free(gw->last_host);
77                gw->last_host = value; /* transfer */
78        }
79
80        /* XXX handle reply */
81
82        if (gw->poll_timeout != -1) {
83                b_event_remove(gw->poll_timeout);
84        }
85        gw->poll_timeout = b_timeout_add(5000, msn_gw_poll_timeout, gw);
86
87}
88
89void msn_gw_dorequest(struct msn_gw *gw, char *args)
90{
91        char *request = NULL;
92        char *body = NULL;
93        size_t bodylen = 0;
94
95        if (gw->out) {
96                bodylen = gw->out->len;
97                g_byte_array_append(gw->out, (guint8 *) "", 1); /* nullnullnull */
98                body = (char *) g_byte_array_free(gw->out, FALSE);
99                gw->out = g_byte_array_new();
100        }
101
102        request = g_strdup_printf(REQUEST_TEMPLATE,
103                gw->session_id ? : "", args ? : "", gw->last_host, bodylen, body ? : "");
104
105        http_dorequest(gw->last_host, gw->port, gw->ssl, request, msn_gw_callback, gw);
106        gw->waiting = TRUE;
107
108        g_free(body);
109        g_free(request);
110}
111
112void msn_gw_open(struct msn_gw *gw)
113{
114        msn_gw_dorequest(gw, "Action=open&Server=NS");
115        gw->open = TRUE;
116}
117
118static gboolean msn_gw_poll_timeout(gpointer data, gint source, b_input_condition cond)
119{
120        struct msn_gw *gw = data;
121        gw->poll_timeout = -1;
122        if (!gw->waiting) {
123                msn_gw_dorequest(gw, NULL);
124        }
125        return FALSE;
126}
Note: See TracBrowser for help on using the repository browser.