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

📄 iax.c

📁 iax协议Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
		"TKOFFHK ",		"OFFHOOK" };	struct iax_full_hdr *fh;	char retries[20];	char class2[20];	char subclass2[20];	char *class;	char *subclass;	if (f) {		fh = f->data;		snprintf(retries, sizeof(retries), "%03d", f->retries);	} else {		strcpy(retries, "N/A");		fh = fhi;	}	if (!(ntohs(fh->callno) & IAX_FLAG_FULL)) {		/* Don't mess with mini-frames */		return;	}	if ((fh->type >= sizeof(frames)/sizeof(char *)) || (fh->type < 0)) {		snprintf(class2, sizeof(class2), "(%d?)", fh->type);		class = class2;	} else {		class = frames[(int)fh->type];	}	if (fh->type == AST_FRAME_DTMF) {		sprintf(subclass2, "%c", fh->csub);		subclass = subclass2;	} else if (fh->type == AST_FRAME_IAX) {		if (fh->csub >= sizeof(iaxs)/sizeof(iaxs[0])) {			snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);			subclass = subclass2;		} else {			subclass = iaxs[(int)fh->csub];		}	} else if (fh->type == AST_FRAME_CONTROL) {		if (fh->csub > sizeof(cmds)/sizeof(char *)) {			snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);			subclass = subclass2;		} else {			subclass = cmds[(int)fh->csub];		}	} else {		snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);		subclass = subclass2;	}	if (debug) {		fprintf(stderr, "%s-Frame Retry[%s] -- Seqno: %2.2d  Type: %s Subclass: %s\n", 	(rx ? "Rx" : "Tx"),	retries, ntohs(fh->seqno), class, subclass);		fprintf(stderr, "   Timestamp: %05dms  Callno: %4.4d  DCall: %4.4d\n", 	ntohl(fh->ts),	ntohs(fh->callno) & ~IAX_FLAG_FULL, (short) ntohs(fh->dcallno));	}}#endifstatic int iax_xmit_frame(struct iax_frame *f){	/* Send the frame raw */#ifdef DEBUG_SUPPORT	showframe(f, NULL, 0);#endif	return sendto(netfd, (const char *) f->data, f->datalen,#ifdef	WIN32		0,#else		MSG_DONTWAIT | MSG_NOSIGNAL,#endif					f->transferpacket ? 						(struct sockaddr *)&(f->session->transfer) :					(struct sockaddr *)&(f->session->peeraddr), sizeof(f->session->peeraddr));}static int iax_reliable_xmit(struct iax_frame *f){	struct iax_frame *fc;	struct iax_full_hdr *fh;	fh = (struct iax_full_hdr *) f->data;	if (!fh->type) {		DEBU(G "Asked to reliably transmit a non-packet.  Crashing.\n");		*((char *)0)=0;	}	fc = (struct iax_frame *)malloc(sizeof(struct iax_frame));	if (fc) {		/* Make a copy of the frame */		memcpy(fc, f, sizeof(struct iax_frame));		/* And a copy of the data if applicable */		if (!fc->data || !fc->datalen) {			IAXERROR "No frame data?");			DEBU(G "No frame data?\n");			return -1;		} else {			fc->data = (char *)malloc(fc->datalen);			if (!fc->data) {				DEBU(G "Out of memory\n");				IAXERROR "Out of memory\n");				return -1;			}			memcpy(fc->data, f->data, f->datalen);			iax_sched_event(NULL, fc, fc->retrytime);			return iax_xmit_frame(fc);		}	} else		return -1;}int iax_init(int preferredportno){	int portno = preferredportno;	struct sockaddr_in sin;	int sinlen;	int flags;		if (netfd > -1) {		/* Sokay, just don't do anything */		DEBU(G "Already initialized.");		return 0;	}	netfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);	if (netfd < 0) {		DEBU(G "Unable to allocate UDP socket\n");		IAXERROR "Unable to allocate UDP socket\n");		return -1;	}		if (preferredportno == 0) 		preferredportno = IAX_DEFAULT_PORTNO;			if (preferredportno > 0) {		sin.sin_family = AF_INET;		sin.sin_addr.s_addr = 0;		sin.sin_port = htons((short)preferredportno);		if (bind(netfd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {			DEBU(G "Unable to bind to preferred port.  Using random one instead.");		}	}	sinlen = sizeof(sin);	if (getsockname(netfd, (struct sockaddr *) &sin, &sinlen) < 0) {		close(netfd);		netfd = -1;		DEBU(G "Unable to figure out what I'm bound to.");		IAXERROR "Unable to determine bound port number.");	}#ifdef	WIN32	flags = 1;	if (ioctlsocket(netfd,FIONBIO,(unsigned long *) &flags)) {		_close(netfd);		netfd = -1;		DEBU(G "Unable to set non-blocking mode.");		IAXERROR "Unable to set non-blocking mode.");	}	#else	if ((flags = fcntl(netfd, F_GETFL)) < 0) {		close(netfd);		netfd = -1;		DEBU(G "Unable to retrieve socket flags.");		IAXERROR "Unable to retrieve socket flags.");	}	if (fcntl(netfd, F_SETFL, flags | O_NONBLOCK) < 0) {		close(netfd);		netfd = -1;		DEBU(G "Unable to set non-blocking mode.");		IAXERROR "Unable to set non-blocking mode.");	}#endif	portno = ntohs(sin.sin_port);	srand(time(NULL));	callnums = rand() % 32767 + 1;	DEBU(G "Started on port %d\n", portno);	return portno;	}static void destroy_session(struct iax_session *session);static void convert_reply(char *out, unsigned char *in){	int x;	for (x=0;x<16;x++)		out += sprintf(out, "%2.2x", (int)in[x]);}static unsigned char compress_subclass(int subclass){	int x;	int power=-1;	/* If it's 128 or smaller, just return it */	if (subclass < IAX_FLAG_SC_LOG)		return subclass;	/* Otherwise find its power */	for (x = 0; x < IAX_MAX_SHIFT; x++) {		if (subclass & (1 << x)) {			if (power > -1) {				DEBU(G "Can't compress subclass %d\n", subclass);				return 0;			} else				power = x;		}	}	return power | IAX_FLAG_SC_LOG;}int iax_do_event(struct iax_session *session, struct iax_event *event){	struct iax_frame f;	int left;	struct hostent *hp;	unsigned int ts;	char buf[32768];	struct iax_full_hdr *fh = (struct iax_full_hdr *)buf;	struct iax_mini_hdr *mh = (struct iax_mini_hdr *)buf;	struct MD5Context md5;	char reply[32];	char realreply[80];	char *requeststr = fh->data;#define MYSNPRINTF snprintf(requeststr + strlen(requeststr), sizeof(buf) - sizeof(struct iax_full_hdr) - strlen(requeststr), 	bzero(buf, sizeof(buf));	/* Default some things in the frame */	f.session = session;	f.data = buf;	f.datalen = sizeof(struct iax_full_hdr);	left = sizeof(buf) - f.datalen;	f.retries = maxretries;	f.transferpacket = 0;		/* Assume a full header and default some things */	fh->callno = htons((short)(session->callno | IAX_FLAG_FULL));	fh->dcallno = htons((short)session->peercallno);	/* Calculate timestamp */	fh->ts = htonl(calc_timestamp(session, 0));		/* Start by using twice the pingtime */	f.retrytime = session->pingtime * 2;	if (f.retrytime > MAX_RETRY_TIME)		f.retrytime = MAX_RETRY_TIME;	if (f.retrytime < MIN_RETRY_TIME)		f.retrytime = MIN_RETRY_TIME;		f.next = NULL;	/* Some sanity checks */	if (!event) {		DEBU(G "Event is null?\n");		IAXERROR "Null event");		return -1;	}	if (!session)		session = event->session;	if (!iax_session_valid(session)) {		DEBU(G "Session invalid for sending event\n");		IAXERROR "Invalid session for transmitting event");	}	/* Send (possibly reliably) the correct frame given the kind	   of event requested */	switch(event->etype) {	case IAX_EVENT_CONNECT:		/* Connect first */		hp = gethostbyname(event->event.connect.hostname);		if (!hp) {			snprintf(iax_errstr, sizeof(iax_errstr), "Invalid hostname: %s", event->event.connect.hostname);			return -1;		}		memcpy(&session->peeraddr.sin_addr, hp->h_addr, sizeof(session->peeraddr.sin_addr));		session->peeraddr.sin_port = htons(event->event.connect.portno);		session->peeraddr.sin_family = AF_INET;		fh->type = AST_FRAME_IAX;		fh->csub = IAX_COMMAND_NEW;		fh->seqno = htons(session->oseqno++);		if (event->event.connect.exten)			MYSNPRINTF "exten=%s;", event->event.connect.exten);		if (event->event.connect.callerid)			MYSNPRINTF "callerid=%s;", event->event.connect.callerid);				if (event->event.connect.dnid)			MYSNPRINTF "dnid=%s;", event->event.connect.dnid);		if (event->event.connect.context)			MYSNPRINTF "context=%s;", event->event.connect.context);		if (event->event.connect.username)			MYSNPRINTF "username=%s;", event->event.connect.username);		if (event->event.connect.language)			MYSNPRINTF "language=%s;", event->event.connect.language);		MYSNPRINTF "formats=%d;", sformats);		MYSNPRINTF "version=%d;", IAX_PROTO_VERSION);		f.datalen += strlen(requeststr);		iax_reliable_xmit(&f);		break;	case IAX_EVENT_REREQUEST:		fh->type = AST_FRAME_IAX;		fh->csub = IAX_COMMAND_REGREQ;		fh->seqno = htons(session->oseqno++);		MYSNPRINTF "peer=%s;refresh=%d;", session->peer, session->refresh);		if (strstr(session->methods, "md5")) {			MD5Init(&md5);			MD5Update(&md5, (const unsigned char *) &session->challenge[0], strlen(session->challenge));			MD5Update(&md5, (const unsigned char *) &session->secret[0], strlen(session->secret));			MD5Final((unsigned char *) reply, &md5);			memset(realreply, 0, sizeof(realreply));			convert_reply(realreply, (unsigned char *) &reply[0]);			MYSNPRINTF "md5secret=%s;", realreply);		} else {			MYSNPRINTF "secret=%s;", session->secret);		}		f.datalen += strlen(requeststr);		iax_reliable_xmit(&f);		break;	case IAX_EVENT_REGREQ:		/* Connect first */		hp = gethostbyname(event->event.regrequest.server);		if (!hp) {			snprintf(iax_errstr, sizeof(iax_errstr), "Invalid hostname: %s", event->event.regrequest.server);			return -1;		}		memcpy(&session->peeraddr.sin_addr, hp->h_addr, sizeof(session->peeraddr.sin_addr));		session->peeraddr.sin_port = htons(event->event.regrequest.portno);		session->peeraddr.sin_family = AF_INET;		fh->type = AST_FRAME_IAX;		fh->csub = IAX_COMMAND_REGREQ;		fh->seqno = htons(session->oseqno++);		if (event->event.regrequest.secret)			strncpy(session->secret, event->event.regrequest.secret, sizeof(session->secret)-1);		else			strcpy(session->secret, "");		if (event->event.regrequest.peer) {			MYSNPRINTF "peer=%s;", event->event.regrequest.peer);			strncpy(session->peer, event->event.regrequest.peer, sizeof(session->peer)-1);		} else			strcpy(session->peer, "");		if (event->event.regrequest.refresh) {			MYSNPRINTF "refresh=%d;", event->event.regrequest.refresh);					session->refresh = event->event.regrequest.refresh;		} else			session->refresh = 0;		f.datalen += strlen(requeststr);		iax_reliable_xmit(&f);		break;	case IAX_EVENT_AUTHRP:		fh->type = AST_FRAME_IAX;		fh->csub = IAX_COMMAND_AUTHREP;		fh->seqno = htons(session->oseqno++);		if (event->event.authreply.authmethod == IAX_AUTHMETHOD_MD5) {			snprintf(requeststr, left, "md5secret=%s;", event->event.authreply.reply);		} else if (event->event.authreply.authmethod == IAX_AUTHMETHOD_PLAINTEXT) {			snprintf(requeststr, left, "secret=%s;", event->event.authreply.reply);		} else {			DEBU(G "Unknown auth method: %d\n", event->event.authreply.authmethod);			IAXERROR "Invalid authentication method %d\n", event->event.authreply.authmethod);			return -1;		}		f.datalen += strlen(requeststr);		iax_reliable_xmit(&f);		break;	case IAX_EVENT_LAGRP:		/* Special case -- return the original timestamp in the message instead of our		   own. */		fh->type = AST_FRAME_IAX;		fh->csub = IAX_COMMAND_LAGRP;		fh->ts = htonl(event->event.lagrq.ts);		fh->seqno = htons(session->oseqno++);		iax_reliable_xmit(&f);		break;	case IAX_EVENT_DTMF:		/* Send a DTMF tone as a reliable transmission -- easy */		fh->type = AST_FRAME_DTMF;		fh->seqno = htons(session->oseqno++);		fh->csub = event->event.dtmf.digit;		iax_reliable_xmit(&f);		break;	case IAX_EVENT_RINGA:		/* Announce that we are ringing */		fh->type = AST_FRAME_CONTROL;		fh->seqno = htons(session->oseqno++);		fh->csub = AST_CONTROL_RINGING;		iax_reliable_xmit(&f);		break;	case IAX_EVENT_HANGUP:		fh->type = AST_FRAME_IAX;		fh->seqno = htons(session->oseqno++);		fh->csub = IAX_COMMAND_HANGUP;		if (event->event.hangup.byemsg) {			strncpy(fh->data, event->event.hangup.byemsg, left-1);			f.datalen += strlen(fh->data);		}		/* XXX Not really reliable since we turn right around and kill it XXX */		iax_reliable_xmit(&f);		destroy_session(session);		break;	case IAX_EVENT_REJECT:		fh->type = AST_FRAME_IAX;		fh->seqno = htons(session->oseqno++);		fh->csub = IAX_COMMAND_REJECT;		strncpy(fh->data, event->event.reject.reason, left-1);		f.datalen += strlen(fh->data);		/* XXX Not really reliable since we turn right around and kill it XXX */		iax_reliable_xmit(&f);		destroy_session(session);		break;	case IAX_EVENT_BUSY:		fh->type = AST_FRAME_CONTROL;		fh->seqno = htons(session->oseqno++);		fh->csub = AST_CONTROL_BUSY;		/* XXX Not really reliable since we turn right around and kill it XXX */		iax_reliable_xmit(&f);		destroy_session(session);		break;	case IAX_EVENT_ACCEPT:		fh->type = AST_FRAME_IAX;		fh->seqno = htons(session->oseqno++);		fh->csub = IAX_COMMAND_ACCEPT;		f.datalen += snprintf((char *)(fh->data), left, "formats=%d;", sformats);		f.datalen++;		iax_reliable_xmit(&f);		break;	case IAX_EVENT_LAGRQ:		fh->type = AST_FRAME_IAX;		fh->seqno = htons(session->oseqno++);		fh->csub = IAX_COMMAND_LAGRQ;		iax_reliable_xmit(&f);		break;	case IAX_EVENT_ANSWER:		fh->type = AST_FRAME_CONTROL;		fh->seqno = htons(session->oseqno++);		fh->csub = AST_CONTROL_ANSWER;		iax_reliable_xmit(&f);		break;	case IAX_EVENT_PONG:		fh->type = AST_FRAME_IAX;		fh->csub = IAX_COMMAND_PONG;		fh->ts = htonl(event->event.ping.ts);		iax_reliable_xmit(&f);		break;	case IAX_EVENT_URL:		fh->type = AST_FRAME_HTML;		fh->seqno = htons(session->oseqno++);		if (event->event.url.link)			fh->csub = AST_HTML_LINKURL;		else			fh->csub = AST_HTML_URL;		if (event->event.url.url) {			f.datalen += strlen(event->event.url.url) + 1;			strcpy(fh->data, event->event.url.url);		}		iax_reliable_xmit(&f);		break;	case IAX_EVENT_TEXT:		fh->type = AST_FRAME_TEXT;		fh->seqno = htons(session->oseqno++);		fh->csub = AST_FRAME_TEXT;		f.datalen += strlen(event->event.text.text) + 1;		strcpy(fh->data, event->event.text.text);		iax_reliable_xmit(&f);		break;	case IAX_EVENT_UNLINK:		fh->type = AST_FRAME_HTML;		fh->seqno = htons(session->oseqno++);		fh->csub = AST_HTML_UNLINK;		iax_reliable_xmit(&f);		break;	case IAX_EVENT_LINKREJECT:		fh->type = AST_FRAME_HTML;		fh->seqno = htons(session->oseqno++);		fh->csub = AST_HTML_LINKREJECT;		iax_reliable_xmit(&f);		break;	case IAX_EVENT_LDCOMPLETE:		fh->type = AST_FRAME_HTML;		fh->seqno = htons(session->oseqno++);

⌨️ 快捷键说明

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