aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordequis <dx@dxzone.com.ar>2015-03-02 00:43:04 -0300
committerdequis <dx@dxzone.com.ar>2015-04-10 14:10:40 -0300
commitcfeadc32ba56ce1a9bede1077f392c47d30225b8 (patch)
tree734dd2aa2b087c32d78c769e0fd67d9db21c72f9
parentd5503584fb11fbe8b4eec3baba6fb6756c1fc4c0 (diff)
msn: start of the http gateway code
-rw-r--r--protocols/msn/Makefile2
-rw-r--r--protocols/msn/gw.c126
-rw-r--r--protocols/msn/msn.h22
3 files changed, 149 insertions, 1 deletions
diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile
index ce4a3325..7d020942 100644
--- a/protocols/msn/Makefile
+++ b/protocols/msn/Makefile
@@ -12,7 +12,7 @@ _SRCDIR_ := $(_SRCDIR_)protocols/msn/
endif
# [SH] Program variables
-objects = msn.o msn_util.o ns.o soap.o tables.o
+objects = msn.o msn_util.o ns.o soap.o tables.o gw.o
LFLAGS += -r
diff --git a/protocols/msn/gw.c b/protocols/msn/gw.c
new file mode 100644
index 00000000..3d46eeda
--- /dev/null
+++ b/protocols/msn/gw.c
@@ -0,0 +1,126 @@
+#include "bitlbee.h"
+#include "lib/http_client.h"
+#include "msn.h"
+
+#define GATEWAY_HOST "geo.gateway.messenger.live.com"
+#define GATEWAY_PORT 443
+
+#define REQUEST_TEMPLATE \
+ "POST /gateway/gateway.dll?SessionID=%s&%s HTTP/1.1\r\n" \
+ "Host: %s\r\n" \
+ "Content-Length: %zd\r\n" \
+ "\r\n" \
+ "%s"
+
+static gboolean msn_gw_poll_timeout(gpointer data, gint source, b_input_condition cond);
+
+struct msn_gw *msn_gw_new(struct msn_data *md)
+{
+ struct msn_gw *gw = g_new0(struct msn_gw, 1);
+ gw->last_host = g_strdup(GATEWAY_HOST);
+ gw->port = GATEWAY_PORT;
+ gw->ssl = (GATEWAY_PORT == 443);
+ gw->poll_timeout = -1;
+ gw->data = md;
+ gw->in = g_byte_array_new();
+ gw->out = g_byte_array_new();
+ return gw;
+}
+
+void msn_gw_free(struct msn_gw *gw)
+{
+ g_byte_array_free(gw->in, TRUE);
+ g_byte_array_free(gw->out, TRUE);
+ g_free(gw->session_id);
+ g_free(gw->last_host);
+ g_free(gw);
+}
+
+static gboolean msn_gw_parse_session_header(struct msn_gw *gw, char *value)
+{
+ int i;
+ char **subvalues;
+ gboolean closed = FALSE;
+
+ subvalues = g_strsplit(value, "; ", 0);
+
+ for (i = 0; subvalues[i]; i++) {
+ if (strcmp(subvalues[i], "Session=close") == 0) {
+ /* gateway closed, signal the death of the socket */
+ closed = TRUE;
+ } else if (g_str_has_prefix(subvalues[i], "SessionID=")) {
+ /* copy the part after the = to session_id*/
+ g_free(gw->session_id);
+ gw->session_id = g_strdup(subvalues[i] + 10);
+ }
+ }
+
+ g_strfreev(subvalues);
+
+ return !closed;
+}
+
+void msn_gw_callback(struct http_request *req)
+{
+ char *value;
+ struct msn_gw *gw = req->data;
+
+ if ((value = get_rfc822_header(req->reply_headers, "X-MSN-Messenger", 0))) {
+ if (!msn_gw_parse_session_header(gw, value)) {
+ /* XXX handle this */
+ }
+ g_free(value);
+ }
+
+ if ((value = get_rfc822_header(req->reply_headers, "X-MSN-Host", 0))) {
+ g_free(gw->last_host);
+ gw->last_host = value; /* transfer */
+ }
+
+ /* XXX handle reply */
+
+ if (gw->poll_timeout != -1) {
+ b_event_remove(gw->poll_timeout);
+ }
+ gw->poll_timeout = b_timeout_add(5000, msn_gw_poll_timeout, gw);
+
+}
+
+void msn_gw_dorequest(struct msn_gw *gw, char *args)
+{
+ char *request = NULL;
+ char *body = NULL;
+ size_t bodylen = 0;
+
+ if (gw->out) {
+ bodylen = gw->out->len;
+ g_byte_array_append(gw->out, (guint8 *) "", 1); /* nullnullnull */
+ body = (char *) g_byte_array_free(gw->out, FALSE);
+ gw->out = g_byte_array_new();
+ }
+
+ request = g_strdup_printf(REQUEST_TEMPLATE,
+ gw->session_id ? : "", args ? : "", gw->last_host, bodylen, body ? : "");
+
+ http_dorequest(gw->last_host, gw->port, gw->ssl, request, msn_gw_callback, gw);
+ gw->waiting = TRUE;
+
+ g_free(body);
+ g_free(request);
+}
+
+void msn_gw_open(struct msn_gw *gw)
+{
+ msn_gw_dorequest(gw, "Action=open&Server=NS");
+ gw->open = TRUE;
+}
+
+static gboolean msn_gw_poll_timeout(gpointer data, gint source, b_input_condition cond)
+{
+ struct msn_gw *gw = data;
+ gw->poll_timeout = -1;
+ if (!gw->waiting) {
+ msn_gw_dorequest(gw, NULL);
+ }
+ return FALSE;
+}
diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h
index a3894242..2669a736 100644
--- a/protocols/msn/msn.h
+++ b/protocols/msn/msn.h
@@ -123,6 +123,25 @@ typedef enum {
MSN_EMAIL_UNVERIFIED = 16,
} msn_flags_t;
+struct msn_gw {
+ char *last_host;
+ int port;
+ gboolean ssl;
+
+ char *session_id;
+
+ GByteArray *in;
+ GByteArray *out;
+
+ int poll_timeout;
+
+ b_event_handler callback;
+ gpointer data;
+
+ gboolean open;
+ gboolean waiting;
+};
+
struct msn_data {
int fd, inpa;
int rxlen;
@@ -151,6 +170,9 @@ struct msn_data {
it to the MSNP server. */
GTree *domaintree;
int adl_todo;
+
+ gboolean is_http;
+ struct msn_gw *gw;
};
struct msn_away_state {