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

📄 peer.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (read < 0)	{		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))			/* No worries */			return;		peer_connection_destroy(conn,				OSCAR_DISCONNECT_LOST_CONNECTION, strerror(errno));		return;	}	conn->lastactivity = time(NULL);	conn->buffer_incoming.offset += read;	if (conn->buffer_incoming.offset < conn->buffer_incoming.len)		/* Waiting for more data to arrive */		return;	/* We have a complete ODC/OFT frame!  Handle it and continue reading */	byte_stream_rewind(&conn->buffer_incoming);	if (conn->type == OSCAR_CAPABILITY_DIRECTIM)	{		peer_odc_recv_frame(conn, &conn->buffer_incoming);	}	else if (conn->type == OSCAR_CAPABILITY_SENDFILE)	{		peer_oft_recv_frame(conn, &conn->buffer_incoming);	}	g_free(conn->buffer_incoming.data);	conn->buffer_incoming.data = NULL;	conn->header_received = 0;}/*******************************************************************//* End code for receiving data on a peer connection                *//*******************************************************************//*******************************************************************//* Begin code for sending data on a peer connection                *//*******************************************************************/static voidsend_cb(gpointer data, gint source, PurpleInputCondition cond){	PeerConnection *conn;	gsize writelen;	ssize_t wrotelen;	conn = data;	writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing);	if (writelen == 0)	{		purple_input_remove(conn->watcher_outgoing);		conn->watcher_outgoing = 0;		return;	}	wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);	if (wrotelen <= 0)	{		if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))			/* No worries */			return;		if (conn->ready)		{			purple_input_remove(conn->watcher_outgoing);			conn->watcher_outgoing = 0;			close(conn->fd);			conn->fd = -1;			peer_connection_schedule_destroy(conn,					OSCAR_DISCONNECT_LOST_CONNECTION, NULL);		}		else		{			/*			 * This could happen when unable to send a negotiation			 * frame to a peer proxy server.			 */			peer_connection_trynext(conn);		}		return;	}	purple_circ_buffer_mark_read(conn->buffer_outgoing, wrotelen);	conn->lastactivity = time(NULL);}/** * This should be called by OFT/ODC code to send a standard OFT or ODC * frame across the peer connection along with some payload data.  Or * maybe a file.  Anything, really. */voidpeer_connection_send(PeerConnection *conn, ByteStream *bs){	/* Add everything to our outgoing buffer */	purple_circ_buffer_append(conn->buffer_outgoing, bs->data, bs->len);	/* If we haven't already started writing stuff, then start the cycle */	if ((conn->watcher_outgoing == 0) && (conn->fd >= 0))	{		conn->watcher_outgoing = purple_input_add(conn->fd,				PURPLE_INPUT_WRITE, send_cb, conn);		send_cb(conn, conn->fd, 0);	}}/*******************************************************************//* End code for sending data on a peer connection                  *//*******************************************************************//*******************************************************************//* Begin code for establishing a peer connection                   *//*******************************************************************/voidpeer_connection_finalize_connection(PeerConnection *conn){	conn->watcher_incoming = purple_input_add(conn->fd,			PURPLE_INPUT_READ, peer_connection_recv_cb, conn);	if (conn->type == OSCAR_CAPABILITY_DIRECTIM)	{		/*		 * If we are connecting to them then send our cookie so they		 * can verify who we are.  Note: This doesn't seem to be		 * necessary, but it also doesn't seem to hurt.		 */		if (!(conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING))			peer_odc_send_cookie(conn);	}	else if (conn->type == OSCAR_CAPABILITY_SENDFILE)	{		if (purple_xfer_get_type(conn->xfer) == PURPLE_XFER_SEND)		{			peer_oft_send_prompt(conn);		}	}	/*	 * Tell the remote user that we're connected (which may also imply	 * that we've accepted their request).	 */	if (!(conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING))		aim_im_sendch2_connected(conn);}/** * We tried to make an outgoing connection to a remote user.  It * either connected or failed to connect. */static voidpeer_connection_common_established_cb(gpointer data, gint source, const gchar *error_message, gboolean verified){	PeerConnection *conn;	conn = data;	if (verified)		conn->verified_connect_data = NULL;	else		conn->client_connect_data = NULL;	if (source < 0)	{		if ((conn->verified_connect_data == NULL) &&			(conn->client_connect_data == NULL))		{			/* Our parallel connection attemps have both failed. */			peer_connection_trynext(conn);		}		return;	}	purple_timeout_remove(conn->connect_timeout_timer);	conn->connect_timeout_timer = 0;	if (conn->client_connect_data != NULL)	{		purple_proxy_connect_cancel(conn->client_connect_data);		conn->client_connect_data = NULL;	}	if (conn->verified_connect_data != NULL)	{		purple_proxy_connect_cancel(conn->verified_connect_data);		conn->verified_connect_data = NULL;	}	conn->fd = source;	peer_connection_finalize_connection(conn);}static voidpeer_connection_verified_established_cb(gpointer data, gint source, const gchar *error_message){	peer_connection_common_established_cb(data, source, error_message, TRUE);}static voidpeer_connection_client_established_cb(gpointer data, gint source, const gchar *error_message){	peer_connection_common_established_cb(data, source, error_message, FALSE);}/** * This is the watcher callback for any listening socket that is * waiting for a peer to connect.  When a peer connects we set the * input watcher to start reading data from the peer. * * To make sure that the connection is with the intended person and * not with a malicious middle man, we don't send anything until we've * received a peer frame from the remote user and have verified that * the cookie in the peer frame matches the cookie that was exchanged * in the channel 2 ICBM. */voidpeer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond){	PeerConnection *conn;	OscarData *od;	PurpleConnection *gc;	struct sockaddr addr;	socklen_t addrlen = sizeof(addr);	conn = data;	od = conn->od;	gc = od->gc;	purple_debug_info("oscar", "Accepting connection on listener socket.\n");	conn->fd = accept(conn->listenerfd, &addr, &addrlen);	if (conn->fd < 0)	{		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))			/* No connection yet--no worries */			/* TODO: Hmm, but they SHOULD be connected if we're here, right? */			return;		peer_connection_trynext(conn);		return;	}	if ((addr.sa_family != PF_INET) && (addr.sa_family != PF_INET6))	{		/* Invalid connection type?!  Continue waiting. */		close(conn->fd);		return;	}	fcntl(conn->fd, F_SETFL, O_NONBLOCK);	purple_input_remove(conn->watcher_incoming);	peer_connection_finalize_connection(conn);}/** * We've just opened a listener socket, so we send the remote * user an ICBM and ask them to connect to us. */static voidpeer_connection_establish_listener_cb(int listenerfd, gpointer data){	PeerConnection *conn;	OscarData *od;	PurpleConnection *gc;	PurpleAccount *account;	PurpleConversation *conv;	char *tmp;	FlapConnection *bos_conn;	const char *listener_ip;	unsigned short listener_port;	conn = data;	conn->listen_data = NULL;	if (listenerfd < 0)	{		/* Could not open listener socket */		peer_connection_trynext(conn);		return;	}	od = conn->od;	gc = od->gc;	account = purple_connection_get_account(gc);	conn->listenerfd = listenerfd;	/* Send the "please connect to me!" ICBM */	bos_conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);	if (bos_conn == NULL)	{		/* Not good */		peer_connection_trynext(conn);		return;	}	listener_ip = purple_network_get_my_ip(bos_conn->fd);	listener_port = purple_network_get_port_from_fd(conn->listenerfd);	if (conn->type == OSCAR_CAPABILITY_DIRECTIM)	{		aim_im_sendch2_odc_requestdirect(od,				conn->cookie, conn->sn, purple_network_ip_atoi(listener_ip),				listener_port, ++conn->lastrequestnumber);		/* Print a message to a local conversation window */		conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->sn);		tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for "				"Direct IM."), conn->sn, listener_ip, listener_port);		purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));		g_free(tmp);	}	else if (conn->type == OSCAR_CAPABILITY_SENDFILE)	{		aim_im_sendch2_sendfile_requestdirect(od,				conn->cookie, conn->sn,				purple_network_ip_atoi(listener_ip),				listener_port, ++conn->lastrequestnumber,				(const gchar *)conn->xferdata.name,				conn->xferdata.size, conn->xferdata.totfiles);	}}/** * This is a callback function used when we're connecting to a peer * using either the client IP or the verified IP and the connection * took longer than 5 seconds to complete.  We do this because * waiting for the OS to time out the connection attempt is not * practical--the default timeout on many OSes can be 3 minutes or * more, and users are impatient. * * Worst case scenario: the user is connected to the Internet using * a modem with severe lag.  The peer connections fail and Purple falls * back to using a proxied connection.  The lower bandwidth * limitations imposed by the proxied connection won't matter because * the user is using a modem. * * I suppose this line of thinking is discriminatory against people * with very high lag but decent throughput who are transferring * large files.  But we don't care about those people. * * I (Sean) changed the timeout from 15 to 5 seconds, as 60 seconds is * too long for a user to wait to send a file. I'm also parallelizing * requests when possible. The longest we should have to wait now is 10 * seconds. We shouldn't make it shorter than this. */static gbooleanpeer_connection_tooktoolong(gpointer data){	PeerConnection *conn;	conn = data;	purple_debug_info("oscar", "Peer connection timed out after 5 seconds.  "			"Trying next method...\n");	peer_connection_trynext(conn);

⌨️ 快捷键说明

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