⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 si.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * purple - Jabber Protocol Plugin * * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include "blist.h"#include "internal.h"#include "cipher.h"#include "debug.h"#include "ft.h"#include "request.h"#include "network.h"#include "notify.h"#include "buddy.h"#include "disco.h"#include "jabber.h"#include "iq.h"#include "si.h"#include "si.h"struct bytestreams_streamhost {	char *jid;	char *host;	int port;};typedef struct _JabberSIXfer {	JabberStream *js;	PurpleProxyConnectData *connect_data;	PurpleNetworkListenData *listen_data;	gboolean accepted;	char *stream_id;	char *iq_id;	enum {		STREAM_METHOD_UNKNOWN = 0,		STREAM_METHOD_BYTESTREAMS = 2 << 1,		STREAM_METHOD_IBB = 2 << 2,		STREAM_METHOD_UNSUPPORTED = 2 << 31	} stream_method;	GList *streamhosts;	PurpleProxyInfo *gpi;	char *rxqueue;	size_t rxlen;	gsize rxmaxlen;} JabberSIXfer;static PurpleXfer*jabber_si_xfer_find(JabberStream *js, const char *sid, const char *from){	GList *xfers;	if(!sid || !from)		return NULL;	for(xfers = js->file_transfers; xfers; xfers = xfers->next) {		PurpleXfer *xfer = xfers->data;		JabberSIXfer *jsx = xfer->data;		if(jsx->stream_id && xfer->who &&				!strcmp(jsx->stream_id, sid) && !strcmp(xfer->who, from))			return xfer;	}	return NULL;}static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer);static voidjabber_si_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message){	PurpleXfer *xfer = data;	JabberSIXfer *jsx = xfer->data;	JabberIq *iq;	xmlnode *query, *su;	struct bytestreams_streamhost *streamhost = jsx->streamhosts->data;	purple_proxy_info_destroy(jsx->gpi);	jsx->connect_data = NULL;	if(source < 0) {		purple_debug_warning("jabber",				"si connection failed, jid was %s, host was %s, error was %s\n",				streamhost->jid, streamhost->host, error_message);		jsx->streamhosts = g_list_remove(jsx->streamhosts, streamhost);		g_free(streamhost->jid);		g_free(streamhost->host);		g_free(streamhost);		jabber_si_bytestreams_attempt_connect(xfer);		return;	}	iq = jabber_iq_new_query(jsx->js, JABBER_IQ_RESULT, "http://jabber.org/protocol/bytestreams");	xmlnode_set_attrib(iq->node, "to", xfer->who);	jabber_iq_set_id(iq, jsx->iq_id);	query = xmlnode_get_child(iq->node, "query");	su = xmlnode_new_child(query, "streamhost-used");	xmlnode_set_attrib(su, "jid", streamhost->jid);	jabber_iq_send(iq);	purple_xfer_start(xfer, source, NULL, -1);}static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer){	JabberSIXfer *jsx = xfer->data;	struct bytestreams_streamhost *streamhost;	char *dstaddr, *p;	int i;	unsigned char hashval[20];	JabberID *dstjid;	if(!jsx->streamhosts) {		JabberIq *iq = jabber_iq_new(jsx->js, JABBER_IQ_ERROR);		xmlnode *error, *inf;		if(jsx->iq_id)			jabber_iq_set_id(iq, jsx->iq_id);		xmlnode_set_attrib(iq->node, "to", xfer->who);		error = xmlnode_new_child(iq->node, "error");		xmlnode_set_attrib(error, "code", "404");		xmlnode_set_attrib(error, "type", "cancel");		inf = xmlnode_new_child(error, "item-not-found");		xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas");		jabber_iq_send(iq);		purple_xfer_cancel_local(xfer);		return;	}	streamhost = jsx->streamhosts->data;	dstjid = jabber_id_new(xfer->who);	if(dstjid != NULL) {		jsx->gpi = purple_proxy_info_new();		purple_proxy_info_set_type(jsx->gpi, PURPLE_PROXY_SOCKS5);		purple_proxy_info_set_host(jsx->gpi, streamhost->host);		purple_proxy_info_set_port(jsx->gpi, streamhost->port);		dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, dstjid->node, dstjid->domain, dstjid->resource, jsx->js->user->node,				jsx->js->user->domain, jsx->js->user->resource);		purple_cipher_digest_region("sha1", (guchar *)dstaddr, strlen(dstaddr),				sizeof(hashval), hashval, NULL);		g_free(dstaddr);		dstaddr = g_malloc(41);		p = dstaddr;		for(i=0; i<20; i++, p+=2)			snprintf(p, 3, "%02x", hashval[i]);		jsx->connect_data = purple_proxy_connect_socks5(NULL, jsx->gpi,				dstaddr, 0,				jabber_si_bytestreams_connect_cb, xfer);		g_free(dstaddr);		jabber_id_free(dstjid);	}	if (jsx->connect_data == NULL)	{		jsx->streamhosts = g_list_remove(jsx->streamhosts, streamhost);		g_free(streamhost->jid);		g_free(streamhost->host);		g_free(streamhost);		jabber_si_bytestreams_attempt_connect(xfer);	}}void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet){	PurpleXfer *xfer;	JabberSIXfer *jsx;	xmlnode *query, *streamhost;	const char *sid, *from, *type;	if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "set"))		return;	if(!(from = xmlnode_get_attrib(packet, "from")))		return;	if(!(query = xmlnode_get_child(packet, "query")))		return;	if(!(sid = xmlnode_get_attrib(query, "sid")))		return;	if(!(xfer = jabber_si_xfer_find(js, sid, from)))		return;	jsx = xfer->data;	if(!jsx->accepted)		return;	if(jsx->iq_id)		g_free(jsx->iq_id);	jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id"));	for(streamhost = xmlnode_get_child(query, "streamhost"); streamhost;			streamhost = xmlnode_get_next_twin(streamhost)) {		const char *jid, *host, *port;		int portnum;		if((jid = xmlnode_get_attrib(streamhost, "jid")) &&				(host = xmlnode_get_attrib(streamhost, "host")) &&				(port = xmlnode_get_attrib(streamhost, "port")) &&				(portnum = atoi(port))) {			struct bytestreams_streamhost *sh = g_new0(struct bytestreams_streamhost, 1);			sh->jid = g_strdup(jid);			sh->host = g_strdup(host);			sh->port = portnum;			jsx->streamhosts = g_list_append(jsx->streamhosts, sh);		}	}	jabber_si_bytestreams_attempt_connect(xfer);}static voidjabber_si_xfer_bytestreams_send_read_again_resp_cb(gpointer data, gint source,		PurpleInputCondition cond){	PurpleXfer *xfer = data;	JabberSIXfer *jsx = xfer->data;	int len;	len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen);	if (len < 0 && errno == EAGAIN)		return;	else if (len < 0) {		purple_input_remove(xfer->watcher);		xfer->watcher = 0;		g_free(jsx->rxqueue);		jsx->rxqueue = NULL;		close(source);		purple_xfer_cancel_remote(xfer);		return;	}	jsx->rxlen += len;	if (jsx->rxlen < jsx->rxmaxlen)		return;	purple_input_remove(xfer->watcher);	xfer->watcher = 0;	g_free(jsx->rxqueue);	jsx->rxqueue = NULL;	purple_xfer_start(xfer, source, NULL, -1);}static voidjabber_si_xfer_bytestreams_send_read_again_cb(gpointer data, gint source,		PurpleInputCondition cond){	PurpleXfer *xfer = data;	JabberSIXfer *jsx = xfer->data;	int i;	char buffer[256];	int len;	char *dstaddr, *p;	unsigned char hashval[20];	const char *host;	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_again_cb\n");	if(jsx->rxlen < 5) {		purple_debug_info("jabber", "reading the first 5 bytes\n");		len = read(source, buffer, 5 - jsx->rxlen);		if(len < 0 && errno == EAGAIN)			return;		else if(len <= 0) {			purple_input_remove(xfer->watcher);			xfer->watcher = 0;			close(source);			purple_xfer_cancel_remote(xfer);			return;		}		jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);		memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);		jsx->rxlen += len;		return;	} else if(jsx->rxqueue[0] != 0x05 || jsx->rxqueue[1] != 0x01 ||			jsx->rxqueue[3] != 0x03) {		purple_debug_info("jabber", "invalid socks5 stuff\n");		purple_input_remove(xfer->watcher);		xfer->watcher = 0;		close(source);		purple_xfer_cancel_remote(xfer);		return;	} else if(jsx->rxlen - 5 <  jsx->rxqueue[4] + 2) {		purple_debug_info("jabber", "reading umpteen more bytes\n");		len = read(source, buffer, jsx->rxqueue[4] + 5 + 2 - jsx->rxlen);		if(len < 0 && errno == EAGAIN)			return;		else if(len <= 0) {			purple_input_remove(xfer->watcher);			xfer->watcher = 0;			close(source);			purple_xfer_cancel_remote(xfer);			return;		}		jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);		memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);		jsx->rxlen += len;	}	if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2)		return;	purple_input_remove(xfer->watcher);	xfer->watcher = 0;	dstaddr = g_strdup_printf("%s%s@%s/%s%s", jsx->stream_id,			jsx->js->user->node, jsx->js->user->domain,			jsx->js->user->resource, xfer->who);	purple_cipher_digest_region("sha1", (guchar *)dstaddr, strlen(dstaddr),							  sizeof(hashval), hashval, NULL);	g_free(dstaddr);	dstaddr = g_malloc(41);	p = dstaddr;	for(i=0; i<20; i++, p+=2)		snprintf(p, 3, "%02x", hashval[i]);	if(jsx->rxqueue[4] != 40 || strncmp(dstaddr, jsx->rxqueue+5, 40) ||			jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) {		purple_debug_error("jabber", "someone connected with the wrong info!\n");		close(source);		purple_xfer_cancel_remote(xfer);		return;	}	g_free(jsx->rxqueue);	host = purple_network_get_my_ip(jsx->js->fd);	jsx->rxmaxlen = 5 + strlen(host) + 2;	jsx->rxqueue = g_malloc(jsx->rxmaxlen);	jsx->rxlen = 0;	jsx->rxqueue[0] = 0x05;	jsx->rxqueue[1] = 0x00;	jsx->rxqueue[2] = 0x00;	jsx->rxqueue[3] = 0x03;	jsx->rxqueue[4] = strlen(host);	memcpy(jsx->rxqueue + 5, host, strlen(host));	jsx->rxqueue[5+strlen(host)] = 0x00;	jsx->rxqueue[6+strlen(host)] = 0x00;	xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,		jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer);	jabber_si_xfer_bytestreams_send_read_again_resp_cb(xfer, source,		PURPLE_INPUT_WRITE);}static voidjabber_si_xfer_bytestreams_send_read_response_cb(gpointer data, gint source,		PurpleInputCondition cond){	PurpleXfer *xfer = data;	JabberSIXfer *jsx = xfer->data;	int len;	len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen);	if (len < 0 && errno == EAGAIN)		return;	else if (len < 0) {		purple_input_remove(xfer->watcher);		xfer->watcher = 0;		g_free(jsx->rxqueue);		jsx->rxqueue = NULL;		close(source);		purple_xfer_cancel_remote(xfer);		return;	}	jsx->rxlen += len;	if (jsx->rxlen < jsx->rxmaxlen)		return;	purple_input_remove(xfer->watcher);	xfer->watcher = 0;	if (jsx->rxqueue[1] == 0x00) {		xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ,			jabber_si_xfer_bytestreams_send_read_again_cb, xfer);		g_free(jsx->rxqueue);		jsx->rxqueue = NULL;	} else {		close(source);		purple_xfer_cancel_remote(xfer);	}}static voidjabber_si_xfer_bytestreams_send_read_cb(gpointer data, gint source,		PurpleInputCondition cond){	PurpleXfer *xfer = data;	JabberSIXfer *jsx = xfer->data;	int i;	int len;	char buffer[256];	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n");	xfer->fd = source;	if(jsx->rxlen < 2) {		purple_debug_info("jabber", "reading those first two bytes\n");		len = read(source, buffer, 2 - jsx->rxlen);		if(len < 0 && errno == EAGAIN)			return;		else if(len <= 0) {			purple_input_remove(xfer->watcher);			xfer->watcher = 0;			close(source);			purple_xfer_cancel_remote(xfer);			return;		}		jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);		memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);		jsx->rxlen += len;		return;	} else if(jsx->rxlen - 2 <  jsx->rxqueue[1]) {		purple_debug_info("jabber", "reading the next umpteen bytes\n");		len = read(source, buffer, jsx->rxqueue[1] + 2 - jsx->rxlen);		if(len < 0 && errno == EAGAIN)			return;		else if(len <= 0) {			purple_input_remove(xfer->watcher);			xfer->watcher = 0;			close(source);			purple_xfer_cancel_remote(xfer);			return;		}		jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);		memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);		jsx->rxlen += len;	}	if(jsx->rxlen -2 < jsx->rxqueue[1])		return;	purple_input_remove(xfer->watcher);	xfer->watcher = 0;	purple_debug_info("jabber", "checking to make sure we're socks FIVE\n");	if(jsx->rxqueue[0] != 0x05) {		close(source);		purple_xfer_cancel_remote(xfer);		return;	}	purple_debug_info("jabber", "going to test %hhu different methods\n", jsx->rxqueue[1]);	for(i=0; i<jsx->rxqueue[1]; i++) {		purple_debug_info("jabber", "testing %hhu\n", jsx->rxqueue[i+2]);		if(jsx->rxqueue[i+2] == 0x00) {			g_free(jsx->rxqueue);			jsx->rxlen = 0;			jsx->rxmaxlen = 2;			jsx->rxqueue = g_malloc(jsx->rxmaxlen);			jsx->rxqueue[0] = 0x05;			jsx->rxqueue[1] = 0x00;			xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,				jabber_si_xfer_bytestreams_send_read_response_cb,				xfer);			jabber_si_xfer_bytestreams_send_read_response_cb(xfer,				source, PURPLE_INPUT_WRITE);			jsx->rxqueue = NULL;			jsx->rxlen = 0;			return;		}	}	g_free(jsx->rxqueue);	jsx->rxlen = 0;	jsx->rxmaxlen = 2;	jsx->rxqueue = g_malloc(jsx->rxmaxlen);	jsx->rxqueue[0] = 0x05;	jsx->rxqueue[1] = 0xFF;	xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,		jabber_si_xfer_bytestreams_send_read_response_cb, xfer);	jabber_si_xfer_bytestreams_send_read_response_cb(xfer,		source, PURPLE_INPUT_WRITE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -