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

📄 oscar.c

📁 oscar message protocol stack
💻 C
📖 第 1 页 / 共 5 页
字号:
	aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0);	aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0);	aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0);	conn->status |= AIM_CONN_STATUS_INPROGRESS;	if (gaim_proxy_connect(account, gaim_account_get_string(account, "server", FAIM_LOGIN_SERVER),			  gaim_account_get_int(account, "port", FAIM_LOGIN_PORT),			  oscar_login_connect, gc) < 0) {		gaim_connection_error(gc, _("Couldn't connect to host"));		return;	}	gaim_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS);	ck[0] = 0x5a;}static void oscar_close(GaimConnection *gc) {	OscarData *od = (OscarData *)gc->proto_data;	while (od->oscar_chats) {		struct chat_connection *n = od->oscar_chats->data;		if (n->inpa > 0)			gaim_input_remove(n->inpa);		g_free(n->name);		g_free(n->show);		od->oscar_chats = g_slist_remove(od->oscar_chats, n);		g_free(n);	}	while (od->direct_ims) {		struct oscar_direct_im *n = od->direct_ims->data;		oscar_direct_im_destroy(od, n);	}/* BBB */	while (od->file_transfers) {		GaimXfer *xfer;		xfer = (GaimXfer *)od->file_transfers->data;		gaim_xfer_cancel_local(xfer);	}	while (od->requesticon) {		char *sn = od->requesticon->data;		od->requesticon = g_slist_remove(od->requesticon, sn);		free(sn);	}	g_hash_table_destroy(od->buddyinfo);	while (od->create_rooms) {		struct create_room *cr = od->create_rooms->data;		g_free(cr->name);		od->create_rooms = g_slist_remove(od->create_rooms, cr);		g_free(cr);	}	if (od->email)		g_free(od->email);	if (od->newp)		g_free(od->newp);	if (od->oldp)		g_free(od->oldp);	if (gc->inpa > 0)		gaim_input_remove(gc->inpa);	if (od->cnpa > 0)		gaim_input_remove(od->cnpa);	if (od->paspa > 0)		gaim_input_remove(od->paspa);	if (od->emlpa > 0)		gaim_input_remove(od->emlpa);	if (od->icopa > 0)		gaim_input_remove(od->icopa);	if (od->icontimer > 0)		gaim_timeout_remove(od->icontimer);	if (od->getblisttimer > 0)		gaim_timeout_remove(od->getblisttimer);	if (od->getinfotimer > 0)		gaim_timeout_remove(od->getinfotimer);	aim_session_kill(od->sess);	g_free(od->sess);	od->sess = NULL;	g_free(gc->proto_data);	gc->proto_data = NULL;	gaim_debug_info("oscar", "Signed off.\n");}static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) {	GaimConnection *gc = data;	OscarData *od;	aim_session_t *sess;	aim_conn_t *bosconn;	if (!g_list_find(gaim_connections_get_all(), gc)) {		close(source);		return;	}	od = gc->proto_data;	sess = od->sess;	bosconn = od->conn;		bosconn->fd = source;	if (source < 0) {		gaim_connection_error(gc, _("Could Not Connect"));		return;	}	aim_conn_completeconnect(sess, bosconn);	gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, oscar_callback, bosconn);	gaim_connection_update_progress(gc,			_("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS);	ck[4] = 0x61;}/* BBB *//* * 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 gaim_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 AIM_CB_OFT_PROMPT (this happens  *   in oscar_sendfile_estblsh) *  -They send us an AIM_CB_OFT_ACK and then we start sending data *  -When we finish, they send us an AIM_CB_OFT_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 gaim_xfer request (this happens in incomingim_chan2) *  -Gaim 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 AIM_CB_OFT_PROMPT.  In reply, we send  *   them an AIM_CB_OFT_ACK. *  -They begin to send us lots of raw data. *  -When they finish sending data we send an AIM_CB_OFT_DONE and then close  *   the connection. */static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition);/* * Miscellaneous xfer functions */static GaimXfer *oscar_find_xfer_by_cookie(GSList *fts, const fu8_t *ck){	GaimXfer *xfer;	struct aim_oft_info *oft_info;	while (fts) {		xfer = fts->data;		oft_info = xfer->data;		if (oft_info && !memcmp(ck, oft_info->cookie, 8))			return xfer;		fts = g_slist_next(fts);	}	return NULL;}static GaimXfer *oscar_find_xfer_by_conn(GSList *fts, aim_conn_t *conn){	GaimXfer *xfer;	struct aim_oft_info *oft_info;	while (fts) {		xfer = fts->data;		oft_info = xfer->data;		if (oft_info && (conn == oft_info->conn))			return xfer;		fts = g_slist_next(fts);	}	return NULL;}static void oscar_xfer_end(GaimXfer *xfer){	struct aim_oft_info *oft_info = xfer->data;	GaimConnection *gc = oft_info->sess->aux_data;	OscarData *od = gc->proto_data;	gaim_debug_info("oscar", "AAA - in oscar_xfer_end\n");	if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) {		oft_info->fh.nrecvd = gaim_xfer_get_bytes_sent(xfer);		aim_oft_sendheader(oft_info->sess, AIM_CB_OFT_DONE, oft_info);	}	aim_conn_kill(oft_info->sess, &oft_info->conn);	aim_oft_destroyinfo(oft_info);	xfer->data = NULL;	od->file_transfers = g_slist_remove(od->file_transfers, xfer);}/* * xfer functions used when receiving files */static void oscar_xfer_init_recv(GaimXfer *xfer){	struct aim_oft_info *oft_info = xfer->data;	GaimConnection *gc = oft_info->sess->aux_data;	OscarData *od = gc->proto_data;	gaim_debug_info("oscar", "AAA - in oscar_xfer_recv_init\n");	oft_info->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL);	if (oft_info->conn) {		oft_info->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;		aim_conn_addhandler(od->sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_PROMPT, oscar_sendfile_prompt, 0);		oft_info->conn->fd = xfer->fd = gaim_proxy_connect(gaim_connection_get_account(gc),					xfer->remote_ip, xfer->remote_port,	oscar_sendfile_connected, xfer);		if (xfer->fd == -1) {			gaim_xfer_error(GAIM_XFER_RECEIVE, xfer->who,							_("Unable to establish file descriptor."));			gaim_xfer_cancel_local(xfer);		}	} else {		gaim_xfer_error(GAIM_XFER_RECEIVE, xfer->who,						_("Unable to create new connection."));		gaim_xfer_cancel_local(xfer);		/* Try a different port? Ask them to connect to us? /join #gaim and whine? */	}}static void oscar_xfer_cancel_recv(GaimXfer *xfer){	struct aim_oft_info *oft_info = xfer->data;	GaimConnection *gc = oft_info->sess->aux_data;	OscarData *od = gc->proto_data;	gaim_debug_info("oscar", "AAA - in oscar_xfer_cancel_recv\n");	if (gaim_xfer_get_status(xfer) != GAIM_XFER_STATUS_CANCEL_REMOTE)		aim_im_sendch2_sendfile_cancel(oft_info->sess, oft_info);	aim_conn_kill(oft_info->sess, &oft_info->conn);	aim_oft_destroyinfo(oft_info);	xfer->data = NULL;	od->file_transfers = g_slist_remove(od->file_transfers, xfer);}static void oscar_xfer_ack_recv(GaimXfer *xfer, const char *buffer, size_t size){	struct aim_oft_info *oft_info = xfer->data;	/* Update our rolling checksum.  Like Walmart, yo. */	oft_info->fh.recvcsum = aim_oft_checksum_chunk(buffer, size, oft_info->fh.recvcsum);}/* * xfer functions used when sending files */static void oscar_xfer_init_send(GaimXfer *xfer){	struct aim_oft_info *oft_info = xfer->data;	GaimConnection *gc = oft_info->sess->aux_data;	OscarData *od = gc->proto_data;	int listenfd;	gaim_debug_info("oscar", "AAA - in oscar_xfer_send_init\n");	xfer->filename = g_path_get_basename(xfer->local_filename);	strncpy(oft_info->fh.name, xfer->filename, 64);	oft_info->fh.name[63] = '\0';	oft_info->fh.totsize = gaim_xfer_get_size(xfer);	oft_info->fh.size = gaim_xfer_get_size(xfer);	oft_info->fh.checksum = aim_oft_checksum_file(xfer->local_filename);	/* Create a listening socket and an associated libfaim conn */	if ((listenfd = gaim_network_listen_range(5190, 5199)) < 0) {		gaim_xfer_cancel_local(xfer);		return;	}	xfer->local_port = gaim_network_get_port_from_fd(listenfd);	oft_info->port = xfer->local_port;	if (aim_sendfile_listen(od->sess, oft_info, listenfd) != 0) {		gaim_xfer_cancel_local(xfer);		return;	}	gaim_debug_misc("oscar",			   "port is %hu, ip is %s\n",			   xfer->local_port, oft_info->clientip);	if (oft_info->conn) {		xfer->watcher = gaim_input_add(oft_info->conn->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn);		aim_im_sendch2_sendfile_ask(od->sess, oft_info);		aim_conn_addhandler(od->sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED, oscar_sendfile_estblsh, 0);	} else {		gaim_xfer_error(GAIM_XFER_SEND, xfer->who,						_("Unable to establish listener socket."));		gaim_xfer_cancel_local(xfer);	}}static void oscar_xfer_cancel_send(GaimXfer *xfer){	struct aim_oft_info *oft_info = xfer->data;	GaimConnection *gc = oft_info->sess->aux_data;	OscarData *od = gc->proto_data;	gaim_debug_info("oscar", "AAA - in oscar_xfer_cancel_send\n");	if (gaim_xfer_get_status(xfer) != GAIM_XFER_STATUS_CANCEL_REMOTE)		aim_im_sendch2_sendfile_cancel(oft_info->sess, oft_info);	aim_conn_kill(oft_info->sess, &oft_info->conn);	aim_oft_destroyinfo(oft_info);	xfer->data = NULL;	od->file_transfers = g_slist_remove(od->file_transfers, xfer);}static void oscar_xfer_ack_send(GaimXfer *xfer, const char *buffer, size_t size){	struct aim_oft_info *oft_info = xfer->data;	/* I'm not sure I like how we do this. --marv	 * I do.  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 Gaim 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, however...  --KingAnt	 */	/*	 * 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 (gaim_xfer_get_bytes_remaining(xfer) <= 0) {		gaim_input_remove(xfer->watcher);		xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn);		xfer->fd = 0;		gaim_xfer_set_completed(xfer, TRUE);	}}static gboolean oscar_can_receive_file(GaimConnection *gc, const char *who) {	gboolean can_receive = FALSE;	OscarData *od = gc->proto_data;	if (!od->icq) {		aim_userinfo_t *userinfo;		userinfo = aim_locate_finduserinfo(od->sess, who);		if (userinfo && userinfo->capabilities & AIM_CAPS_SENDFILE)			can_receive = TRUE;	}	return can_receive;}static void oscar_send_file(GaimConnection *gc, const char *who, const char *file) {	OscarData *od;	GaimXfer *xfer;	struct aim_oft_info *oft_info;	const char *ip;	od = (OscarData *)gc->proto_data;	/* You want to send a file to someone else, you're so generous */	/* Build the file transfer handle */	xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who);	/* Create the oscar-specific data */	ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1);	oft_info = aim_oft_createinfo(od->sess, NULL, who, ip, 0, 0, 0, NULL);	xfer->data = oft_info;	 /* Setup our I/O op functions */	gaim_xfer_set_init_fnc(xfer, oscar_xfer_init_send);	gaim_xfer_set_end_fnc(xfer, oscar_xfer_end);	gaim_xfer_set_cancel_send_fnc(xfer, oscar_xfer_cancel_send);	gaim_xfer_set_request_denied_fnc(xfer, oscar_xfer_cancel_send);	gaim_xfer_set_ack_fnc(xfer, oscar_xfer_ack_send);	/* Keep track of this transfer for later */	od->file_transfers = g_slist_append(od->file_transfers, xfer);	/* Now perform the request */	if (file)		gaim_xfer_request_accepted(xfer, file);	else		gaim_xfer_request(xfer);}static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) {	GaimConnection *gc = sess->aux_data;	OscarData *od = gc->proto_data;	GaimAccount *account = gc->account;	aim_conn_t *bosconn;	char *host; int port;	int i, rc;	va_list ap;	struct aim_authresp_info *info;	port = gaim_account_get_int(account, "port", FAIM_LOGIN_PORT);	va_start(ap, fr);	info = va_arg(ap, struct aim_authresp_info *);	va_end(ap);	gaim_debug_info("oscar",			   "inside auth_resp (Screen name: %s)\n", info->sn);	if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) {		char buf[256];		switch (info->errorcode) {		case 0x05:			/* Incorrect nick/password */			gc->wants_to_die = TRUE;			gaim_connection_error(gc, _("Incorrect nickname or password."));			break;		case 0x11:			/* Suspended account */			gc->wants_to_die = TRUE;			gaim_connection_error(gc, _("Your account is currently suspended."));			break;		case 0x14:			/* service temporarily unavailable */			gaim_connection_error(gc, _("The AOL Instant Messenger service is temporaril

⌨️ 快捷键说明

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