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);  | 
