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

📄 file_trans.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
					filename_len = strlen(filename);					_fill_filename_md5(filename, filename_md5);					_fill_file_md5(purple_xfer_get_local_filename(qd->xfer),							purple_xfer_get_size(qd->xfer),							file_md5);					info->fragment_num = (filesize - 1) / QQ_FILE_FRAGMENT_MAXLEN + 1;					info->fragment_len = QQ_FILE_FRAGMENT_MAXLEN;					purple_debug(PURPLE_DEBUG_INFO, "QQ", 							"start transfering data, %d fragments with %d length each\n",							info->fragment_num, info->fragment_len);					/* Unknown */					bytes += create_packet_w(raw_data, &cursor, 0x0000);					/* Sub-operation type */					bytes += create_packet_b(raw_data, &cursor, sub_type);					/* Length of file */					bytes += create_packet_dw(raw_data, &cursor, filesize);					/* Number of fragments */					bytes += create_packet_dw(raw_data, &cursor, info->fragment_num);					/* Length of a single fragment */					bytes += create_packet_dw(raw_data, &cursor, info->fragment_len);					bytes += create_packet_data(raw_data, &cursor, file_md5, 16);					bytes += create_packet_data(raw_data, &cursor, filename_md5, 16);					/* Length of filename */					bytes += create_packet_w(raw_data, &cursor, filename_len);					/* 8 unknown bytes */					bytes += create_packet_dw(raw_data, &cursor, 0x00000000);					bytes += create_packet_dw(raw_data, &cursor, 0x00000000);					/* filename */					bytes += create_packet_data(raw_data, &cursor, (guint8 *) filename,							filename_len);					break;				case QQ_FILE_DATA_INFO:					purple_debug(PURPLE_DEBUG_INFO, "QQ", 							"sending %dth fragment with length %d, offset %d\n",							fragment_index, len, (fragment_index-1)*fragment_size);					/* bytes += create_packet_w(raw_data, &cursor, ++(qd->send_seq)); */					bytes += create_packet_w(raw_data, &cursor, info->send_seq);					bytes += create_packet_b(raw_data, &cursor, sub_type);					/* bytes += create_packet_dw(raw_data, &cursor, fragment_index); */					bytes += create_packet_dw(raw_data, &cursor, fragment_index - 1);					bytes += create_packet_dw(raw_data, &cursor, (fragment_index - 1) * fragment_size);					bytes += create_packet_w(raw_data, &cursor, len);					bytes += create_packet_data(raw_data, &cursor, data, len);					break;				case QQ_FILE_EOF:					purple_debug(PURPLE_DEBUG_INFO, "QQ", "end of sending data\n");					/* bytes += create_packet_w(raw_data, &cursor, info->fragment_num + 1); */					bytes += create_packet_w(raw_data, &cursor, info->fragment_num);					bytes += create_packet_b(raw_data, &cursor, sub_type);					/* purple_xfer_set_completed(qd->xfer, TRUE); */			}			break;		case QQ_FILE_CMD_FILE_OP_ACK:			switch (sub_type)			{				case QQ_FILE_BASIC_INFO:					bytes += create_packet_w(raw_data, &cursor, 0x0000);					bytes += create_packet_b(raw_data, &cursor, sub_type);					bytes += create_packet_dw(raw_data, &cursor, 0x00000000);					break;				case QQ_FILE_DATA_INFO:					bytes += create_packet_w(raw_data, &cursor, seq);					bytes += create_packet_b(raw_data, &cursor, sub_type);					bytes += create_packet_dw(raw_data, &cursor, fragment_index);					break;				case QQ_FILE_EOF:					bytes += create_packet_w(raw_data, &cursor, filesize / QQ_FILE_FRAGMENT_MAXLEN + 2);					bytes += create_packet_b(raw_data, &cursor, sub_type);					break;			}	}	purple_debug(PURPLE_DEBUG_INFO, "QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type));	_qq_send_file(gc, raw_data, bytes, QQ_FILE_DATA_PACKET_TAG, info->to_uid);}/* A conversation starts like this: * Sender ==> Receiver [QQ_FILE_CMD_PING] * Sender <== Receiver [QQ_FILE_CMD_PONG] * Sender ==> Receiver [QQ_FILE_CMD_SENDER_SAY_HELLO] * Sender <== Receiver [QQ_FILE_CMD_SENDER_SAY_HELLO_ACK] * Sender <== Receiver [QQ_FILE_CMD_RECEIVER_SAY_HELLO] * Sender ==> Receiver [QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK] * Sender ==> Receiver [QQ_FILE_CMD_FILE_OP, QQ_FILE_BASIC_INFO] * Sender <== Receiver [QQ_FILE_CMD_FILE_OP_ACK, QQ_FILE_BASIC_INFO] * Sender ==> Receiver [QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO] * Sender <== Receiver [QQ_FILE_CMD_FILE_OP_ACK, QQ_FILE_DATA_INFO] * Sender ==> Receiver [QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO] * Sender <== Receiver [QQ_FILE_CMD_FILE_OP_ACK, QQ_FILE_DATA_INFO] * ...... * Sender ==> Receiver [QQ_FILE_CMD_FILE_OP, QQ_FILE_EOF] * Sender <== Receiver [QQ_FILE_CMD_FILE_OP_ACK, QQ_FILE_EOF] */static void _qq_process_recv_file_ctl_packet(PurpleConnection *gc, guint8 *data, guint8 *cursor,		gint len, qq_file_header *fh){	guint8 *decrypted_data;	gint decrypted_len;	qq_data *qd = (qq_data *) gc->proto_data;	guint16 packet_type;	guint16 seq;	guint8 hellobyte;	ft_info *info = (ft_info *) qd->xfer->data;	decrypted_data = g_newa(guint8, len);	decrypted_len = len;	if (qq_crypt(DECRYPT, cursor, len - (cursor - data), qd->session_md5, decrypted_data, &decrypted_len)) {		gchar *hex_dump;		cursor = decrypted_data + 16;	/* skip md5 section */		read_packet_w(decrypted_data, &cursor, decrypted_len, &packet_type);		read_packet_w(decrypted_data, &cursor, decrypted_len, &seq);		cursor += 4+1+1+19+1;		purple_debug(PURPLE_DEBUG_INFO, "QQ", "==> [%d] receive %s packet\n", seq, qq_get_file_cmd_desc(packet_type));		hex_dump = hex_dump_to_str(decrypted_data, decrypted_len);		purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypted control packet received: \n%s", hex_dump);		g_free(hex_dump);		switch (packet_type) {			case QQ_FILE_CMD_NOTIFY_IP_ACK:				cursor = decrypted_data;				qq_get_conn_info(decrypted_data, &cursor, decrypted_len, info);/*				qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PING, fh->sender_uid, 0); */				qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh->sender_uid, 0);					break;			case QQ_FILE_CMD_SENDER_SAY_HELLO:				/* I'm receiver, if we receive SAY_HELLO from sender, we send back the ACK */				cursor += 47;				read_packet_b(decrypted_data, &cursor, 						decrypted_len, &hellobyte);				qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO_ACK, fh->sender_uid, hellobyte);				qq_send_file_ctl_packet(gc, QQ_FILE_CMD_RECEIVER_SAY_HELLO, fh->sender_uid, 0);				break;			case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:				/* I'm sender, do nothing */				break;			case QQ_FILE_CMD_RECEIVER_SAY_HELLO:				/* I'm sender, ack the hello packet and send the first data */				cursor += 47;				read_packet_b(decrypted_data, &cursor, 						decrypted_len, &hellobyte);				qq_send_file_ctl_packet(gc, QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK, fh->sender_uid, hellobyte);				_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_BASIC_INFO, 0, 0, NULL, 0);				break;			case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:				/* I'm receiver, do nothing */				break;			case QQ_FILE_CMD_PING:				/* I'm receiver, ack the PING */				qq_send_file_ctl_packet(gc, QQ_FILE_CMD_PONG, fh->sender_uid, 0);				break;			case QQ_FILE_CMD_PONG:				qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh->sender_uid, 0);				break;			default:				purple_debug(PURPLE_DEBUG_INFO, "QQ", "unprocess file command %d\n", packet_type);		}	} }static void _qq_recv_file_progess(PurpleConnection *gc, guint8 *buffer, guint16 len, guint32 index, guint32 offset){	qq_data *qd = (qq_data *) gc->proto_data;	PurpleXfer *xfer = qd->xfer;	ft_info *info = (ft_info *) xfer->data;	guint32 mask;	purple_debug(PURPLE_DEBUG_INFO, "QQ", 			"receiving %dth fragment with length %d, slide window status %o, max_fragment_index %d\n", 			index, len, info->window, info->max_fragment_index);	if (info->window == 0 && info->max_fragment_index == 0) {		if (_qq_xfer_open_file(purple_xfer_get_local_filename(xfer), "wb", xfer) == -1) {			purple_xfer_cancel_local(xfer);			return;		}		purple_debug(PURPLE_DEBUG_INFO, "QQ", "object file opened for writing\n");	}	mask = 0x1 << (index % sizeof(info->window));	if (index < info->max_fragment_index || (info->window & mask)) {		purple_debug(PURPLE_DEBUG_INFO, "QQ", "duplicate %dth fragment, drop it!\n", index+1);		return;	}			info->window |= mask;	_qq_xfer_write_file(buffer, index, len, xfer);		xfer->bytes_sent += len;	xfer->bytes_remaining -= len;	purple_xfer_update_progress(xfer);		mask = 0x1 << (info->max_fragment_index % sizeof(info->window));	while (info->window & mask)	{		info->window &= ~mask;		info->max_fragment_index ++;		if (mask & 0x8000) mask = 0x0001;		else mask = mask << 1;	}	purple_debug(PURPLE_DEBUG_INFO, "QQ", "procceed %dth fragment, slide window status %o, max_fragment_index %d\n", 			index, info->window, info->max_fragment_index);}static void _qq_send_file_progess(PurpleConnection *gc){	qq_data *qd = (qq_data *) gc->proto_data;	PurpleXfer *xfer = qd->xfer;	ft_info *info = (ft_info *) xfer->data;	guint32 mask;	guint8 *buffer;	guint i;	gint readbytes;		if (purple_xfer_get_bytes_remaining(xfer) <= 0) return;	if (info->window == 0 && info->max_fragment_index == 0)	{		if (_qq_xfer_open_file(purple_xfer_get_local_filename(xfer), "rb", xfer) == -1) {			purple_xfer_cancel_local(xfer);			return;		}	}	buffer = g_newa(guint8, info->fragment_len);	mask = 0x1 << (info->max_fragment_index % sizeof(info->window));	for (i = 0; i < sizeof(info->window); i++) {		if ((info->window & mask) == 0) {			readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + i, info->fragment_len, xfer);			if (readbytes > 0)				_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO,					info->max_fragment_index + i + 1, 0, buffer, readbytes);		}		if (mask & 0x8000) mask = 0x0001;		else mask = mask << 1;	}}static void _qq_update_send_progess(PurpleConnection *gc, guint32 fragment_index){	guint32 mask;	guint8 *buffer;	gint readbytes;	qq_data *qd = (qq_data *) gc->proto_data;	PurpleXfer *xfer = qd->xfer;	ft_info *info = (ft_info *) xfer->data;	purple_debug(PURPLE_DEBUG_INFO, "QQ", 			"receiving %dth fragment ack, slide window status %o, max_fragment_index %d\n", 			fragment_index, info->window, info->max_fragment_index);	if (fragment_index < info->max_fragment_index || 			fragment_index >= info->max_fragment_index + sizeof(info->window)) {		purple_debug(PURPLE_DEBUG_INFO, "QQ", "duplicate %dth fragment, drop it!\n", fragment_index+1);		return;	}	mask = 0x1 << (fragment_index % sizeof(info->window));	if ((info->window & mask) == 0)	{		info->window |= mask;		if (fragment_index + 1 != info->fragment_num) {			xfer->bytes_sent += info->fragment_len;		} else {			xfer->bytes_sent += purple_xfer_get_size(xfer) % info->fragment_len;		}		xfer->bytes_remaining = purple_xfer_get_size(xfer) - purple_xfer_get_bytes_sent(xfer);		purple_xfer_update_progress(xfer);		if (purple_xfer_get_bytes_remaining(xfer) <= 0) {			/* We have finished sending the file */			purple_xfer_set_completed(xfer, TRUE);			return;		}		mask = 0x1 << (info->max_fragment_index % sizeof(info->window));		while (info->window & mask)		{			/* move the slide window */			info->window &= ~mask;			buffer = g_newa(guint8, info->fragment_len);			readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + sizeof(info->window), 					info->fragment_len, xfer);			if (readbytes > 0)				_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO,					info->max_fragment_index + sizeof(info->window) + 1, 0, buffer, readbytes);						info->max_fragment_index ++;			if (mask & 0x8000) mask = 0x0001;			else mask = mask << 1;		}	}	purple_debug(PURPLE_DEBUG_INFO, "QQ", 			"procceed %dth fragment ack, slide window status %o, max_fragment_index %d\n", 			fragment_index, info->window, info->max_fragment_index);}static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, guint8 *cursor,		gint len, guint32 to_uid){	guint16 packet_type;	guint16 packet_seq;	guint8 sub_type;	guint32 fragment_index;	guint16 fragment_len;	guint32 fragment_offset;	qq_data *qd = (qq_data *) gc->proto_data;	ft_info *info = (ft_info *) qd->xfer->data;		cursor += 1; /* skip an unknown byte */	read_packet_w(data, &cursor, len, &packet_type);	switch(packet_type)	{		case QQ_FILE_CMD_FILE_OP:			read_packet_w(data, &cursor, len, &packet_seq);			read_packet_b(data, &cursor, len, &sub_type);			switch (sub_type)			{				case QQ_FILE_BASIC_INFO:					cursor += 4;	/* file length, we have already known it from xfer */					read_packet_dw(data, &cursor, len, &info->fragment_num);					read_packet_dw(data, &cursor, len, &info->fragment_len);					/* FIXME: We must check the md5 here, if md5 doesn't match					 * we will ignore the packet or send sth as error number					 */					info->max_fragment_index = 0;					info->window = 0;					purple_debug(PURPLE_DEBUG_INFO, "QQ", 							"start receiving data, %d fragments with %d length each\n",							info->fragment_num, info->fragment_len);					_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type,							0, 0, NULL, 0);					break;				case QQ_FILE_DATA_INFO:					read_packet_dw(data, &cursor, len, &fragment_index);					read_packet_dw(data, &cursor, len, &fragment_offset);					read_packet_w(data, &cursor, len, &fragment_len);					purple_debug(PURPLE_DEBUG_INFO, "QQ", 							"received %dth fragment with length %d, offset %d\n",							fragment_index, fragment_len, fragment_offset);										_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type,							fragment_index, packet_seq, NULL, 0);					_qq_recv_file_progess(gc, cursor, fragment_len, fragment_index, fragment_offset);					break;				case QQ_FILE_EOF:					purple_debug(PURPLE_DEBUG_INFO, "QQ", "end of receiving\n");					_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type,						0, 0, NULL, 0);					break;			}			break;		case QQ_FILE_CMD_FILE_OP_ACK:			read_packet_w(data, &cursor, len, &packet_seq);			read_packet_b(data, &cursor, len, &sub_type);			switch (sub_type)			{				case QQ_FILE_BASIC_INFO:					info->max_fragment_index = 0;					info->window = 0;					/* It is ready to send file data */					_qq_send_file_progess(gc);					break;				case QQ_FILE_DATA_INFO:					read_packet_dw(data, &cursor, len, &fragment_index);					_qq_update_send_progess(gc, fragment_index);					if (purple_xfer_is_completed(qd->xfer))						_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_EOF, 0, 0, NULL, 0);				/*	else						_qq_send_file_progess(gc); */					break;				case QQ_FILE_EOF:					/* FIXME: OK, we can end the connection successfully */										_qq_send_file_data_packet(gc, QQ_FILE_EOF, 0, 0, 0, NULL, 0);					purple_xfer_set_completed(qd->xfer, TRUE);					break;			}			break;		case QQ_FILE_EOF:			_qq_send_file_data_packet(gc, QQ_FILE_EOF, 0, 0, 0, NULL, 0);			purple_xfer_set_completed(qd->xfer, TRUE);			purple_xfer_end(qd->xfer);			break;		case QQ_FILE_BASIC_INFO:			purple_debug(PURPLE_DEBUG_INFO, "QQ", "here\n");			_qq_send_file_data_packet(gc, QQ_FILE_DATA_INFO, 0, 0, 0, NULL, 0);			break;		default:			purple_debug(PURPLE_DEBUG_INFO, "QQ", "_qq_process_recv_file_data: unknown packet type [%d]\n",					packet_type);			break;	}}void qq_process_recv_file(PurpleConnection *gc, guint8 *data, gint len){	guint8 *cursor;	qq_file_header fh;	qq_data *qd;	qd = (qq_data *) gc->proto_data;	cursor = data;	_qq_get_file_header(data, &cursor, len, &fh);	switch (fh.tag) {		case QQ_FILE_CONTROL_PACKET_TAG:			_qq_process_recv_file_ctl_packet(gc, data, cursor, len, &fh);			break;		case QQ_FILE_DATA_PACKET_TAG:			_qq_process_recv_file_data(gc, data, cursor, len, fh.sender_uid);			break;		default:			purple_debug(PURPLE_DEBUG_INFO, "QQ", "unknown packet tag");	}}

⌨️ 快捷键说明

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