diff options
author | dequis <dx@dxzone.com.ar> | 2015-03-14 09:00:58 -0300 |
---|---|---|
committer | dequis <dx@dxzone.com.ar> | 2015-04-10 14:10:41 -0300 |
commit | 913a663a3e383c40c644a7d0a8c8aba9d417167c (patch) | |
tree | bb1199c444c20caf25c04e4f6b982c42536c2dc0 | |
parent | a4be2f6df564eea09612731be194278e4fb755e0 (diff) |
msn: implement the rest of the http gateway support, enable by default
-rw-r--r-- | protocols/msn/gw.c | 57 | ||||
-rw-r--r-- | protocols/msn/msn.c | 7 | ||||
-rw-r--r-- | protocols/msn/msn.h | 7 | ||||
-rw-r--r-- | protocols/msn/msn_util.c | 4 | ||||
-rw-r--r-- | protocols/msn/ns.c | 51 |
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); |