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

📄 slplink.c

📁 msn message protocol stack
💻 C
字号:
/** * @file slplink.c MSNSLP Link support * * gaim * * Gaim is the legal property of its developers, whose names are too numerous * to list here.  Please refer to the COPYRIGHT file distributed with this * source distribution. * * 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 "msn.h"#include "slplink.h"#include "switchboard.h"#include "slp.h"void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);#ifdef DEBUG_SLP_FILESstatic int m_sc = 0;static int m_rc = 0;static voiddebug_msg_to_file(MsnMessage *msg, gboolean send){	char *tmp;	char *dir;	char *pload;	FILE *tf;	int c;	gsize pload_size;	dir = send ? "send" : "recv";	c = send ? m_sc++ : m_rc++;	tmp = g_strdup_printf("%s/msntest/%s/%03d", g_get_home_dir(), dir, c);	tf = fopen(tmp, "wb");	pload = msn_message_gen_payload(msg, &pload_size);	fwrite(pload, 1, pload_size, tf);	fclose(tf);	g_free(tmp);}#endifMsnSlpLink *msn_slplink_new(MsnSession *session, const char *username){	MsnSlpLink *slplink;	slplink = g_new0(MsnSlpLink, 1);	slplink->session = session;	slplink->slp_seq_id = rand() % 0xFFFFFF00 + 4;	slplink->local_user = g_strdup(msn_user_get_passport(session->user));	slplink->remote_user = g_strdup(username);	slplink->slp_msg_queue = g_queue_new();	session->slplinks =		g_list_append(session->slplinks, slplink);	return slplink;}voidmsn_slplink_destroy(MsnSlpLink *slplink){	MsnSession *session;	session = slplink->session;	if (slplink->local_user != NULL)		g_free(slplink->local_user);	if (slplink->remote_user != NULL)		g_free(slplink->remote_user);	if (slplink->directconn != NULL)		msn_directconn_destroy(slplink->directconn);	session->slplinks =		g_list_remove(session->slplinks, slplink);	g_free(slplink);}MsnSlpLink *msn_session_find_slplink(MsnSession *session, const char *who){	MsnSlpLink *slplink;	GList *l;	for (l = session->slplinks; l != NULL; l = l->next)	{		slplink = l->data;		if (!strcmp(slplink->remote_user, who))			return slplink;	}	return NULL;}MsnSlpLink *msn_session_get_slplink(MsnSession *session, const char *username){	MsnSlpLink *slplink;	slplink = msn_session_find_slplink(session, username);	if (slplink == NULL)		slplink = msn_slplink_new(session, username);	return slplink;}MsnSlpSession *msn_slplink_find_slp_session(MsnSlpLink *slplink, long session_id){	GList *l;	MsnSlpSession *slpsession;	for (l = slplink->slp_sessions; l != NULL; l = l->next)	{		slpsession = l->data;		if (slpsession->id == session_id)			return slpsession;	}	return NULL;}MsnSlpCall *msn_slplink_find_slp_call(MsnSlpLink *slplink, const char *id){	GList *l;	MsnSlpCall *slpcall;	if (!id)		return NULL;	for (l = slplink->slp_calls; l != NULL; l = l->next)	{		slpcall = l->data;		if (slpcall->id && !strcmp(slpcall->id, id))			return slpcall;	}	return NULL;}MsnSlpCall *msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id){	GList *l;	MsnSlpCall *slpcall;	for (l = slplink->slp_calls; l != NULL; l = l->next)	{		slpcall = l->data;		if (slpcall->session_id == id)			return slpcall;	}	return NULL;}voidmsn_slplink_send_msg(MsnSlpLink *slplink, MsnMessage *msg){	if (slplink->directconn != NULL)	{		msn_directconn_send_msg(slplink->directconn, msg);	}	else	{		MsnSwitchBoard *swboard;		swboard = msn_session_get_swboard(slplink->session, slplink->remote_user);		if (swboard == NULL)			return;		if (!g_queue_is_empty(swboard->im_queue) ||			!swboard->user_joined)		{			msn_switchboard_queue_msg(swboard, msg);		}		else		{			msn_switchboard_send_msg(swboard, msg);		}	}}static voidt_ack(MsnCmdProc *cmdproc, MsnCommand *cmd){	MsnSlpMessage *slpmsg;	long long real_size;	slpmsg = cmd->trans->data;	real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size;	if (slpmsg->offset < real_size)	{		msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);	}	else	{		/* The whole message has been sent */		if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030)		{			if ((slpmsg->slpcall != NULL) &&				(slpmsg->slpcall->cb != NULL))			{				slpmsg->slpcall->cb(slpmsg->slpcall, NULL, 0);			}		}		msn_slpmsg_destroy(slpmsg);	}}voidmsn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg){	MsnMessage *msg;	long long real_size;	size_t len = 0;	msg = slpmsg->msg;	real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size;	if (slpmsg->offset < real_size)	{		if (slpmsg->fp)		{			char data[1202];			len = fread(data, 1, sizeof(data), slpmsg->fp);			msn_message_set_bin_data(msg, data, len);		}		else		{			len = slpmsg->size - slpmsg->offset;			if (len > 1202)				len = 1202;			msn_message_set_bin_data(msg, slpmsg->buffer + slpmsg->offset, len);		}		msg->msnslp_header.offset = slpmsg->offset;		msg->msnslp_header.length = len;	}#ifdef DEBUG_SLP	msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body);#endif#ifdef DEBUG_SLP_FILES	debug_msg_to_file(msg, TRUE);#endif	msn_slplink_send_msg(slplink, msg);	if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030)	{		if ((slpmsg->slpcall != NULL) &&			(slpmsg->slpcall->progress_cb != NULL))		{			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,										 len, slpmsg->offset);		}	}	slpmsg->offset += len;}voidmsn_slplink_release_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg){	MsnMessage *msg;	slpmsg->msg = msg = msn_message_new_msnslp();	if (slpmsg->flags == 0x0)	{		msg->msnslp_header.session_id = slpmsg->session_id;		msg->msnslp_header.ack_id = rand() % 0xFFFFFF00;	}	else if (slpmsg->flags == 0x2)	{		msg->msnslp_header.session_id = slpmsg->session_id;		msg->msnslp_header.ack_id = slpmsg->ack_id;		msg->msnslp_header.ack_size = slpmsg->ack_size;	}	else if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030)	{		MsnSlpSession *slpsession;		slpsession = slpmsg->slpsession;		g_return_if_fail(slpsession != NULL);		msg->msnslp_header.session_id = slpsession->id;		msg->msnslp_footer.value = slpsession->app_id;		msg->msnslp_header.ack_id = rand() % 0xFFFFFF00;	}	else if (slpmsg->flags == 0x100)	{		msg->msnslp_header.ack_id     = slpmsg->ack_id;		msg->msnslp_header.ack_sub_id = slpmsg->ack_sub_id;		msg->msnslp_header.ack_size   = slpmsg->ack_size;	}	msg->msnslp_header.id = slpmsg->id;	msg->msnslp_header.flags = slpmsg->flags;	msg->msnslp_header.total_size = slpmsg->size;	msn_message_set_attr(msg, "P2P-Dest", slplink->remote_user);	msg->ack_cb = t_ack;	msg->ack_data = slpmsg;	msn_slplink_send_msgpart(slplink, slpmsg);}voidmsn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg){	slpmsg->id = slplink->slp_seq_id++;	g_queue_push_head(slplink->slp_msg_queue, slpmsg);}voidmsn_slplink_send_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg){	slpmsg->id = slplink->slp_seq_id++;	msn_slplink_release_msg(slplink, slpmsg);}voidmsn_slplink_unleash(MsnSlpLink *slplink){	MsnSlpMessage *slpmsg;	/* Send the queued msgs in the order they came. */	while ((slpmsg = g_queue_pop_tail(slplink->slp_msg_queue)) != NULL)		msn_slplink_release_msg(slplink, slpmsg);}voidmsn_slplink_send_ack(MsnSlpLink *slplink, MsnMessage *msg){	MsnSlpMessage *slpmsg;	slpmsg = msn_slpmsg_new(slplink);	slpmsg->session_id = msg->msnslp_header.session_id;	slpmsg->size       = msg->msnslp_header.total_size;	slpmsg->flags      = 0x02;	slpmsg->ack_id     = msg->msnslp_header.id;	slpmsg->ack_sub_id = msg->msnslp_header.ack_id;	slpmsg->ack_size   = msg->msnslp_header.total_size;#ifdef DEBUG_SLP	slpmsg->info = "SLP ACK";#endif	msn_slplink_send_slpmsg(slplink, slpmsg);}static voidsend_file_cb(MsnSlpSession *slpsession){	MsnSlpCall *slpcall;	MsnSlpMessage *slpmsg;	slpcall = slpsession->slpcall;	slpmsg = msn_slpmsg_new(slpcall->slplink);	slpmsg->flags = 0x1000030;	slpmsg->slpsession = slpsession;#ifdef DEBUG_SLP	slpmsg->info = "SLP FILE";#endif	slpmsg->slpcall = slpcall;	msn_slpmsg_open_file(slpmsg, gaim_xfer_get_local_filename(slpcall->xfer));	msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);}voidmsn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg){	MsnSlpMessage *slpmsg;	const char *data;	gsize offset;	gsize len;#ifdef DEBUG_SLP	msn_slpmsg_show(msg);#endif#ifdef DEBUG_SLP_FILES	debug_msg_to_file(msg, FALSE);#endif	if (msg->msnslp_header.total_size < msg->msnslp_header.length)	{		gaim_debug_error("msn", "This can't be good\n");		g_return_if_reached();	}	slpmsg = NULL;	data = msn_message_get_bin_data(msg, &len);	/*		OVERHEAD!		if (msg->msnslp_header.length < msg->msnslp_header.total_size)	 */	offset = msg->msnslp_header.offset;	if (offset == 0)	{		slpmsg = msn_slpmsg_new(slplink);		slpmsg->id = msg->msnslp_header.id;		slpmsg->session_id = msg->msnslp_header.session_id;		slpmsg->size = msg->msnslp_header.total_size;		slpmsg->flags = msg->msnslp_header.flags;		if (slpmsg->session_id)		{			if (slpmsg->slpcall == NULL)				slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id);			if (slpmsg->slpcall != NULL)			{				if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030)				{					GaimXfer *xfer;					xfer = slpmsg->slpcall->xfer;					if (xfer != NULL)					{						slpmsg->fp =							fopen(gaim_xfer_get_local_filename(slpmsg->slpcall->xfer),								  "wb");					}				}			}		}		if (!slpmsg->fp)		{			slpmsg->buffer = g_try_malloc(slpmsg->size);			if (slpmsg->buffer == NULL)			{				gaim_debug_error("msn", "Failed to allocate buffer for slpmsg\n");				return;			}		}	}	else	{		slpmsg = msn_slplink_message_find(slplink, msg->msnslp_header.session_id, msg->msnslp_header.id);	}	if (slpmsg != NULL)	{		if (slpmsg->fp)		{			/* fseek(slpmsg->fp, offset, SEEK_SET); */			len = fwrite(data, 1, len, slpmsg->fp);		}		else		{			if ((offset + len) > slpmsg->size)			{				gaim_debug_error("msn", "Oversized slpmsg\n");				g_return_if_reached();			}			else				memcpy(slpmsg->buffer + offset, data, len);		}	}	else	{		gaim_debug_error("msn", "Couldn't find slpmsg\n");		g_return_if_reached();	}	if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030)	{		if ((slpmsg->slpcall != NULL) &&			(slpmsg->slpcall->progress_cb != NULL))		{			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,										 len, offset);		}	}#if 0	if (slpmsg->buffer == NULL)		return;#endif	if (msg->msnslp_header.offset + msg->msnslp_header.length		>= msg->msnslp_header.total_size)	{		/* All the pieces of the slpmsg have been received */		MsnSlpCall *slpcall;		slpcall = msn_slp_process_msg(slplink, slpmsg);		if (slpmsg->flags == 0x100)		{			MsnDirectConn *directconn;			directconn = slplink->directconn;			if (!directconn->acked)				msn_directconn_send_handshake(directconn);		}		else if (slpmsg->flags == 0x0 || slpmsg->flags == 0x20 ||				 slpmsg->flags == 0x1000030)		{			/* Release all the messages and send the ACK */			msn_slplink_send_ack(slplink, msg);			msn_slplink_unleash(slplink);		}		msn_slpmsg_destroy(slpmsg);		if (slpcall != NULL && slpcall->wasted)			msn_slp_call_destroy(slpcall);	}}MsnSlpMessage *msn_slplink_message_find(MsnSlpLink *slplink, long session_id, long id){	GList *e;	for (e = slplink->slp_msgs; e != NULL; e = e->next)	{		MsnSlpMessage *slpmsg = e->data;		if ((slpmsg->session_id == session_id) && (slpmsg->id == id))			return slpmsg;	}	return NULL;}typedef struct{	guint32 length;	guint32 unk1;	guint32 file_size;	guint32 unk2;	guint32 unk3;} MsnContextHeader;#define MAX_FILE_NAME_LEN 0x226static char *gen_context(const char *file_name, const char *file_path){	struct stat st;	gsize size = 0;	MsnContextHeader header;	gchar *u8 = NULL;	gchar *base, *n;	gunichar2 *uni = NULL;	glong currentChar = 0;	glong uni_len = 0;	gsize len;	if (stat(file_path, &st) == 0)		size = st.st_size;	if(!file_name) {		u8 = gaim_utf8_try_convert(g_basename(file_path));		file_name = u8;	}	uni = g_utf8_to_utf16(file_name, -1, NULL, &uni_len, NULL);	if(u8) {		g_free(u8);		file_name = NULL;		u8 = NULL;	}	len = sizeof(MsnContextHeader) + MAX_FILE_NAME_LEN + 4;	header.length = GUINT32_TO_LE(len);	header.unk1 = GUINT32_TO_LE(2);	header.file_size = GUINT32_TO_LE(size);	header.unk2 = GUINT32_TO_LE(0);	header.unk3 = GUINT32_TO_LE(0);		base = g_malloc(len + 1);	n = base;	memcpy(n, &header, sizeof(MsnContextHeader));	n += sizeof(MsnContextHeader);	memset(n, 0x00, MAX_FILE_NAME_LEN);	for(currentChar = 0; currentChar < uni_len; currentChar++) {		*((gunichar2 *)n + currentChar) = GUINT16_TO_LE(uni[currentChar]);	}	n += MAX_FILE_NAME_LEN;	memset(n, 0xFF, 4);	n += 4;		g_free(uni);	return gaim_base64_encode(base, len);}voidmsn_slplink_request_ft(MsnSlpLink *slplink, GaimXfer *xfer){	MsnSlpCall *slpcall;	char *context;	const char *fn;	const char *fp;	fn = gaim_xfer_get_filename(xfer);	fp = gaim_xfer_get_local_filename(xfer);	g_return_if_fail(slplink != NULL);	g_return_if_fail(fp != NULL);	slpcall = msn_slp_call_new(slplink);	msn_slp_call_init(slpcall, MSN_SLPCALL_DC);	slpcall->session_init_cb = send_file_cb;	slpcall->end_cb = msn_xfer_end_cb;	slpcall->progress_cb = msn_xfer_progress_cb;	slpcall->cb = msn_xfer_completed_cb;	slpcall->xfer = xfer;	gaim_xfer_set_cancel_send_fnc(xfer, msn_xfer_cancel);	xfer->data = slpcall;	context = gen_context(fn, fp);	msn_slp_call_invite(slpcall, "5D3E02AB-6190-11D3-BBBB-00C04F795683", 2,						context);	g_free(context);}voidmsn_slplink_request_object(MsnSlpLink *slplink,						   const char *info,						   MsnSlpCb cb,						   const MsnObject *obj){	MsnSlpCall *slpcall;	char *msnobj_data;	char *msnobj_base64;	g_return_if_fail(slplink != NULL);	g_return_if_fail(obj     != NULL);	msnobj_data = msn_object_to_string(obj);	msnobj_base64 = gaim_base64_encode(msnobj_data, strlen(msnobj_data));	g_free(msnobj_data);	slpcall = msn_slp_call_new(slplink);	msn_slp_call_init(slpcall, MSN_SLPCALL_ANY);	slpcall->data_info = g_strdup(info);	slpcall->cb = cb;	msn_slp_call_invite(slpcall, "A4268EEC-FEC5-49E5-95C3-F126696BDBF6", 1,						msnobj_base64);	g_free(msnobj_base64);}

⌨️ 快捷键说明

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