aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordequis <dx@dxzone.com.ar>2015-03-14 09:00:58 -0300
committerdequis <dx@dxzone.com.ar>2015-04-10 14:10:41 -0300
commit913a663a3e383c40c644a7d0a8c8aba9d417167c (patch)
treebb1199c444c20caf25c04e4f6b982c42536c2dc0
parenta4be2f6df564eea09612731be194278e4fb755e0 (diff)
msn: implement the rest of the http gateway support, enable by default
-rw-r--r--protocols/msn/gw.c57
-rw-r--r--protocols/msn/msn.c7
-rw-r--r--protocols/msn/msn.h7
-rw-r--r--protocols/msn/msn_util.c4
-rw-r--r--protocols/msn/ns.c51
5 files changed, 106 insertions, 20 deletions
diff --git a/protocols/msn/gw.c b/protocols/msn/gw.c
index 3d46eeda..e046f0c8 100644
--- a/protocols/msn/gw.c
+++ b/protocols/msn/gw.c
@@ -29,6 +29,9 @@ struct msn_gw *msn_gw_new(struct msn_data *md)
void msn_gw_free(struct msn_gw *gw)
{
+ if (gw->poll_timeout != -1) {
+ b_event_remove(gw->poll_timeout);
+ }
g_byte_array_free(gw->in, TRUE);
g_byte_array_free(gw->out, TRUE);
g_free(gw->session_id);
@@ -65,9 +68,30 @@ void msn_gw_callback(struct http_request *req)
char *value;
struct msn_gw *gw = req->data;
+ gw->waiting = FALSE;
+
+ if (!gw->open) {
+ /* the user tried to logout while the request was pending
+ * see msn_ns_close() */
+ msn_gw_free(gw);
+ return;
+ }
+
+ if (getenv("BITLBEE_DEBUG")) {
+ fprintf(stderr, "\n\x1b[90mHTTP:%s\n", req->reply_body);
+ fprintf(stderr, "\n\x1b[97m\n");
+ }
+
+ if (req->status_code != 200) {
+ gw->callback(gw->data, -1, B_EV_IO_READ);
+ return;
+ }
+
if ((value = get_rfc822_header(req->reply_headers, "X-MSN-Messenger", 0))) {
if (!msn_gw_parse_session_header(gw, value)) {
- /* XXX handle this */
+ gw->callback(gw->data, -1, B_EV_IO_READ);
+ g_free(value);
+ return;
}
g_free(value);
}
@@ -77,7 +101,10 @@ void msn_gw_callback(struct http_request *req)
gw->last_host = value; /* transfer */
}
- /* XXX handle reply */
+ if (req->body_size) {
+ g_byte_array_append(gw->in, (const guint8 *) req->reply_body, req->body_size);
+ gw->callback(gw->data, -1, B_EV_IO_READ);
+ }
if (gw->poll_timeout != -1) {
b_event_remove(gw->poll_timeout);
@@ -103,6 +130,7 @@ void msn_gw_dorequest(struct msn_gw *gw, char *args)
gw->session_id ? : "", args ? : "", gw->last_host, bodylen, body ? : "");
http_dorequest(gw->last_host, gw->port, gw->ssl, request, msn_gw_callback, gw);
+ gw->open = TRUE;
gw->waiting = TRUE;
g_free(body);
@@ -112,7 +140,6 @@ void msn_gw_dorequest(struct msn_gw *gw, char *args)
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)
@@ -124,3 +151,27 @@ static gboolean msn_gw_poll_timeout(gpointer data, gint source, b_input_conditio
}
return FALSE;
}
+
+ssize_t msn_gw_read(struct msn_gw *gw, char **buf)
+{
+ size_t bodylen;
+ if (!gw->open) {
+ return 0;
+ }
+
+ bodylen = gw->in->len;
+ g_byte_array_append(gw->in, (guint8 *) "", 1); /* nullnullnull */
+ *buf = (char *) g_byte_array_free(gw->in, FALSE);
+ gw->in = g_byte_array_new();
+ return bodylen;
+}
+
+void msn_gw_write(struct msn_gw *gw, char *buf, size_t len)
+{
+ g_byte_array_append(gw->out, (const guint8 *) buf, len);
+ if (!gw->open) {
+ msn_gw_open(gw);
+ } else if (!gw->waiting) {
+ msn_gw_dorequest(gw, NULL);
+ }
+}
diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c
index 4bc985ad..f6d85a4f 100644
--- a/protocols/msn/msn.c
+++ b/protocols/msn/msn.c
@@ -61,11 +61,7 @@ static void msn_login(account_t *acc)
ic->flags |= OPT_PONGS | OPT_PONGED;
if (!server) {
- imcb_error(ic, "The msn protocol is disabled in this version because most servers disabled MSNP18 over port 1863.");
- imcb_error(ic, "If you find a working server, you can change the 'server' setting of this account. Good luck!");
- imcb_error(ic, "See also: http://ismsndeadyet.com/"); // shameless plug
- imc_logout(ic, FALSE);
- return;
+ server = "geo.gateway.messenger.live.com";
}
if (strchr(acc->user, '@') == NULL) {
@@ -78,6 +74,7 @@ static void msn_login(account_t *acc)
md->away_state = msn_away_state_list;
md->domaintree = g_tree_new(msn_domaintree_cmp);
md->fd = -1;
+ md->is_http = TRUE;
msn_connections = g_slist_prepend(msn_connections, ic);
diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h
index 7b1e0d26..cdc459f5 100644
--- a/protocols/msn/msn.h
+++ b/protocols/msn/msn.h
@@ -262,4 +262,11 @@ const struct msn_away_state *msn_away_state_by_code(char *code);
const struct msn_away_state *msn_away_state_by_name(char *name);
const struct msn_status_code *msn_status_by_number(int number);
+/* gw.c */
+struct msn_gw *msn_gw_new(struct msn_data *md);
+void msn_gw_free(struct msn_gw *gw);
+void msn_gw_open(struct msn_gw *gw);
+ssize_t msn_gw_read(struct msn_gw *gw, char **buf);
+void msn_gw_write(struct msn_gw *gw, char *buf, size_t len);
+
#endif //_MSN_H
diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c
index 931641ce..58bc0eae 100644
--- a/protocols/msn/msn_util.c
+++ b/protocols/msn/msn_util.c
@@ -173,7 +173,7 @@ void msn_buddy_ask(bee_user_t *bu)
void msn_queue_feed(struct msn_data *h, char *bytes, int st)
{
- h->rxq = g_renew(char, h->rxq, h->rxlen + 1024);
+ h->rxq = g_renew(char, h->rxq, h->rxlen + st);
memcpy(h->rxq + h->rxlen, bytes, st);
h->rxlen += st;
@@ -234,7 +234,7 @@ int msn_handler(struct msn_data *h)
/* If we reached the end of the buffer, there's still an incomplete command there.
Return and wait for more data. */
- if (i == h->rxlen && h->rxq[i - 1] != '\r' && h->rxq[i - 1] != '\n') {
+ if (i && i == h->rxlen && h->rxq[i - 1] != '\r' && h->rxq[i - 1] != '\n') {
break;
}
} else {
diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c
index 3976bfd0..4d98982a 100644
--- a/protocols/msn/ns.c
+++ b/protocols/msn/ns.c
@@ -59,7 +59,14 @@ int msn_ns_write(struct im_connection *ic, int fd, const char *fmt, ...)
}
len = strlen(out);
- st = write(fd, out, len);
+
+ if (md->is_http) {
+ st = len;
+ msn_gw_write(md->gw, out, len);
+ } else {
+ st = write(fd, out, len);
+ }
+
g_free(out);
if (st != len) {
imcb_error(ic, "Short write() to main server");
@@ -78,11 +85,17 @@ gboolean msn_ns_connect(struct im_connection *ic, const char *host, int port)
closesocket(handler->fd);
}
- handler->fd = proxy_connect(host, port, msn_ns_connected, handler);
- if (handler->fd < 0) {
- imcb_error(ic, "Could not connect to server");
- imc_logout(ic, TRUE);
- return FALSE;
+ if (handler->is_http) {
+ handler->gw = msn_gw_new(handler);
+ handler->gw->callback = msn_ns_callback;
+ msn_ns_connected(handler, -1, B_EV_IO_READ);
+ } else {
+ handler->fd = proxy_connect(host, port, msn_ns_connected, handler);
+ if (handler->fd < 0) {
+ imcb_error(ic, "Could not connect to server");
+ imc_logout(ic, TRUE);
+ return FALSE;
+ }
}
return TRUE;
@@ -94,7 +107,7 @@ static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition c
struct msn_data *handler = md;
struct im_connection *ic = md->ic;
- if (source == -1) {
+ if (source == -1 && !md->is_http) {
imcb_error(ic, "Could not connect to server");
imc_logout(ic, TRUE);
return FALSE;
@@ -120,7 +133,9 @@ static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition c
}
if (msn_ns_write(ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER)) {
- handler->inpa = b_input_add(handler->fd, B_EV_IO_READ, msn_ns_callback, handler);
+ if (!handler->is_http) {
+ handler->inpa = b_input_add(handler->fd, B_EV_IO_READ, msn_ns_callback, handler);
+ }
imcb_log(ic, "Connected to server, waiting for reply");
}
@@ -129,6 +144,14 @@ static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition c
void msn_ns_close(struct msn_data *handler)
{
+ if (handler->gw) {
+ if (handler->gw->waiting) {
+ /* mark it as closed, let the request callback clean it */
+ handler->gw->open = FALSE;
+ } else {
+ msn_gw_free(handler->gw);
+ }
+ }
if (handler->fd >= 0) {
closesocket(handler->fd);
b_event_remove(handler->inpa);
@@ -147,10 +170,16 @@ static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition co
{
struct msn_data *handler = data;
struct im_connection *ic = handler->ic;
- char bytes[1024];
+ char *bytes;
int st;
- st = read(handler->fd, bytes, 1024);
+ if (handler->is_http) {
+ st = msn_gw_read(handler->gw, &bytes);
+ } else {
+ bytes = g_malloc(1024);
+ st = read(handler->fd, bytes, 1024);
+ }
+
if (st <= 0) {
imcb_error(ic, "Error while reading from server");
imc_logout(ic, TRUE);
@@ -159,6 +188,8 @@ static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition co
msn_queue_feed(handler, bytes, st);
+ g_free(bytes);
+
/* Ignore ret == 0, it's already disconnected then. */
msn_handler(handler);