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

📄 iax.c

📁 iax协议Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
								session->transfer.sin_family = AF_INET;								session->transfercallno = atoi(s);								free(s);								session->transferring = TRANSFER_BEGIN;								e->etype = IAX_EVENT_TXREPLY;								iax_do_event(session, e);							}						}					}				}				free(e);				return NULL;			case IAX_COMMAND_DPREP:				/* Received dialplan reply */				printf("Got dialplan reply: %s\n", text);				e->etype = IAX_EVENT_DPREP;				s = extract(text, "number=");				if (s)					e->event.dprep.number = s;				e->event.dprep.canexist = 0;				e->event.dprep.exists = 0;				e->event.dprep.nonexistant = 0;				s = extract(text, "status=");				if (s) {					if (!strcmp(s, "canexist"))						e->event.dprep.canexist = 1;					else if (!strcmp(s, "exists"))						e->event.dprep.exists = 1;					else if (!strcmp(s, "nonexistant"))						e->event.dprep.nonexistant = 1;					else						fprintf(stderr, "Unknown status '%s'\n", s);					free(s);				}				e->event.dprep.ignorepat = 0;				s = extract(text, "ignorepat=");				if (s) {					if (!strcmp(s, "yes"))						e->event.dprep.ignorepat = 1;					free(s);				}				s = extract(text, "expirey=");				if (s) {					e->event.dprep.expirey = atoi(s);					if (e->event.dprep.expirey < 0)						e->event.dprep.expirey = 0;					free(s);				} else					e->event.dprep.expirey = 0;				/* Return immediately, makes no sense to schedule */				return e;			case IAX_COMMAND_TXCNT:				/* Received a transfer connect.  Accept it if we're transferring */				e->etype = IAX_EVENT_TXACCEPT;				if (session->transferring) 					iax_do_event(session, e);				free(e);				return NULL;			case IAX_COMMAND_TXACC:				e->etype = IAX_EVENT_TXREADY;				if (session->transferring) {					/* Cancel any more connect requests */					sch = schedq;					while(sch) {						if (sch->frame && sch->frame->transferpacket)								sch->frame->retries = -1;						sch = sch->next;					}					session->transferring = TRANSFER_READY;					iax_do_event(session, e);				}				free(e);				return NULL;			case IAX_COMMAND_TXREL:				printf("Release: text is %s\n", text);				/* Release the transfer */				s = extract(text, "peercallno=");				if (s) 					session->peercallno = atoi(s);				/* Change from transfer to session now */				memcpy(&session->peeraddr, &session->transfer, sizeof(session->peeraddr));				memset(&session->transfer, 0, sizeof(session->transfer));				session->transferring = TRANSFER_NONE;				/* Force retransmission of a real voice packet, and reset all timing */				session->svoiceformat = -1;				session->voiceformat = 0;				memset(&session->rxcore, 0, sizeof(session->rxcore));				memset(&session->offset, 0, sizeof(session->offset));				memset(&session->history, 0, sizeof(session->history));				session->jitterbuffer = 0;				session->jitter = 0;				session->lag = 0;				/* Reset sequence numbers */				session->oseqno = 0;				session->iseqno = 0;				session->lastsent = 0;				session->last_ts = 0;				session->lastvoicets = 0;				session->pingtime = 30;				e->etype = IAX_EVENT_TRANSFER;				e->event.transfer.newip = strdup(inet_ntoa(session->peeraddr.sin_addr));				e->event.transfer.newport = ntohs(session->peeraddr.sin_port);				/* We have to dump anything we were going to (re)transmit now that we've been				   transferred since they're all invalid and for the old host. */				sch = schedq;				while(sch) {					if (sch->frame && (sch->frame->session == session))								sch->frame->retries = -1;					sch = sch->next;				}				return e;			case IAX_COMMAND_QUELCH:				e->etype = IAX_EVENT_QUELCH;				session->quelch = 1;				return e;			case IAX_COMMAND_UNQUELCH:				e->etype = IAX_EVENT_UNQUELCH;				session->quelch = 0;				return e;			default:				DEBU(G "Don't know what to do with IAX command %d\n", subclass);				free(e);				return NULL;			}			break;		case AST_FRAME_CONTROL:			switch(subclass) {			case AST_CONTROL_ANSWER:				e->etype = IAX_EVENT_ANSWER;				return schedule_delivery(e, ts);			case AST_CONTROL_BUSY:				e->etype = IAX_EVENT_BUSY;				return schedule_delivery(e, ts);			case AST_CONTROL_RINGING:				e->etype = IAX_EVENT_RINGA;				return schedule_delivery(e, ts);			default:				DEBU(G "Don't know what to do with AST control %d\n", subclass);				free(e);				return NULL;			}			break;		case AST_FRAME_IMAGE:			e->etype = IAX_EVENT_IMAGE;			e->event.image.format = subclass;			if (datalen) {				e->event.image.data = (char *)malloc(datalen);				e->event.image.datalen = datalen;				if (e->event.image.data) {					memcpy(e->event.image.data, fh->data, datalen);				} else {					free(e);					e = NULL;					DEBU(G "Out of memory\n");					return NULL;				}			} else {				/* Empty image frame?  Maybe it could happen... */				e->event.image.data = NULL;				e->event.image.datalen = 0;			}			return schedule_delivery(e, ts);		case AST_FRAME_TEXT:			e->etype = IAX_EVENT_TEXT;			strncpy(e->event.text.text, (char *)fh->data, datalen);			return schedule_delivery(e, ts);		case AST_FRAME_HTML:			switch(fh->csub) {			case AST_HTML_LINKURL:				e->event.url.link = 1;				/* Fall through */			case AST_HTML_URL:				e->etype = IAX_EVENT_URL;				if (datalen) {					e->event.url.url = (char *)malloc(datalen + 1);					strncpy(e->event.url.url, (char *)fh->data, datalen);				}				return schedule_delivery(e, ts);			case AST_HTML_LDCOMPLETE:				e->etype = IAX_EVENT_LDCOMPLETE;				return schedule_delivery(e, ts);			case AST_HTML_UNLINK:				e->etype = IAX_EVENT_UNLINK;				return schedule_delivery(e, ts);			case AST_HTML_LINKREJECT:				e->etype = IAX_EVENT_LINKREJECT;				return schedule_delivery(e, ts);			default:				DEBU(G "Don't know how to handle HTML type %d frames\n", fh->csub);				free(e);				return NULL;			}			break;		default:			DEBU(G "Don't know what to do with frame type %d\n", fh->type);			free(e);			return NULL;		}	} else		DEBU(G "Out of memory\n");	return NULL;}static struct iax_event *iax_miniheader_to_event(struct iax_session *session,						struct iax_mini_hdr *mh,						int datalen){	struct iax_event *e;	unsigned int ts;	e = (struct iax_event *)malloc(sizeof(struct iax_event));	if (e) {		if (session->voiceformat > 0) {			e->etype = IAX_EVENT_VOICE;			e->session = session;			e->event.voice.format = session->voiceformat;			if (datalen) {#ifdef EXTREME_DEBUG				DEBU(G "%d bytes of voice\n", datalen);#endif				e->event.voice.data = (char *)malloc(datalen);				if (e->event.voice.data) {					e->event.voice.datalen = datalen;					memcpy(e->event.voice.data, mh->data, datalen);				} else {					free(e);					e = NULL;					DEBU(G "Out of memory\n");					return e;				}			} else {				/* Empty voice frame?  Maybe it could happen... */				e->event.voice.data = NULL;				e->event.voice.datalen = 0;			}			ts = (session->last_ts & 0xFFFF0000) | ntohs(mh->ts);			return schedule_delivery(e, ts);		} else {			DEBU(G "No last format received on session %d\n", session->callno);			free(e);			e = NULL;		}	} else		DEBU(G "Out of memory\n");	return e;}static struct iax_event *iax_net_read(void){	char buf[IAX_MAX_BUF_SIZE];	int res;	struct sockaddr_in sin;	int sinlen;	struct iax_full_hdr *fh = (struct iax_full_hdr *)buf;	struct iax_mini_hdr *mh = (struct iax_mini_hdr *)buf;	struct iax_session *session;		sinlen = sizeof(sin);	res = recvfrom(netfd, buf, sizeof(buf), 0, (struct sockaddr *) &sin, &sinlen);	buf[sizeof(buf) - 1] = '\0';	if (res < 0) {#ifdef	WIN32		if (WSAGetLastError() != WSAEWOULDBLOCK) {			DEBU(G "Error on read: %d\n", WSAGetLastError());			IAXERROR "Read error on network socket: %s", strerror(errno));		}#else		if (errno != EAGAIN) {			DEBU(G "Error on read: %s\n", strerror(errno));			IAXERROR "Read error on network socket: %s", strerror(errno));		}#endif		return NULL;	}	if (ntohs(fh->callno) & IAX_FLAG_FULL) {		/* Full size header */		if (res < sizeof(struct iax_full_hdr)) {			DEBU(G "Short header received from %s\n", inet_ntoa(sin.sin_addr));			IAXERROR "Short header received from %s\n", inet_ntoa(sin.sin_addr));		}		/* We have a full header, process appropriately */		session = iax_find_session(&sin, (short)(ntohs((short)fh->callno) & ~IAX_FLAG_FULL), ntohs((short)fh->dcallno), 1);		if (session) 			return iax_header_to_event(session, fh, res - sizeof(struct iax_full_hdr));		DEBU(G "No session?\n");		return NULL;	} else {		if (res < sizeof(struct iax_mini_hdr)) {			DEBU(G "Short header received from %s\n", inet_ntoa(sin.sin_addr));			IAXERROR "Short header received from %s\n", inet_ntoa(sin.sin_addr));		}		/* Miniature, voice frame */		session = iax_find_session(&sin, ntohs(fh->callno), 0, 0);		if (session)			return iax_miniheader_to_event(session, mh, res - sizeof(struct iax_mini_hdr));		DEBU(G "No session?\n");		return NULL;	}}static struct iax_sched *iax_get_sched(struct timeval tv){	struct iax_sched *cur, *prev=NULL;	cur = schedq;	/* Check the event schedule first. */	while(cur) {		if ((tv.tv_sec > cur->when.tv_sec) ||		    ((tv.tv_sec == cur->when.tv_sec) && 			(tv.tv_usec >= cur->when.tv_usec))) {				/* Take it out of the event queue */				if (prev) {					prev->next = cur->next;				} else {					schedq = cur->next;				}				return cur;		}		cur = cur->next;	}	return NULL;}struct iax_event *iax_get_event(int blocking){	struct iax_event *event;	struct iax_frame *frame;	struct timeval tv;	struct iax_sched *cur;	struct iax_event e;		gettimeofday(&tv, NULL);		while((cur = iax_get_sched(tv))) {		event = cur->event;		frame = cur->frame;		if (event) {			/* See if this is an event we need to handle */			event = handle_event(event);			if (event) {				free(cur);				return event;			}		} else {			/* It's a frame, transmit it and schedule a retry */			if (frame->retries < 0) {				/* It's been acked.  No need to send it.   Destroy the old				   frame */				if (frame->data)					free(frame->data);				free(frame);			} else if (frame->retries == 0) {				if (frame->transferpacket) {					/* Send a transfer reject since we weren't able to connect */					e.etype = IAX_EVENT_TXREJECT;					iax_do_event(frame->session, &e);					break;				} else {					/* We haven't been able to get an ACK on this packet.  We should					   destroy its session */					event = (struct iax_event *)malloc(sizeof(struct iax_event));					if (event) {						event->etype = IAX_EVENT_TIMEOUT;						event->session = frame->session;						free(cur);						return handle_event(event);					}				}			} else {				/* Decrement remaining retries */				frame->retries--;				/* Multiply next retry time by 4, not above MAX_RETRY_TIME though */				frame->retrytime *= 4;				/* Keep under 1000 ms if this is a transfer packet */				if (!frame->transferpacket) {					if (frame->retrytime > MAX_RETRY_TIME)						frame->retrytime = MAX_RETRY_TIME;				} else if (frame->retrytime > 1000)					frame->retrytime = 1000;				iax_xmit_frame(frame);				/* Schedule another retransmission */				printf("Scheduling retransmission %d\n", frame->retries);				iax_sched_event(NULL, frame, frame->retrytime);			}		}		free(cur);	}	/* Now look for networking events */	if (blocking) {		/* Block until there is data if desired */		fd_set fds;		FD_ZERO(&fds);		FD_SET(netfd, &fds);		select(netfd + 1, &fds, NULL, NULL, NULL);	}	event = iax_net_read();		return handle_event(event);}struct sockaddr_in iax_get_peer_addr(struct iax_session *session){	return session->peeraddr;}void iax_event_free(struct iax_event *event){	switch(event->etype) {	case IAX_EVENT_CONNECT:		if (event->event.connect.callerid)			free(event->event.connect.callerid);		if (event->event.connect.dnid)			free(event->event.connect.dnid);		if (event->event.connect.context)			free(event->event.connect.context);		if (event->event.connect.exten)			free(event->event.connect.exten);		if (event->event.connect.username)			free(event->event.connect.username);		if (event->event.connect.hostname)			free(event->event.connect.hostname);		if (event->event.connect.language)			free(event->event.connect.language);		break;	case IAX_EVENT_HANGUP:		if (event->event.hangup.byemsg)			free(event->event.hangup.byemsg);		break;	case IAX_EVENT_REJECT:		if (event->event.reject.reason)			free(event->event.reject.reason);		break;	case IAX_EVENT_VOICE:		if (event->event.voice.data)			free(event->event.voice.data);		break;	case IAX_EVENT_IMAGE:		if (event->event.image.data)			free(event->event.image.data);		break;	case IAX_EVENT_URL:		if (event->event.url.url)			free(event->event.url.url);		break;	case IAX_EVENT_AUTHRQ:		if (event->event.authrequest.challenge)			free(event->event.authrequest.challenge);		if (event->event.authrequest.username)			free(event->event.authrequest.username);		break;	case IAX_EVENT_AUTHRP:		if (event->event.authreply.reply)			free(event->event.authreply.reply);		break;	case IAX_EVENT_REGREQ:		if (event->event.regrequest.server)			free(event->event.regrequest.server);		if (event->event.regrequest.peer)			free(event->event.regrequest.peer);		if (event->event.regrequest.secret)			free(event->event.regrequest.secret);		break;	case IAX_EVENT_REGREP:		if (event->event.regreply.ourip)			free(event->event.regreply.ourip);		if (event->event.regreply.callerid)			free(event->event.regreply.callerid);		break;	case IAX_EVENT_TRANSFER:		if (event->event.transfer.newip)			free(event->event.transfer.newip);		break;	case IAX_EVENT_DPREQ:		if (event->event.dpreq.number)			free(event->event.dpreq.number);		break;	case

⌨️ 快捷键说明

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