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

📄 ft.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * File transfer (OFT) and DirectIM (ODC). * (OSCAR File Transfer, Oscar Direct Connect(ion?) */#define FAIM_INTERNAL#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <aim.h>#ifndef _WIN32#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/utsname.h> /* for aim_directim_initiate */#include <arpa/inet.h> /* for inet_ntoa */#endif/* TODO:    o look for memory leaks.. there's going to be shitloads, i'm sure. */struct aim_directim_intdata {	fu8_t cookie[8];	char sn[MAXSNLEN+1];	char ip[22];};static int listenestablish(fu16_t portnum); /** * aim_handlerendconnect - call this to accept OFT connections and set up the required structures * @sess: the session * @cur: the conn the incoming connection is on * * call this when you get an outstanding read on a conn with subtype * AIM_CONN_SUBTYPE_RENDEZVOUS_OUT, it will clone the current * &aim_conn_t and tweak things as appropriate. the new conn and the * listener conn are both returned to the client in the * %AIM_CB_FAM_OFT, %AIM_CB_OFT_<CLASS>INITIATE callback. */faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur){ 	int acceptfd = 0;	struct sockaddr cliaddr;	int clilen = sizeof(cliaddr);	int ret = 0;	aim_conn_t *newconn;	if ((acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1)		return 0; /* not an error */	if (cliaddr.sa_family != AF_INET) { /* just in case IPv6 really is happening */		close(acceptfd);		aim_conn_close(cur);		return -1;	} 	if (!(newconn = aim_cloneconn(sess, cur))) {		close(acceptfd);		aim_conn_close(cur);		return -1;	}	newconn->type = AIM_CONN_TYPE_RENDEZVOUS;	newconn->fd = acceptfd;	if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { 		struct aim_directim_intdata *priv;		aim_rxcallback_t userfunc;		priv = (struct aim_directim_intdata *)(newconn->internal = cur->internal);		cur->internal = NULL;		snprintf(priv->ip, sizeof(priv->ip), "%s:%u", 				inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), 				ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));		if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE)))			ret = userfunc(sess, NULL, newconn, cur);	} else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) {#if 0		struct aim_filetransfer_priv *priv;		aim_rxcallback_t userfunc;		newconn->priv = cur->priv;		cur->priv = NULL;		priv = (struct aim_filetransfer_priv *)newconn->priv;		snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));		if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE)))			ret = userfunc(sess, NULL, newconn, cur);#endif	} else { 		faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous Closing conn.\n");		aim_conn_close(newconn);		ret = -1;	}	return ret;}/** * aim_send_im_direct - send IM client-to-client over established connection * @sess: session to conn * @conn: directim connection * @msg: null-terminated string to send; if this is NULL, it will send a "typing" notice.  * * Call this just like you would aim_send_im, to send a directim. You * _must_ have previously established the directim connection. */faim_export int aim_send_im_direct(aim_session_t *sess, aim_conn_t *conn, const char *msg){	struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal;	aim_frame_t *fr;	aim_bstream_t hdrbs; /* XXX this should be within aim_frame_t */	if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) 		return -EINVAL; 	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, strlen(msg))))	       return -ENOMEM;		memcpy(fr->hdr.oft.magic, "ODC2", 4);		fr->hdr.oft.hdr2len = 0x44;		if (!(fr->hdr.oft.hdr2 = calloc(1, fr->hdr.oft.hdr2len))) { 		aim_frame_destroy(fr);		return -ENOMEM;	}		aim_bstream_init(&hdrbs, fr->hdr.oft.hdr2, fr->hdr.oft.hdr2len);	aimbs_put16(&hdrbs, 0x0006);	aimbs_put16(&hdrbs, 0x0000);	aimbs_putraw(&hdrbs, intdata->cookie, 8);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put32(&hdrbs, strlen(msg));	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	/* flags -- 0x000e for "typing", 0x0000 for message */	aimbs_put16(&hdrbs, msg ? 0x0000 : 0x000e);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_putraw(&hdrbs, sess->sn, strlen(sess->sn));	aim_bstream_setpos(&hdrbs, 52); /* bleeehh */	aimbs_put8(&hdrbs, 0x00);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	aimbs_put16(&hdrbs, 0x0000);	/* end of hdr2 */	if (msg) {#if 0 /* XXX this is how you send buddy icon info... */			i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008);		i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c);		i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);		i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466);		i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001);		i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f);		i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e);		i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8);#endif		aimbs_putraw(&fr->data, msg, strlen(msg));	} 	aim_tx_enqueue(sess, fr);	return 0;} static int getlocalip(fu8_t *ip){	struct hostent *hptr;	char localhost[129];	/* XXX if available, use getaddrinfo() */	/* XXX allow client to specify which IP to use for multihomed boxes */	if (gethostname(localhost, 128) < 0)		return -1;	if (!(hptr = gethostbyname(localhost)))		return -1;	memcpy(ip, hptr->h_addr_list[0], 4);	return 0;}/** * aim_directim_intitiate - For those times when we want to open up the directim channel ourselves. * @sess: your session, * @conn: the BOS conn, * @priv: a dummy priv value (we'll let it get filled in later) (if you pass a %NULL, we alloc one) * @destsn: the SN to connect to. * */faim_export aim_conn_t *aim_directim_initiate(aim_session_t *sess, const char *destsn){ 	aim_conn_t *newconn;	aim_msgcookie_t *cookie;	struct aim_directim_intdata *priv;	int listenfd;	fu16_t port = 4443;	fu8_t localip[4];	fu8_t ck[8];	if (getlocalip(localip) == -1)		return NULL;	if ((listenfd = listenestablish(port)) == -1)		return NULL;	aim_request_directim(sess, destsn, localip, port, ck);	cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t));	memcpy(cookie->cookie, ck, 8);	cookie->type = AIM_COOKIETYPE_OFTIM;	/* this one is for the cookie */	priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata));	memcpy(priv->cookie, ck, 8);	strncpy(priv->sn, destsn, sizeof(priv->sn));	cookie->data = priv;	aim_cachecookie(sess, cookie);	/* XXX switch to aim_cloneconn()? */	if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) {		close(listenfd);		return NULL;	}	/* this one is for the conn */	priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata));	memcpy(priv->cookie, ck, 8);	strncpy(priv->sn, destsn, sizeof(priv->sn));	newconn->fd = listenfd;	newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;	newconn->internal = priv;	newconn->lastactivity = time(NULL);	faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd);	return newconn;}/** * aim_sendfile_intitiate - For those times when we want to send the file ourselves. * @sess: your session, * @conn: the BOS conn, * @destsn: the SN to connect to. * @filename: the name of the files you want to send * */faim_export aim_conn_t *aim_sendfile_initiate(aim_session_t *sess, const char *destsn, const char *filename, fu16_t numfiles, fu32_t totsize){ 	aim_conn_t *newconn;	aim_msgcookie_t *cookie;	struct aim_directim_intdata *priv;	int listenfd;	fu16_t port = 4443;	fu8_t localip[4];	fu8_t ck[8];	if (getlocalip(localip) == -1)		return NULL;	if ((listenfd = listenestablish(port)) == -1)		return NULL;	aim_request_sendfile(sess, destsn, filename, numfiles, totsize, localip, port, ck);	cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t));	memcpy(cookie->cookie, ck, 8);	cookie->type = AIM_COOKIETYPE_OFTIM;	/* this one is for the cookie */	priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata));	memcpy(priv->cookie, ck, 8);	strncpy(priv->sn, destsn, sizeof(priv->sn));	cookie->data = priv;	aim_cachecookie(sess, cookie);	/* XXX switch to aim_cloneconn()? */	if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) {		close(listenfd);		return NULL;	}	/* this one is for the conn */	priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata));	memcpy(priv->cookie, ck, 8);	strncpy(priv->sn, destsn, sizeof(priv->sn));	newconn->fd = listenfd;	newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;	newconn->internal = priv;	newconn->lastactivity = time(NULL);	faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd);	return newconn;}#if 0/** * unsigned int aim_oft_listener_clean - close up old listeners * @sess: session to clean up in * @age: maximum age in seconds  * * returns number closed, -1 on error. */faim_export unsigned int aim_oft_listener_clean(struct aim_session_t *sess, time_t age) {   struct aim_conn_t *cur;  time_t now;  unsigned int hit = 0;    if (!sess)    return -1;  now = time(NULL);  faim_mutex_lock(&sess->connlistlock);  for(cur = sess->connlist;cur; cur = cur->next)    if (cur->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {       faim_mutex_lock(&cur->active);      if (cur->lastactivity < (now - age) ) { 	faim_mutex_unlock(&cur->active);	aim_conn_close(cur);	hit++;      } else 	faim_mutex_unlock(&cur->active);    }   faim_mutex_unlock(&sess->connlistlock);  return hit;} #endif faim_export const char *aim_directim_getsn(aim_conn_t *conn){	struct aim_directim_intdata *intdata;	if (!conn)	       return NULL;	if ((conn->type != AIM_CONN_TYPE_RENDEZVOUS) || 			(conn->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM))	       return NULL;	if (!conn->internal)		return NULL;	intdata = (struct aim_directim_intdata *)conn->internal;	return intdata->sn;}/** * aim_directim_connect - connect to buddy for directim * @sess: the session to append the conn to, * @sn: the SN we're connecting to * @addr: address to connect to * * This is a wrapper for aim_newconn. * * If addr is NULL, the socket is not created, but the connection is  * allocated and setup to connect. * */faim_export aim_conn_t *aim_directim_connect(aim_session_t *sess, const char *sn, const char *addr, const fu8_t *cookie){ 	aim_conn_t *newconn;	struct aim_directim_intdata *intdata;	if (!sess || !sn)		return NULL;	if (!(intdata = malloc(sizeof(struct aim_directim_intdata))))		return NULL;	memset(intdata, 0, sizeof(struct aim_directim_intdata));	memcpy(intdata->cookie, cookie, 8);	strncpy(intdata->sn, sn, sizeof(intdata->sn));	if (addr)		strncpy(intdata->ip, addr, sizeof(intdata->ip));	/* XXX verify that non-blocking connects actually work */	if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr))) {		free(intdata);		return NULL;	}	if (!newconn) {		free(intdata);		return newconn;	}	newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;	newconn->internal = intdata;	return newconn;} /** * aim_directim_getconn - find a directim conn for buddy name * @sess: your session, * @name: the name to get,   * * returns conn for directim with name, %NULL if none found.  * */faim_export aim_conn_t *aim_directim_getconn(aim_session_t *sess, const char *name){	aim_conn_t *cur;	if (!sess || !name || !strlen(name))		return NULL;	for (cur = sess->connlist; cur; cur = cur->next) {		struct aim_directim_intdata *intdata;				if ((cur->type != AIM_CONN_TYPE_RENDEZVOUS) || (cur->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM))			continue;		intdata = cur->internal;		if (aim_sncmp(intdata->sn, name) == 0)			break;	}	return cur;} /** * aim_accepttransfer - accept a file transfer request * @sess: the session, * @conn: the BOS conn for the CAP reply * @sn: the screenname to send it to, * @cookie: the cookie used * @ip: the ip to connect to * @listingfiles: number of files to share * @listingtotsize: total size of shared files * @listingsize: length of the listing file(buffer) * @listingchecksum: checksum of the listing * @rendid: capability type (%AIM_CAPS_GETFILE or %AIM_CAPS_SENDFILE)   * * Returns new connection or %NULL on error. * * XXX this should take a struct. */faim_export aim_conn_t *aim_accepttransfer(aim_session_t *sess, 						  aim_conn_t *conn, 						  const char *sn, const fu8_t *cookie, 						  const fu8_t *ip, 						  fu16_t listingfiles, 						  fu16_t listingtotsize, 

⌨️ 快捷键说明

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