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

📄 oft.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	peer_oft_copy_xfer_data(conn, frame);	peer_oft_send_ack(conn);	/* Remove our watchers and use the file transfer watchers in the core */	purple_input_remove(conn->watcher_incoming);	conn->watcher_incoming = 0;	conn->sending_data_timer = purple_timeout_add(100,			start_transfer_when_done_sending_data, conn);}/** * We are sending a file to someone else.  They have just acknowledged our * prompt, so we want to start sending data like there's no tomorrow. */static voidpeer_oft_recv_frame_ack(PeerConnection *conn, OftFrame *frame){	if (memcmp(conn->cookie, frame->cookie, 8) != 0)	{		purple_debug_info("oscar", "Received an incorrect cookie.  "				"Closing connection.\n");		peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL);		return;	}	/* Remove our watchers and use the file transfer watchers in the core */	purple_input_remove(conn->watcher_incoming);	conn->watcher_incoming = 0;	conn->sending_data_timer = purple_timeout_add(100,			start_transfer_when_done_sending_data, conn);}static gbooleanpeer_oft_recv_frame_resume_checksum_calculated_cb(gpointer data){	ChecksumData *checksum_data;	PeerConnection *conn;	checksum_data = data;	conn = checksum_data->conn;	/* Check the checksums here.  If not match, don't allow resume */	if (checksum_data->checksum != conn->xferdata.recvcsum || checksum_data->total != conn->xferdata.nrecvd)	{		/* Reset internal structure */		conn->xferdata.recvcsum = 0xffff0000;		conn->xferdata.rfrcsum = 0xffff0000;		conn->xferdata.nrecvd = 0;	}	else		/* Accept the change */		purple_xfer_set_bytes_sent(checksum_data->xfer, conn->xferdata.nrecvd);	peer_oft_send_resume_accept(conn);	return FALSE;}/** * We are sending a file to someone else.  They have just acknowledged our * prompt and are asking to resume, so we accept their resume and await * a resume ack. */static voidpeer_oft_recv_frame_resume(PeerConnection *conn, OftFrame *frame){	if (memcmp(conn->cookie, frame->cookie, 8) != 0)	{		purple_debug_info("oscar", "Received an incorrect cookie.  "				"Closing connection.\n");		peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL);		return;	}	/* Copy resume data into internal structure */	conn->xferdata.recvcsum = frame->recvcsum;	conn->xferdata.rfrcsum = frame->rfrcsum;	conn->xferdata.nrecvd = frame->nrecvd;	peer_oft_checksum_file(conn, conn->xfer,			peer_oft_recv_frame_resume_checksum_calculated_cb,			frame->nrecvd);}/* * We just sent a file to someone.  They said they got it and everything, * so we can close our direct connection and what not. */static voidpeer_oft_recv_frame_done(PeerConnection *conn, OftFrame *frame){	purple_input_remove(conn->watcher_incoming);	conn->watcher_incoming = 0;	conn->xfer->fd = conn->fd;	conn->fd = -1;	conn->disconnect_reason = OSCAR_DISCONNECT_DONE;	peer_connection_schedule_destroy(conn, conn->disconnect_reason, NULL);}/** * Handle an incoming OftFrame.  If there is a payload associated * with this frame, then we remove the old watcher and add the * OFT watcher to read in the payload. */voidpeer_oft_recv_frame(PeerConnection *conn, ByteStream *bs){	OftFrame frame;	frame.type = byte_stream_get16(bs);	byte_stream_getrawbuf(bs, frame.cookie, 8);	frame.encrypt = byte_stream_get16(bs);	frame.compress = byte_stream_get16(bs);	frame.totfiles = byte_stream_get16(bs);	frame.filesleft = byte_stream_get16(bs);	frame.totparts = byte_stream_get16(bs);	frame.partsleft = byte_stream_get16(bs);	frame.totsize = byte_stream_get32(bs);	frame.size = byte_stream_get32(bs);	frame.modtime = byte_stream_get32(bs);	frame.checksum = byte_stream_get32(bs);	frame.rfrcsum = byte_stream_get32(bs);	frame.rfsize = byte_stream_get32(bs);	frame.cretime = byte_stream_get32(bs);	frame.rfcsum = byte_stream_get32(bs);	frame.nrecvd = byte_stream_get32(bs);	frame.recvcsum = byte_stream_get32(bs);	byte_stream_getrawbuf(bs, frame.idstring, 32);	frame.flags = byte_stream_get8(bs);	frame.lnameoffset = byte_stream_get8(bs);	frame.lsizeoffset = byte_stream_get8(bs);	byte_stream_getrawbuf(bs, frame.dummy, 69);	byte_stream_getrawbuf(bs, frame.macfileinfo, 16);	frame.nencode = byte_stream_get16(bs);	frame.nlanguage = byte_stream_get16(bs);	frame.name_length = bs->len - 186;	frame.name = byte_stream_getraw(bs, frame.name_length);	purple_debug_info("oscar", "Incoming OFT frame from %s with "			"type=0x%04x\n", conn->sn, frame.type);	/* TODOFT: peer_oft_dirconvert_fromstupid(frame->name); */	switch(frame.type)	{		case PEER_TYPE_PROMPT:			peer_oft_recv_frame_prompt(conn, &frame);			break;		case PEER_TYPE_ACK:		case PEER_TYPE_RESUMEACK:			peer_oft_recv_frame_ack(conn, &frame);			break;		case PEER_TYPE_RESUME:			peer_oft_recv_frame_resume(conn, &frame);			break;		case PEER_TYPE_DONE:			peer_oft_recv_frame_done(conn, &frame);			break;		default:			break;	}	g_free(frame.name);}/*******************************************************************//* Begin PurpleXfer callbacks for use when receiving a file          *//*******************************************************************/voidpeer_oft_recvcb_init(PurpleXfer *xfer){	PeerConnection *conn;	conn = xfer->data;	conn->flags |= PEER_CONNECTION_FLAG_APPROVED;	peer_connection_trynext(conn);}voidpeer_oft_recvcb_end(PurpleXfer *xfer){	PeerConnection *conn;	conn = xfer->data;	/* Tell the other person that we've received everything */	conn->fd = conn->xfer->fd;	conn->xfer->fd = -1;	peer_oft_send_done(conn);	conn->disconnect_reason = OSCAR_DISCONNECT_DONE;	conn->sending_data_timer = purple_timeout_add(100,			destroy_connection_when_done_sending_data, conn);}voidpeer_oft_recvcb_ack_recv(PurpleXfer *xfer, const guchar *buffer, size_t size){	PeerConnection *conn;	/* Update our rolling checksum.  Like Walmart, yo. */	conn = xfer->data;	conn->xferdata.recvcsum = peer_oft_checksum_chunk(buffer,			size, conn->xferdata.recvcsum, purple_xfer_get_bytes_sent(xfer) & 1);}/*******************************************************************//* End PurpleXfer callbacks for use when receiving a file            *//*******************************************************************//*******************************************************************//* Begin PurpleXfer callbacks for use when sending a file            *//*******************************************************************/static gbooleanpeer_oft_checksum_calculated_cb(gpointer data){	ChecksumData *checksum_data;	PeerConnection *conn;	checksum_data = data;	conn = checksum_data->conn;	conn->xferdata.checksum = checksum_data->checksum;	/* Start the connection process */	peer_connection_trynext(checksum_data->conn);	return FALSE;}voidpeer_oft_sendcb_init(PurpleXfer *xfer){	PeerConnection *conn;	size_t size;	conn = xfer->data;	conn->flags |= PEER_CONNECTION_FLAG_APPROVED;	/* Make sure the file size can be represented in 32 bits */	size = purple_xfer_get_size(xfer);	if (size > G_MAXUINT32)	{		gchar *tmp, *size1, *size2;		size1 = purple_str_size_to_units(size);		size2 = purple_str_size_to_units(G_MAXUINT32);		tmp = g_strdup_printf(_("File %s is %s, which is larger than "				"the maximum size of %s."),				xfer->local_filename, size1, size2);		purple_xfer_error(purple_xfer_get_type(xfer),				purple_xfer_get_account(xfer), xfer->who, tmp);		g_free(size1);		g_free(size2);		g_free(tmp);		peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);		return;	}	/* Keep track of file transfer info */	conn->xferdata.totfiles = 1;	conn->xferdata.filesleft = 1;	conn->xferdata.totparts = 1;	conn->xferdata.partsleft = 1;	conn->xferdata.totsize = size;	conn->xferdata.size = size;	conn->xferdata.checksum = 0xffff0000;	conn->xferdata.rfrcsum = 0xffff0000;	conn->xferdata.rfcsum = 0xffff0000;	conn->xferdata.recvcsum = 0xffff0000;	strncpy((gchar *)conn->xferdata.idstring, "OFT_Windows ICBMFT V1.1 32", 31);	conn->xferdata.modtime = 0;	conn->xferdata.cretime = 0;	xfer->filename = g_path_get_basename(xfer->local_filename);	conn->xferdata.name = (guchar *)g_strdup(xfer->filename);	conn->xferdata.name_length = strlen(xfer->filename);	peer_oft_checksum_file(conn, xfer,			peer_oft_checksum_calculated_cb, G_MAXUINT32);}/* * AIM file transfers aren't really meant to be thought * of as a transferring just a single file.  The rendezvous * establishes a connection between two computers, and then * those computers can use the same connection for transferring * multiple files.  So we don't want the Purple core up and closing * the socket all willy-nilly.  We want to do that in the oscar * prpl, whenever one side or the other says they're finished * using the connection.  There might be a better way to intercept * the socket from the core... */voidpeer_oft_sendcb_ack(PurpleXfer *xfer, const guchar *buffer, size_t size){	PeerConnection *conn;	conn = xfer->data;	/*	 * If we're done sending, intercept the socket from the core ft code	 * and wait for the other guy to send the "done" OFT packet.	 */	if (purple_xfer_get_bytes_remaining(xfer) <= 0)	{		purple_input_remove(xfer->watcher);		conn->fd = xfer->fd;		xfer->fd = -1;		conn->watcher_incoming = purple_input_add(conn->fd,				PURPLE_INPUT_READ, peer_connection_recv_cb, conn);	}}/*******************************************************************//* End PurpleXfer callbacks for use when sending a file              *//*******************************************************************//*******************************************************************//* Begin PurpleXfer callbacks for use when sending and receiving     *//*******************************************************************/voidpeer_oft_cb_generic_cancel(PurpleXfer *xfer){	PeerConnection *conn;	conn = xfer->data;	if (conn == NULL)		return;	peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);}/*******************************************************************//* End PurpleXfer callbacks for use when sending and receiving       *//*******************************************************************/#ifdef TODOFT/* * This little area in oscar.c is the nexus of file transfer code, * so I wrote a little explanation of what happens.  I am such a * ninja. * * The series of events for a file send is: *  -Create xfer and call purple_xfer_request (this happens in oscar_ask_sendfile) *  -User chooses a file and oscar_xfer_init is called.  It establishes a *   listening socket, then asks the remote user to connect to us (and *   gives them the file name, port, IP, etc.) *  -They connect to us and we send them an PEER_TYPE_PROMPT (this happens *   in peer_oft_recv_frame_established) *  -They send us an PEER_TYPE_ACK and then we start sending data *  -When we finish, they send us an PEER_TYPE_DONE and they close the *   connection. *  -We get drunk because file transfer kicks ass. * * The series of events for a file receive is: *  -Create xfer and call purple_xfer request (this happens in incomingim_chan2) *  -Purple user selects file to name and location to save file to and *   oscar_xfer_init is called *  -It connects to the remote user using the IP they gave us earlier *  -After connecting, they send us an PEER_TYPE_PROMPT.  In reply, we send *   them an PEER_TYPE_ACK. *  -They begin to send us lots of raw data. *  -When they finish sending data we send an PEER_TYPE_DONE and then close *   the connection. * * Update August 2005: * The series of events for transfers has been seriously complicated by the addition * of transfer redirects and proxied connections. I could throw a whole lot of words * at trying to explain things here, but it probably wouldn't do much good. To get * a better idea of what happens, take a look at the diagrams and documentation * from my Summer of Code project. -- Jonathan Clark *//** * Convert the directory separator from / (0x2f) to ^A (0x01) * * @param name The filename to convert. */static voidpeer_oft_dirconvert_tostupid(char *name){	while (name[0]) {		if (name[0] == 0x01)			name[0] = G_DIR_SEPARATOR;		name++;	}}/** * Convert the directory separator from ^A (0x01) to / (0x2f) * * @param name The filename to convert. */static voidpeer_oft_dirconvert_fromstupid(char *name){	while (name[0]) {		if (name[0] == G_DIR_SEPARATOR)			name[0] = 0x01;		name++;	}}#endif

⌨️ 快捷键说明

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