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

📄 send_file.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file send_file.c * * purple * * Purple 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 "send_file.h"#include "debug.h"#include "network.h"#include "notify.h"#include "buddy_status.h"#include "crypt.h"#include "file_trans.h"#include "header_info.h"#include "im.h"#include "keep_alive.h"#include "packet_parse.h"#include "qq.h"#include "send_core.h"#include "utils.h"enum{	QQ_FILE_TRANS_REQ = 0x0035,	QQ_FILE_TRANS_ACC_UDP = 0x0037,	QQ_FILE_TRANS_ACC_TCP = 0x0003,	QQ_FILE_TRANS_DENY_UDP = 0x0039,	QQ_FILE_TRANS_DENY_TCP = 0x0005,	QQ_FILE_TRANS_NOTIFY = 0x003b,	QQ_FILE_TRANS_NOTIFY_ACK = 0x003c,	QQ_FILE_TRANS_CANCEL = 0x0049,	QQ_FILE_TRANS_PASV = 0x003f};static int _qq_in_same_lan(ft_info *info){	if (info->remote_internet_ip == info->local_internet_ip) return 1;	purple_debug(PURPLE_DEBUG_INFO, "QQ", 			"Not in the same LAN, remote internet ip[%x], local internet ip[%x]\n",  			info->remote_internet_ip			, info->local_internet_ip);	return 0;}static int _qq_xfer_init_udp_channel(ft_info *info){	struct sockaddr_in sin;	memset(&sin, 0, sizeof(sin));	sin.sin_family = AF_INET;	if (!_qq_in_same_lan(info)) {		sin.sin_port = g_htons(info->remote_major_port);		sin.sin_addr.s_addr = g_htonl(info->remote_internet_ip);	} else {		sin.sin_port = g_htons(info->remote_minor_port);		sin.sin_addr.s_addr = g_htonl(info->remote_real_ip);	}	return 0;}/* these 2 functions send and recv buffer from/to UDP channel */static ssize_t _qq_xfer_udp_recv(guint8 *buf, size_t len, PurpleXfer *xfer){	struct sockaddr_in sin;	socklen_t sinlen;	ft_info *info;	gint r;	info = (ft_info *) xfer->data;	sinlen = sizeof(sin);	r = recvfrom(info->recv_fd, buf, len, 0, (struct sockaddr *) &sin, &sinlen);	purple_debug(PURPLE_DEBUG_INFO, "QQ", 			"==> recv %d bytes from File UDP Channel, remote ip[%s], remote port[%d]\n",			r, inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port));	return r;}/*static ssize_t _qq_xfer_udp_send(const char *buf, size_t len, PurpleXfer *xfer){	ft_info *info;	info = (ft_info *) xfer->data;	return send(info->sender_fd, buf, len, 0);}*/static ssize_t _qq_xfer_udp_send(const guint8 *buf, size_t len, PurpleXfer *xfer){	struct sockaddr_in sin;	ft_info *info;	info = (ft_info *) xfer->data;	memset(&sin, 0, sizeof(sin));	sin.sin_family = AF_INET;	if (!_qq_in_same_lan(info)) {		sin.sin_port = g_htons(info->remote_major_port);		sin.sin_addr.s_addr = g_htonl(info->remote_internet_ip);	} else if (info->use_major) {		sin.sin_port = g_htons(info->remote_major_port);		sin.sin_addr.s_addr = g_htonl(info->remote_real_ip);	} else {		sin.sin_port = g_htons(info->remote_minor_port);		sin.sin_addr.s_addr = g_htonl(info->remote_real_ip);	}	purple_debug(PURPLE_DEBUG_INFO, "QQ", "sending to channel: %d.%d.%d.%d:%d\n",			sin.sin_addr.s_addr & 0xff,			(sin.sin_addr.s_addr >> 8) & 0xff,			(sin.sin_addr.s_addr >> 16) & 0xff,			sin.sin_addr.s_addr >> 24,			g_ntohs(sin.sin_port)		  );	return sendto(info->sender_fd, buf, len, 0, (struct sockaddr *) &sin, sizeof(sin));}/* user-defined functions for purple_xfer_read and purple_xfer_write *//*static ssize_t _qq_xfer_read(char **buf, PurpleXfer *xfer){	*buf = g_newa(char, QQ_FILE_FRAGMENT_MAXLEN + 100);	return _qq_xfer_udp_recv(*buf, QQ_FILE_FRAGMENT_MAXLEN + 100, xfer);}*/gssize _qq_xfer_write(const guint8 *buf, size_t len, PurpleXfer *xfer){	return _qq_xfer_udp_send(buf, len, xfer);}static void _qq_xfer_recv_packet(gpointer data, gint source, PurpleInputCondition condition){	PurpleXfer *xfer = (PurpleXfer *) data;	PurpleAccount *account = purple_xfer_get_account(xfer);	PurpleConnection *gc = purple_account_get_connection(account);	guint8 *buf;	gint size;	/* FIXME: It seems that the transfer never use a packet	 * larger than 1500 bytes, so if it happened to be a	 * larger packet, either error occured or protocol should	 * be modified	 */	ft_info *info;	info = xfer->data;	g_return_if_fail (source == info->recv_fd);	buf = g_newa(guint8, 1500);	size = _qq_xfer_udp_recv(buf, 1500, xfer);	qq_process_recv_file(gc, buf, size);}/* start file transfer process *//*static void _qq_xfer_send_start (PurpleXfer *xfer){	PurpleAccount *account;	PurpleConnection *gc;	ft_info *info;	account = purple_xfer_get_account(xfer);	gc = purple_account_get_connection(account);	info = (ft_info *) xfer->data;}*//*static void _qq_xfer_send_ack (PurpleXfer *xfer, const char *buffer, size_t len){	PurpleAccount *account;	PurpleConnection *gc;	account = purple_xfer_get_account(xfer);	gc = purple_account_get_connection(account);	qq_process_recv_file(gc, (guint8 *) buffer, len);}*//*static void _qq_xfer_recv_start(PurpleXfer *xfer){}*/static void _qq_xfer_end(PurpleXfer *xfer){	ft_info *info;	g_return_if_fail(xfer != NULL && xfer->data != NULL);	info = (ft_info *) xfer->data;	qq_xfer_close_file(xfer);	if (info->dest_fp != NULL) {		fclose(info->dest_fp);		purple_debug(PURPLE_DEBUG_INFO, "QQ", "file closed\n");	}	if (info->major_fd != 0) {		close(info->major_fd);		purple_debug(PURPLE_DEBUG_INFO, "QQ", "major port closed\n");	}	if (info->minor_fd != 0) {		close(info->minor_fd);		purple_debug(PURPLE_DEBUG_INFO, "QQ", "minor port closed\n");	}	/*	if (info->buffer != NULL) {		munmap(info->buffer, purple_xfer_get_size(xfer));		purple_debug(PURPLE_DEBUG_INFO, "QQ", "file mapping buffer is freed.\n");	}	*/	g_free(info);}static void qq_show_conn_info(ft_info *info){	gchar *internet_ip_str, *real_ip_str;	guint32 ip;	ip = g_htonl(info->remote_real_ip);	real_ip_str = gen_ip_str((guint8 *) &ip);	ip = g_htonl(info->remote_internet_ip);	internet_ip_str = gen_ip_str((guint8 *) &ip);	purple_debug(PURPLE_DEBUG_INFO, "QQ", "remote internet ip[%s:%d], major port[%d], real ip[%s], minor port[%d]\n",			internet_ip_str, info->remote_internet_port,			info->remote_major_port, real_ip_str, info->remote_minor_port		  );	g_free(real_ip_str);	g_free(internet_ip_str);}void qq_get_conn_info(guint8 *data, guint8 **cursor, gint data_len, ft_info *info){	read_packet_data(data, cursor, data_len, info->file_session_key, 16);	*cursor += 30;	read_packet_b(data, cursor, data_len, &info->conn_method);	read_packet_dw(data, cursor, data_len, &info->remote_internet_ip);	read_packet_w(data, cursor, data_len, &info->remote_internet_port);	read_packet_w(data, cursor, data_len, &info->remote_major_port);	read_packet_dw(data, cursor, data_len, &info->remote_real_ip);	read_packet_w(data, cursor, data_len, &info->remote_minor_port);	qq_show_conn_info(info);}gint qq_fill_conn_info(guint8 *raw_data, guint8 **cursor, ft_info *info){	gint bytes;	bytes = 0;	/* 064: connection method, UDP 0x00, TCP 0x03 */	bytes += create_packet_b (raw_data, cursor, info->conn_method);	/* 065-068: outer ip address of sender (proxy address) */	bytes += create_packet_dw (raw_data, cursor, info->local_internet_ip);	/* 069-070: sender port */	bytes += create_packet_w (raw_data, cursor, info->local_internet_port);	/* 071-072: the first listening port(TCP doesn't have this part) */	bytes += create_packet_w (raw_data, cursor, info->local_major_port);	/* 073-076: real ip */	bytes += create_packet_dw (raw_data, cursor, info->local_real_ip);	/* 077-078: the second listening port */	bytes += create_packet_w (raw_data, cursor, info->local_minor_port);	return bytes;}/* fill in the common information of file transfer */static gint _qq_create_packet_file_header(guint8 *raw_data, guint8 **cursor, guint32 to_uid, guint16 message_type, qq_data *qd, gboolean seq_ack){	gint bytes;	time_t now;	guint16 seq;	ft_info *info;	bytes = 0;	now = time(NULL);	if (!seq_ack) seq = qd->send_seq;	else {		info = (ft_info *) qd->xfer->data;		seq = info->send_seq;	}	/* 000-003: receiver uid */	bytes += create_packet_dw (raw_data, cursor, qd->uid);	/* 004-007: sender uid */	bytes += create_packet_dw (raw_data, cursor, to_uid);	/* 008-009: sender client version */	bytes += create_packet_w (raw_data, cursor, QQ_CLIENT);	/* 010-013: receiver uid */	bytes += create_packet_dw (raw_data, cursor, qd->uid);	/* 014-017: sender uid */	bytes += create_packet_dw (raw_data, cursor, to_uid);	/* 018-033: md5 of (uid+session_key) */	bytes += create_packet_data (raw_data, cursor, qd->session_md5, 16);	/* 034-035: message type */	bytes += create_packet_w (raw_data, cursor, message_type);	/* 036-037: sequence number */	bytes += create_packet_w (raw_data, cursor, seq);	/* 038-041: send time */	bytes += create_packet_dw (raw_data, cursor, (guint32) now);	/* 042-042: always 0x00 */	bytes += create_packet_b (raw_data, cursor, 0x00);	/* 043-043: sender icon */	bytes += create_packet_b (raw_data, cursor, qd->my_icon);	/* 044-046: always 0x00 */	bytes += create_packet_w (raw_data, cursor, 0x0000);	bytes += create_packet_b (raw_data, cursor, 0x00);	/* 047-047: we use font attr */	bytes += create_packet_b (raw_data, cursor, 0x01);	/* 048-051: always 0x00 */	bytes += create_packet_dw (raw_data, cursor, 0x00000000);	/* 052-062: always 0x00 */	bytes += create_packet_dw (raw_data, cursor, 0x00000000);	bytes += create_packet_dw (raw_data, cursor, 0x00000000);	bytes += create_packet_w (raw_data, cursor, 0x0000);	bytes += create_packet_b (raw_data, cursor, 0x00);	/* 063: transfer_type,  0x65: FILE 0x6b: FACE */	bytes += create_packet_b (raw_data, cursor, QQ_FILE_TRANSFER_FILE); /* FIXME */	return bytes;}#if 0in_addr_t get_real_ip(){	char hostname[40];	struct hostent *host;	gethostname(hostname, sizeof(hostname));	host = gethostbyname(hostname);	return *(host->h_addr);}#include <sys/ioctl.h>#include <net/if.h>#define MAXINTERFACES 16in_addr_t get_real_ip(){	int fd, intrface, i;	struct ifconf ifc;	struct ifreq buf[MAXINTERFACES];	in_addr_t ret;	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return 0;	ifc.ifc_len = sizeof(buf);	ifc.ifc_buf = (caddr_t) buf;	if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) < 0) return 0;	intrface = ifc.ifc_len / sizeof(struct ifreq);	for (i = 0; i < intrface; i++) {		/* buf[intrface].ifr_name */		if (ioctl(fd, SIOCGIFADDR, (char *) &buf[i]) >= 0)		{			ret = (((struct sockaddr_in *)(&buf[i].ifr_addr))->sin_addr).s_addr;			if (ret == g_ntohl(0x7f000001)) continue;			return ret;		}	}	return 0;}#endifstatic void _qq_xfer_init_socket(PurpleXfer *xfer){	gint sockfd, listen_port = 0, i; 	socklen_t sin_len;	struct sockaddr_in sin;	ft_info *info;	g_return_if_fail(xfer != NULL);	g_return_if_fail(xfer->data != NULL);	info = (ft_info *) xfer->data;	/* debug 	info->local_real_ip = 0x7f000001;	*/	info->local_real_ip = g_ntohl(inet_addr(purple_network_get_my_ip(-1)));	purple_debug(PURPLE_DEBUG_INFO, "QQ", "local real ip is %x", info->local_real_ip);	for (i = 0; i < 2; i++) {		sockfd = socket(PF_INET, SOCK_DGRAM, 0);		g_return_if_fail(sockfd >= 0);		memset(&sin, 0, sizeof(sin));		sin.sin_family = AF_INET;		sin.sin_port = 0;		sin.sin_addr.s_addr = INADDR_ANY;		sin_len = sizeof(sin);		bind(sockfd, (struct sockaddr *) &sin, sin_len);		getsockname(sockfd, (struct sockaddr *) &sin, &sin_len);		listen_port = g_ntohs(sin.sin_port);		switch (i) {			case 0:				info->local_major_port = listen_port;				info->major_fd = sockfd;				purple_debug(PURPLE_DEBUG_INFO, "QQ", "UDP Major Channel created on port[%d]\n",						info->local_major_port);				break;			case 1:				info->local_minor_port = listen_port;				info->minor_fd = sockfd;				purple_debug(PURPLE_DEBUG_INFO, "QQ", "UDP Minor Channel created on port[%d]\n",						info->local_minor_port);				break;		}	}	if (_qq_in_same_lan(info)) {		info->sender_fd = info->recv_fd = info->minor_fd;	} else {		info->sender_fd = info->recv_fd = info->major_fd;	}/*	xfer->watcher = purple_input_add(info->recv_fd, PURPLE_INPUT_READ, _qq_xfer_recv_packet, xfer); */}/* create the QQ_FILE_TRANS_REQ packet with file infomations */static void _qq_send_packet_file_request (PurpleConnection *gc, guint32 to_uid, gchar *filename, gint filesize){	qq_data *qd;	guint8 *cursor, *raw_data;	gchar *filelen_str;	gint filename_len, filelen_strlen, packet_len, bytes;	ft_info *info;	qd = (qq_data *) gc->proto_data;	info = g_new0(ft_info, 1);	info->to_uid = to_uid;	info->send_seq = qd->send_seq;	info->local_internet_ip = g_ntohl(inet_addr(qd->my_ip));	info->local_internet_port = qd->my_port;	info->local_real_ip = 0x00000000;	info->conn_method = 0x00;	qd->xfer->data = info;	filename_len = strlen(filename);	filelen_str = g_strdup_printf("%d ?ֽ?", filesize);	filelen_strlen = strlen(filelen_str);	packet_len = 82 + filename_len + filelen_strlen;	raw_data = g_newa(guint8, packet_len);	cursor = raw_data;	bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, 			QQ_FILE_TRANS_REQ, qd, FALSE);	bytes += qq_fill_conn_info(raw_data, &cursor, info);	/* 079: 0x20 */	bytes += create_packet_b (raw_data, &cursor, 0x20);	/* 080: 0x1f */	bytes += create_packet_b (raw_data, &cursor, 0x1f);	/* undetermined len: filename */	bytes += create_packet_data (raw_data, &cursor, (guint8 *) filename,				     filename_len);	/* 0x1f */	bytes += create_packet_b (raw_data, &cursor, 0x1f);	/* file length */	bytes += create_packet_data (raw_data, &cursor, (guint8 *) filelen_str,				     filelen_strlen);

⌨️ 快捷键说明

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