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

📄 miniphone.c

📁 ppciaxclient softphone
💻 C
📖 第 1 页 / 共 2 页
字号:
	}

	if ( (port = iax_init(0) < 0)) {
		fprintf(stderr, "Fatal error: failed to initialize iax with port %d\n", port);
		return -1;
	}

	iax_set_formats(AST_FORMAT_GSM);
	netfd = iax_get_fd();

	check_iax_register();

	fprintf(f, "Text Based Telephony Client.\n\n");
	issue_prompt(f);

	timer.tv_sec = 0;
	timer.tv_usec = 0;

	while(1) {
		FD_ZERO(&readfd);
		FD_ZERO(&writefd);
		FD_SET(fd, &readfd);
			if(fd > h)
				h = fd;
		if(answered_call && !writeonly) {
			FD_SET(audiofd, &readfd);
				if(audiofd > h)
					h = audiofd;
		}
		if (cursound > -1) {
			FD_SET(audiofd, &writefd);
			if (audiofd > h)
				h = audiofd;
		}
		FD_SET(netfd, &readfd);
		if(netfd > h)
			h = netfd;

		if ( (c = select(h+1, &readfd, &writefd, 0, timerptr)) >= 0) {
			if(FD_ISSET(fd, &readfd)) {
				if ( ( fgets(&*rcmd, 256, f))) {
					rcmd[strlen(rcmd)-1] = 0;
					parse_args(f, &*rcmd);
				} else fprintf(f, "Fatal error: failed to read data!\n");

				issue_prompt(f);
			}
			if(answered_call) {
				if(FD_ISSET(audiofd, &readfd)) {
				static int ret, rlen = 0;
					static short rbuf[FRAME_SIZE];

					if ( (ret = read(audiofd, rbuf + rlen, 2 * (FRAME_SIZE-rlen))) == -1) {
						puts("Failed to read audio.");
						return -1;
					}
					rlen += ret/2;
					if(rlen == FRAME_SIZE) {
						rlen = 0;

						if(!most_recent_answer->gsmout)
							most_recent_answer->gsmout = gsm_create();

						gsm_encode(most_recent_answer->gsmout, rbuf, fo);
						if(iax_send_voice(most_recent_answer->session,
						AST_FORMAT_GSM, (char *)fo, sizeof(fo)) == -1)
							puts("Failed to send voice!");
					}
				}
			}
			do_iax_event(f);
			m = iax_time_to_next_event();
			if(m > -1) {
				timerptr = &timer;
				timer.tv_sec = m /1000;
				timer.tv_usec = (m % 1000) * 1000;
			} else 
				timerptr = 0;
			regm = check_iax_timeout();
			if (!timerptr || (m > regm)) {
				timerptr = &timer;
				timer.tv_sec = regm /1000;
				timer.tv_usec = (regm % 1000) * 1000;
			}
			if (FD_ISSET(audiofd, &writefd)) {
				send_sound(audiofd);
			}
		} else {
			if(errno == EINTR)
				continue;
			fprintf(stderr, "Fatal error in select(): %s\n", strerror(errno));
			return -1;
		}
	}
	return 0;
}

