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

📄 session.cpp

📁 语音接口~语音识别 & 从声音识别到对各种情报的查找/提供 资料请求~住所.姓名.电话号码等的识别接待 受订货业务~被定型化的受订货业务 预约业务~预约情况的向导和预约接
💻 CPP
字号:
// Copyright (C) 2005 Open Source Telecom Corp.//  // This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.#include "driver.h"namespace sipdriver {using namespace ost;using namespace std;Session::Session(timeslot_t ts) :BayonneSession(&Driver::sip, ts),TimerPort(){#ifndef	WIN32	if(getppid() > 1)		logevents = &cout;#endif	iface = IF_INET;	bridge = BR_GATE;	cid = 0;	did = 0;	rtp = NULL;	dtmf_sipinfo = Driver::sip.info_negotiate;	dtmf_payload = Driver::sip.dtmf_negotiate;	data_payload = Driver::sip.data_negotiate;	dtmf_inband = Driver::sip.dtmf_inband;	dtmf_sipinfo = false;	update_pos = false;	peer_buffer = NULL;	peer_codec = NULL;	if(Driver::peer_encoding == Audio::pcm16Mono)	{		peer_buffer = new Sample[Driver::sip.info.framecount];		peer_codec = AudioCodec::getCodec(Driver::sip.info);	} }Session::~Session(){}void Session::setEncoding(const char *encoding, timeout_t framing){	if(codec)		AudioCodec::endCodec(codec);	memset(&info, 0, sizeof(info));	info.encoding = Audio::getEncoding(encoding);	switch(info.encoding)	{	default:		info.rate = Audio::rate8khz;		if(!framing)			framing = 20;	}	info.setFraming(framing);	codec = AudioCodec::getCodec(info);}void Session::sendDTMFInfo(char digit, unsigned duration){	osip_message_t *message = NULL;	char dtmf_body[1000];        snprintf(dtmf_body, sizeof(dtmf_body) - 1,                "Signal=%c\r\nDuration=%d\r\n", digit, duration);  	eXosip_lock();	if(eXosip_call_build_info(did, &message) != 0)	{		eXosip_unlock();		return;	}	osip_message_set_body(message, dtmf_body, strlen(dtmf_body));	osip_message_set_content_type(message, "application/dtmf-relay");	eXosip_call_send_request(did, message);	eXosip_unlock();}timeout_t Session::getRemaining(void){	return TimerPort::getTimer();}void Session::startTimer(timeout_t timer){	TimerPort::setTimer(timer);	msgport->update();}void Session::stopTimer(void){	TimerPort::endTimer();	msgport->update();}tpport_t Session::getLocalPort(void){	Driver *d = (Driver *)(driver);	return d->rtp_port + (4 * timeslot);}	void Session::startRTP(void){	if(rtp)	{		slog.error("%s: rtp already started", logname);		return;	}	rtp = new RTPStream(this);	if(!rtp->addDestination(remote_address, remote_port))		slog.error("%s: destination not available");	rtp->start();}		void Session::stopRTP(void){	if(!rtp)		return;	rtp->setSource(NULL);	rtp->setSink(NULL);	rtp->setTone(NULL);	delete rtp;	rtp = NULL;}void Session::makeIdle(void){	update_pos = false;	if(offhook)		sipHangup();	BayonneSession::makeIdle();	dtmf_inband = Driver::sip.dtmf_inband;	dtmf_payload = Driver::sip.dtmf_negotiate;	dtmf_sipinfo = Driver::sip.info_negotiate;	data_payload = Driver::sip.data_negotiate;	memcpy(&info, &Driver::sip.info, sizeof(info));	if(codec)		AudioCodec::endCodec(codec);	codec = AudioCodec::getCodec(info);}bool Session::enterJoin(Event *event){	Level level = 26000;	Rate rate = (Rate)info.rate;	unsigned f1, f2;	timeout_t framing = getToneFraming(), duration;	struct dtmf2833 dtmfevent;	switch(event->id)	{	case AUDIO_IDLE:		rtp->setTone(NULL);		return true;	case DTMF_GENTONE:		if(dtmf_sipinfo)		{			sendDTMFInfo(getChar(event->dtmf.digit), event->dtmf.duration);			return true;		}		if(dtmf_payload)		{			memset(&dtmfevent, 0, sizeof(dtmfevent));			dtmfevent.event = event->dtmf.digit;			rtp->set2833(&dtmfevent, event->dtmf.duration);			return true;		}		rtp->setTone(NULL);		if(audio.tone)		{			delete audio.tone;			audio.tone = NULL;		}		f1 = f2 = 0;		duration = event->dtmf.duration;		duration = (duration + (framing - 1)) / framing;		duration *= framing;		switch(event->dtmf.digit)		{		case 0:			f1 = 941; f2 = 1336; break;		case 1:			f1 = 697; f2 = 1209; break;		case 2:			f1 = 697; f2 = 1336; break;		case 3:			f1 = 697; f2 = 1447; break;		case 4:			f1 = 770; f2 = 1209; break;		case 5:			f1 = 770; f2 = 1336; break;		case 6:			f1 = 770; f2 = 1477; break;		case 7:			f1 = 852; f2 = 1209; break;		case 8:			f1 = 852; f2 = 1336; break;		case 9:			f1 = 852; f2 = 1477; break;		case 10:			f1 = 941; f2 = 1209; break;		case 11:			f1 = 941; f2 = 1477; break;		}		if(f1)			audio.tone = new AudioTone(f1, f2, level, level, duration, rate);		if(audio.tone)			rtp->setTone(audio.tone);		return true;	default:		return false;	}}bool Session::enterSeize(Event *event){	char buf[128];	char cref[64];	const char *cp, *to, *from = NULL;	char *sp = NULL;	osip_message_t *invite = NULL;	Registry *reg = NULL;	ScriptImage *img = getImage();	char rbuf[16];	char cbuf[65];	char sdp[512];	const char *rtpmap = NULL;	const char *route;        const char *lp = driver->getLast("localip");	BayonneSession *parent = Bayonne::getSid(var_pid);	switch(event->id)	{	case ENTER_STATE:		cp = getSymbol("session.dialed");		if(!cp)		{			event->id = DIAL_FAILED;			return false;		}		route = Driver::sip.getLast("outbound");		if(!strchr(cp, '@'))		{			snprintf(buf, sizeof(buf), "uri.%s", cp);			reg = (Registry *)img->getPointer(buf);			if(reg && !strnicmp(reg->type, "ext", 3))			{				snprintf(buf, sizeof(buf), "sip:%s@%s",					reg->userid, reg->proxy);				if(!route)					route = reg->proxy;				sp = strrchr(buf, ':');				if(sp && !stricmp(sp, ":5060"))					*sp = 0;				setConst("session.uri_remote", buf);				goto dialing;			}		}		if(!strchr(cp, '@'))			snprintf(buf, sizeof(buf), "sip:%s@%s", cp, route);		else 		{			if(!strnicmp(cp, "sip:", 4))				cp += 4;			snprintf(buf, sizeof(buf), "sip:%s", cp);			}		if(sp && stricmp(sp, ":5060"))			sp = NULL;		setConst("session.uri_remote", buf);		cp = getSymbol("session.uri_remote");		cp = strchr(cp, '@');		if(cp)		{			snprintf(buf, sizeof(buf), "sip.%s", ++cp);			reg = (Registry *)img->getPointer(buf);		}dialing:		dtmf_sipinfo = Driver::sip.info_negotiate;		if(reg)		{			if(reg->dtmf && !stricmp(reg->dtmf, "info"))				dtmf_sipinfo = true;			else if(reg->dtmf && !stricmp(reg->dtmf, "sipinfo"))				dtmf_sipinfo = true;			else if(reg->dtmf)				dtmf_sipinfo = false;			if(!route)				route = reg->proxy;			snprintf(rbuf, sizeof(rbuf), "sipreg.%d", reg->regid);			setConst("session.registry", rbuf);			setConst("session.uri_server", reg->proxy);			setConst("session.uri_local", reg->contact);                        if(reg->address)                        {                                InetAddress host(reg->address);                                snprintf(cbuf, sizeof(cbuf), "%s",                                        inet_ntoa(host.getAddress()));                                setConst("session.ip_public", cbuf);                        }                        else                                setConst("session.ip_public", lp);		}		else		{			snprintf(buf, sizeof(buf), "sip:anon@%s",				Driver::sip.getLast("interface"));			setConst("session.uri_local", buf);                        setConst("session.ip_local", lp);                        setConst("session.ip_public", lp);		}					to = getSymbol("session.uri_remote");		from = getSymbol("session.uri_local");		if(!route)		{			route = strchr(to, '@');			if(route)				++route;		}		if(!strnicmp(route, "sip:", 4))			route += 4;		snprintf(buf, sizeof(buf), "<sip:%s;lr>", route);		slog.debug("invite %s from %s using %s", to, from, route);		eXosip_lock();		if(eXosip_call_build_initial_invite(&invite, 			(char *)to, (char *)from, buf, "Bayonne Call"))		{			eXosip_unlock();failure:			slog.error("sip: invite invalid");			event->id = DIAL_FAILED;			return false;		}		eXosip_unlock();		cp = Driver::sip.getLast("localip");		data_payload = Driver::sip.data_negotiate;		dtmf_payload = Driver::sip.dtmf_negotiate;		if(parent && !parent->peerLinear())			setEncoding(parent->audioEncoding(), parent->audioFraming());		else if(reg && reg->encoding)			setEncoding(reg->encoding, reg->framing);		switch(info.encoding)		{		case pcm16Stereo:			data_payload = 98;			rtpmap = "a=rtpmap:98 L16/11025/2";			break;		case pcm16Mono:			data_payload = 97;			rtpmap = "a=rtpmap:97 L16/8000/1";			break;		case pcm8Mono:			data_payload = 96;			rtpmap = "a=rtpmap:96 L8/8000/1";			break;		case mulawAudio:			data_payload = 0;			rtpmap = "a=rtpmap:0 PCMU/8000/1";			break;		case alawAudio:			data_payload = 8;			rtpmap = "a=rtpmap:8 PCMA/8000/1";			break;		case gsmVoice:			data_payload = 3;			rtpmap = "a=rtpmap:3 GSM/8000/1";			break;		case speexVoice:			data_payload = 97;			rtpmap = "a=rtpmap:97 SPEEX/8000/1";		default:			break;		}					if(dtmf_payload)                        snprintf(sdp, sizeof(sdp),                                "v=0\r\n"                                "o=bayonne 0 0 IN IP4 %s\r\n"                                "s=call\r\n"                                "c=IN IP4 %s\r\n"                                "t=0 0\r\n"                                "m=audio %d RTP/AVP %d %d\r\n"                                "%s\r\n"				"a=rtpmap:%d telephone-events/8000\r\n",				cp, cp, 				getLocalPort(), data_payload, dtmf_payload,				rtpmap, dtmf_payload);		else			snprintf(sdp, sizeof(sdp),				"v=0\r\n"				"o=bayonne 0 0 IN IP4 %s\r\n"				"s=call\r\n"				"c=IN IP4 %s\r\n"				"t=0 0\r\n"				"m=audio %d RTP/AVP %d\r\n"				"%s\r\n",				cp, cp, 				getLocalPort(), data_payload, 				rtpmap);		setConst("session.rtpmap", rtpmap);		if(dtmf_sipinfo)			setConst("session.dtmfmode", "info");		else if(dtmf_payload)			setConst("session.dtmfmode", "2833");		else			setConst("session.dtmfmode", "none");		eXosip_lock();		osip_message_set_body(invite, sdp, strlen(sdp));		osip_message_set_content_type(invite, "application/sdp");				offhook = true;		setSid();		snprintf(cref, sizeof(cref), "%s@%s",			var_sid, inet_ntoa(local_address.getAddress()));		setConst("session.callref", cref);		cid = eXosip_call_send_initial_invite(invite);		if(cid > 0)			eXosip_call_set_reference(cid, cref);		eXosip_unlock();		if(cid <= 0)			goto failure;		startTimer(atol(Driver::sip.getLast("invite")));		return true;	case CALL_CONNECTED:		startRTP();		setRunning();		return true;	case CALL_ANSWERED:		setState(STATE_PICKUP);		return true;	case CALL_RINGING:		stopTimer();		return true;	case TIMER_EXPIRED:		offhook = false;	default:		return false;	}}bool Session::enterHangup(Event *event){	switch(event->id)	{	case TIMER_EXPIRED:		sipHangup();	default:		break;	}	update_pos = false;	return false;}bool Session::enterRecord(Event *event){	switch(event->id)	{	case ENTER_STATE:		audio.record(state.audio.list[0], state.audio.mode, state.audio.note);		update_pos = true;		if(!audio.isOpen())		{			slog.error("%s: audio file access error", logname);                        error("no-files");                        setRunning();			return true;		}		rtp->setSink(&audio, state.audio.total);		return false;	default:		return false;	}}bool Session::enterPlay(Event *event){	switch(event->id)	{	case AUDIO_IDLE:		if(!Driver::sip.audio_timer)			return false;		startTimer(Driver::sip.audio_timer);		return true;	case ENTER_STATE:		if(state.audio.mode == Audio::modeReadAny)			update_pos = false;		else			update_pos = true;		audio.play(state.audio.list, state.audio.mode);		if(!audio.isOpen())		{                	slog.error("%s: audio file access error", logname);                	error("no-files");			setRunning();			return true;		}		rtp->setSource(&audio);				return false;	default:		return false;	}}bool Session::enterPickup(Event *event){	if(event->id == ENTER_STATE)	{		offhook = true;		startRTP();		startTimer(driver->getPickupTimer());		return true;	}	else if(event->id == CALL_ACCEPTED)	{		startTimer(Driver::sip.accept_timer);		return true;	}	return false;}bool Session::enterTone(Event *event){	if(event->id == ENTER_STATE && audio.tone)		rtp->setTone(audio.tone);	return false;}bool Session::enterXfer(Event *event){	osip_message_t *refer;	int rtn;	switch(event->id)	{	case DIAL_FAILED:		event->id = DIAL_INVALID;		return false;	case ENTER_STATE:		eXosip_lock();		eXosip_call_build_refer(did, (char *)state.url.ref, &refer);		rtn = eXosip_call_send_request(did, refer);		eXosip_unlock();		if(!rtn)			return true;		event->errmsg = "transfer-invalid";		event->id = ERROR_STATE;		return false;	case STOP_DISCONNECT:		setState(STATE_HANGUP);		return true;	default:		return false;	}	}void Session::clrAudio(void){	if(rtp)	{		rtp->setSource(NULL);		rtp->setTone(NULL);	}	if(audio.isOpen() && update_pos)	{		audio.getPosition(audio.var_position, 12);		update_pos = false;	}	audio.cleanup();}void Session::sipHangup(void){	eXosip_lock();	eXosip_call_terminate(cid, did);	eXosip_unlock();	stopRTP();	offhook = false;}timeout_t Session::getToneFraming(void){	return info.framing;}const char *Session::audioExtension(void){	return Audio::getExtension(info.encoding);}timeout_t Session::audioFraming(void){	return info.framing;}const char *Session::audioEncoding(void){	return Audio::getName(info.encoding);}const char *Session::checkAudio(bool live){	audio.libext = ".au";	switch(info.encoding)	{	case alawAudio:		audio.libext = ".al";		break;	case gsmVoice:		if(!audio.extension)			audio.extension = ".gsm";		audio.libext = ".gsm";	default:		break;	}	if(!audio.extension)		audio.extension = ".au";	if(audio.encoding == unknownEncoding)		audio.encoding = info.encoding;		if(!live)	{		if(!audio.framing)			audio.framing = 10;		return NULL;	}	audio.framing = info.framing;	if(audio.encoding != info.encoding)		return "unsupported audio format";	return NULL;}	bool Session::peerAudio(Encoded encoded){	enter();	if(!peer || !rtp || rtp->source || !isJoined())	{		leave();		return false;	}	rtp->peerAudio(encoded, peer->peerLinear());	leave();	return true;}			} // namespace

⌨️ 快捷键说明

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