void
do_iax_event(FILE *f) {
	int sessions = 0;
	struct iax_event *e = 0;
	struct peer *peer;

	while ( (e = iax_get_event(0))) {
		peer = find_peer(e->session);
		if(peer) {
			handle_event(f, e, peer);
		} else if (e->session == registry) {
			fprintf(stderr, "Registration complete: %s (%d)\n",
				(e->event.regreply.status == IAX_REG_SUCCESS) ? "Success" : "Failed",
				e->event.regreply.status);
			registry = NULL;
		} else {
			if(e->etype != IAX_EVENT_CONNECT) {
				fprintf(stderr, "Huh? This is an event for a non-existant session?\n");
				continue;
			}
			sessions++;

			if(sessions >= MAX_SESSIONS) {
				fprintf(f, "Missed a call... too many sessions open.\n");
			}


			if(e->event.connect.callerid && e->event.connect.dnid)
				fprintf(f, "Call from '%s' for '%s'", e->event.connect.callerid, 
				e->event.connect.dnid);
			else if(e->event.connect.dnid) {
				fprintf(f, "Call from '%s'", e->event.connect.dnid);
			} else if(e->event.connect.callerid) {
				fprintf(f, "Call from '%s'", e->event.connect.callerid);
			} else printf("Call from");
			fprintf(f, " (%s)\n", inet_ntoa(iax_get_peer_addr(e->session).sin_addr));

			if(most_recent_answer) {
				fprintf(f, "Incoming call ignored, there's already a call waiting for answer... \
please accept or reject first\n");
				iax_reject(e->session, "Too many calls, we're busy!");
			} else {
				if ( !(peer = malloc(sizeof(struct peer)))) {
					fprintf(f, "Warning: Unable to allocate memory!\n");
					return;
				}

				peer->time = time(0);
				peer->session = e->session;
				if (peer->gsmin)
					free(peer->gsmin);
				peer->gsmin = 0;
				if (peer->gsmout)
					free(peer->gsmout);
				peer->gsmout = 0;

				peer->next = peers;
				peers = peer;

				iax_accept(peer->session);
				iax_ring_announce(peer->session);
				most_recent_answer = peer;
				ringing = 1;
				gentone(TONE_RINGER, 0);
				fprintf(f, "Incoming call!\n");
			}
			issue_prompt(f);
		}
		iax_event_free(e);
	}
}

void
call(FILE *f, char *num)
{
	struct peer *peer;

	if(!newcall)
		newcall = iax_session_new();
	else {
		fprintf(f, "Already attempting to call somewhere, please cancel first!\n");
		return;
	}

	if ( !(peer = malloc(sizeof(struct peer)))) {
		fprintf(f, "Warning: Unable to allocate memory!\n");
		return;
	}

	peer->time = time(0);
	peer->session = newcall;
	peer->gsmin = 0;
	peer->gsmout = 0;

	peer->next = peers;
	peers = peer;

	most_recent_answer = peer;

	offhook = 1;
	
	iax_call(peer->session, callerid, num, NULL, 10);
}

void
answer_call(void)
{
	if(most_recent_answer)
		iax_answer(most_recent_answer->session);
	printf("Answering call!\n");
	answered_call = 1;
	offhook = 1;
	ringing = 0;
	gentone(TONE_ANSWER, 1);
}

void
reject_call(void)
{
	iax_reject(most_recent_answer->session, "Call rejected manually.");
	most_recent_answer = 0;
	ringing = 0;
	gentone(TONE_NONE, 1);
}

void
handle_event(FILE *f, struct iax_event *e, struct peer *p)
{
	short fr[FRAME_SIZE];
	int len;

	switch(e->etype) {
		case IAX_EVENT_HANGUP:
			iax_hangup(most_recent_answer->session, "Byeee!");
			fprintf(f, "Call disconnected by peer\n");
			free(most_recent_answer);
			most_recent_answer = 0;
			answered_call = 0;
			peers = 0;
			newcall = 0;
			if (offhook)
				gentone(TONE_CONGEST, 0);
			break;

		case IAX_EVENT_REJECT:
			fprintf(f, "Authentication was rejected\n");
			break;
		case IAX_EVENT_ACCEPT:
			fprintf(f, "Accepted...\n");
			issue_prompt(f);
			break;
		case IAX_EVENT_RINGA:
			fprintf(f, "Ringing...\n");
			issue_prompt(f);
			gentone(TONE_RINGTONE, 0);
			break;
		case IAX_EVENT_ANSWER:
			answer_call();
			gentone(TONE_ANSWER, 1);
 			break;
		case IAX_EVENT_VOICE:
			switch(e->event.voice.format) {
				case AST_FORMAT_GSM:
					if(e->event.voice.datalen % 33) {
						fprintf(stderr, "Weird gsm frame, not a multiple of 33.\n");
						break;
					}

					if (!p->gsmin)
						p->gsmin = gsm_create();

					len = 0;
					while(len < e->event.voice.datalen) {
						if(gsm_decode(p->gsmin, e->event.voice.data + len, fr)) {
							fprintf(stderr, "Bad GSM data\n");
							break;
						} else {
							int res;

							res = write(audiofd, fr, sizeof(fr));
							if (res < 0) 
								fprintf(f, "Write failed: %s\n", strerror(errno));
						}
						len += 33;
					}
					break;
				default :
					fprintf(f, "Don't know how to handle that format %d\n", e->event.voice.format);
			}
			break;
		default:
			fprintf(f, "Unknown event: %d\n", e->etype);
	}
}

void
dump_call(void)
{
        if(most_recent_answer)
        {
	        printf("Dumping call!\n");
            iax_hangup(most_recent_answer->session,"");
            free(most_recent_answer);
        }
        answered_call = 0;
        most_recent_answer = 0;
        answered_call = 0;
        peers = 0;
        newcall = 0;
		offhook = 0;
		ringing = 0;
		gentone(TONE_NONE, 0);
}                                                                               

void
parse_cmd(FILE *f, int argc, char **argv)
{
	if(!strcasecmp(argv[0], "HELP")) {
		if(argc == 1)
			dump_array(f, help);
		else if(argc == 2) {
			if(!strcasecmp(argv[1], "HELP"))
				fprintf(f, "Help <Command>\t-\tDisplays general help or specific help on command if supplied an arguement\n");
			else if(!strcasecmp(argv[1], "QUIT"))
				fprintf(f, "Quit\t\t-\tShuts down the miniphone\n");
			else fprintf(f, "No help available on %s\n", argv[1]);
		} else {
			fprintf(f, "Too many arguements for command help.\n");
		}
	} else if(!strcasecmp(argv[0], "STATUS")) {
		if(argc == 1) {
			int c = 0;
			struct peer *peerptr = peers;

			if(!peerptr)
				fprintf(f, "No session matches found.\n");
			else while(peerptr) {
	 			fprintf(f, "Listing sessions:\n\n");
				fprintf(f, "Session %d\n", ++c);
				fprintf(f, "Session existed for %d seconds\n", (int)time(0)-peerptr->time);
				if(answered_call)
					fprintf(f, "Call answered.\n");
				else fprintf(f, "Call ringing.\n");

				peerptr = peerptr->next;
			}
		} else fprintf(f, "Too many arguments for command status.\n");
	} else if(!strcasecmp(argv[0], "ANSWER")) {
		if(argc > 1)
			fprintf(f, "Too many arguements for command answer\n");
		else answer_call();
	} else if(!strcasecmp(argv[0], "REJECT")) {
		if(argc > 1)
			fprintf(f, "Too many arguements for command reject\n");
		else {
			fprintf(f, "Rejecting current phone call.\n");
			reject_call();
		}
	} else if (!strcasecmp(argv[0], "DUMP")) {
		dump_call();
	} else if (!strcasecmp(argv[0], "HANGUP")) {
		dump_call();
	} else if(!strcasecmp(argv[0], "CALL")) {
		if(argc > 2)
			fprintf(f, "Too many arguements for command call\n");
		else {
			call(f, argv[1]);
		}
	} else if(!strcasecmp(argv[0], "QUIT")) {
		if(argc > 1)
			fprintf(f, "Too many arguements for command quit\n");
		else {
			fprintf(f, "Good bye!\n");
			exit(1);
		}
	} else fprintf(f, "Unknown command of %s\n", argv[0]);
}

void
issue_prompt(FILE *f)
{
	fprintf(f, "TeleClient> ");
	fflush(f);
}

void
dump_array(FILE *f, char **array) {
	while(*array)
		fprintf(f, "%s\n", *array++);
}

⌨️ 快捷键说明

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