【Freeswitch从入门到精通】二、初识Freeswitch
【Freeswitch从入门到精通】二、初识Freeswitch
- 1、入门术语
- 1.1 常见短语
- 1.2 Call Legs
- 2、历史
- 3、启动
- 4、dialplan 路由表
- 4.1 测试Demo路由功能
- 4.2 default.xml详细配置
- 5、directory 用户管理
- 6、chatplan 聊天模块
- 7、api 和 app
- 7.1 APP
- 8、呼叫字符串
- 9、安装部署
- 10、启动
- 10.1 生产环境启动
- 10.2 测试环境启动
- 11、变量
- 11.1 主叫配置变量
- 11.2 普通变量
- 11.3 预处理变量
- 12 拨打流程
- 12.1 originate user/1000 &echo
- 12.2 originate user/1000 9196 XML default
1、入门术语
1.1 常见短语
VoIP: Voice over Internet Protocol 基于IP的语音传输
SIP: Session Initiation Protocol 会话初始协议
PSTN:Public Switched Telephone Network 公共交换电话网络
MPL:Mozilla Public License 1998年初Netscape的Mozilla小组为其开源软件项目设计的软件许可证,在MPL许可证中对“发布”的定义是“以源代码方式发布的文件”。
IP-PBX Private Branch eXchange 用户级交换机
NAT:Network Address Translation 网络地址转换
OSTAG: Open Source Telephony Advancement Group 开源电话学进步组
B2BUA: 背靠背的代理
PBX: Private Branch Exchange,用户级交换机,即公司内部使用的电话业务网络,系统内部分机用户分享一定数量的外线。
ITSP:我们的网络电话服务提供商(ITSP),会把拨打DID号码的电话发送到我们的"external" SIP profile(演示配置中的5080端口)。我们将使用"external" SIP profile来发送出局呼叫给ITSP,连接外部世界。在拨号方案中,我们将用一种"gateway"封装的语法来处理连接ITSP可能需要的鉴权过程。
1.2 Call Legs
认识A leg,与B leg
2、历史
2005年开始写,2006年发布第一个版本
3、启动
freeswitch -nonat4、dialplan 路由表
4.1 测试Demo路由功能
4.2 default.xml详细配置
下面为dialplan/default.xml的详细配置:
<extension name="echo"> # 路由名称<condition field="destination_number" expression="^9196$"> # filed是被叫号码, expression是正则匹配,被叫号码匹配上则继续<action application="answer"/> # 执行回复,相当于电话输入完拨号后的确认按钮<action application="echo"/> # 执行回声,echo相当于回声</condition></extension>freeswitch就是和application的沟通name 名称任意,只做标识,不做逻辑。condition 标识条件,field变量,expression正则表达式action 动作,application APP,data 参数freeswitch命令:regex:regex 1234 | \d+ 匹配返回true,否则false<extension name="unloop"> <condition field="${unroll_loops}" expression="^true$"/> # unroll_loops 全局变量var.xmls中,默认为true<condition field="${sip_looped_call}" expression="^true$"> # <action application="deflect" data="${destination_number}"/> # deflect 防止死循环</condition></extension><extension name="tod_example" continue="true"> # time of the day 时间例子 ;continue 不管是否匹配,其他扩展也会继续走。<condition wday="2-6" hour="9-18"> # 周,时<action application="set" data="open=true"/> # set 设置变量open为true。</condition></extension><extension name="global-intercept"> # 全局代接拦截,应用场景为:同公司其他同事没在工位,但是有电话打过来,你又懒得过去接,你可以使用自己的电话进行拦截接听,下方表达式表示,你拨打电话886就可以接入该电话。<condition field="destination_number" expression="^886$"> # 匹配886号码<action application="answer"/> # 执行answer,相当于电话按了确认键。应答<action application="intercept" data="${hash(select/${domain_name}-last_dial_ext/global)}"/> # intercept代接, hash()查找哈希表,domain_name 为当前的域,global全局,最终结果为一个uuid,获取真在振铃的通话<action application="sleep" data="2000"/> # 暂停2秒钟</condition></extension><extension name="group-intercept"> # 同组代打<condition field="destination_number" expression="^\*8$"> # 拨打*8<action application="answer"/><action application="intercept" data="${hash(select/${domain_name}-last_dial_ext/${callgroup})}"/> # 获取当前用户组,每个用户有默认组或者新建组<action application="sleep" data="2000"/></condition></extension><extension name="intercept-ext"> # 代接指定分级<condition field="destination_number" expression="^\*\*(\d+)$"> # 拨打**分机号,就可以代接了<action application="answer"/><action application="intercept" data="${hash(select/${domain_name}-last_dial_ext/$1)}"/> # $1为匹配到的电话号码<action application="sleep" data="2000"/></condition></extension><extension name="redial"> # 重拨<condition field="destination_number" expression="^(redial|870)$"> # 按了重拨或者870<action application="transfer" data="${hash(select/${domain_name}-last_dial/${caller_id_number})}"/> # transfer转接, 以主键号码存key,然后获取号码</condition></extension><extension name="global" continue="true"> # 执行此扩展后继续执行其他扩展<condition field="${call_debug}" expression="^true$" break="never"> # call_debug 如果为true,从不break<action application="info"/> # 当前呼叫的所有的info变量都输出。</condition># 如果默认密码为1234,就会输出提醒修改密码。<condition field="${default_password}" expression="^1234$" break="never"><action application="log" data="CRIT WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING "/><action application="log" data="CRIT Open $${conf_dir}/vars.xml and change the default_password."/><action application="log" data="CRIT Once changed type 'reloadxml' at the console."/><action application="log" data="CRIT WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING "/><action application="sleep" data="10000"/></condition><condition field="${rtp_has_crypto}" expression="^($${rtp_sdes_suites})$" break="never"> # 如果加密rtp的话, $$为只获取一次值,$为每次都获取值<action application="set" data="rtp_secure_media=true"/> #设置变量为true,为加密通话<!-- Offer SRTP on outbound legs if we have it on inbound. --><!-- <action application="export" data="rtp_secure_media=true"/> --> # 让呼出channel也加密</condition><condition field="${endpoint_disposition}" expression="^(DELAYED NEGOTIATION)"/> # 如果匹配 晚协商(freeswitch后面改的晚协商)<condition field="${switch_r_sdp}" expression="(AES_CM_128_HMAC_SHA1_32|AES_CM_128_HMAC_SHA1_80)" break="never"> # 远程sdp如果具有这样的加密方式的话,执行加密为true,即安全方式rtp<action application="set" data="rtp_secure_media=true"/><!-- Offer SRTP on outbound legs if we have it on inbound. --><!-- <action application="export" data="rtp_secure_media=true"/> --> # 同上,呼出channel也加密</condition><condition> # 绝对匹配<action application="hash" data="insert/${domain_name}-spymap/${caller_id_number}/${uuid}"/> # 插入,主叫号码作为key,uuid作为值插入<action application="hash" data="insert/${domain_name}-last_dial/${caller_id_number}/${destination_number}"/> # 设置当前拨号号码,用于重拨870<action application="hash" data="insert/${domain_name}-last_dial/global/${uuid}"/> # 全局代接<action application="export" data="RFC2822_DATE=${strftime(%a, %d %b %Y %T %z)}"/> # export 输出格式化时间</condition></extension><extension name="eavesdrop"> # 监听<condition field="destination_number" expression="^88(\d{4})$|^\*0(.*)$"> # 拨打88+数字<action application="answer"/> <action application="eavesdrop" data="${hash(select/${domain_name}-spymap/$1$2)}"/> # 获取监听号码uuid,并执行监听app</condition></extension><extension name="eavesdrop"><condition field="destination_number" expression="^779$"> <action application="answer"/><action application="set" data="eavesdrop_indicate_failed=tone_stream://%(500, 0, 320)"/> # 监听失败声音<action application="set" data="eavesdrop_indicate_new=tone_stream://%(500, 0, 620)"/> # 新监听声音<action application="set" data="eavesdrop_indicate_idle=tone_stream://%(250, 0, 920)"/> # 什么也听不到,放的声音<action application="eavesdrop" data="all"/> # 输入*听下一个电话</condition></extension><extension name="call_return"> # 回拨<condition field="destination_number" expression="^\*69$|^869$|^lcr$"><action application="transfer" data="${hash(select/${domain_name}-call_return/${caller_id_number})}"/></condition></extension><extension name="del-group"> # 将自己移除组中<condition field="destination_number" expression="^80(\d{2})$"><action application="answer"/><action application="group" data="delete:$1@${domain_name}:${sofia_contact(${sip_from_user}@${domain_name})}"/><action application="gentones" data="%(1000, 0, 320)"/> # 删除成功,返回一个声音</condition></extension><extension name="add-group"> # 将自己加入组中<condition field="destination_number" expression="^81(\d{2})$"><action application="answer"/><action application="group" data="insert:$1@${domain_name}:${sofia_contact(${sip_from_user}@${domain_name})}"/><action application="gentones" data="%(1000, 0, 640)"/></condition></extension><extension name="call-group-simo"> # 同时呼叫,也叫同震<condition field="destination_number" expression="^82(\d{2})$"><action application="bridge" data="{leg_timeout=15,ignore_early_media=true}${group(call:$1@${domain_name})}"/> # 呼叫超时15秒</condition></extension><extension name="call-group-order"> # 顺序呼叫,也叫顺震<condition field="destination_number" expression="^83(\d{2})$"><action application="bridge" data="{leg_timeout=15,ignore_early_media=true}${group(call:$1@${domain_name}:order)}"/></condition></extension><extension name="extension-intercom"> # 对某些电话进行自动广播,需要话机支持自动应答<condition field="destination_number" expression="^8(10[01][0-9])$"> <action application="set" data="dialed_extension=$1"/><action application="export" data="sip_auto_answer=true"/> # 指定呼叫号码自动应答<action application="bridge" data="user/${dialed_extension}@${domain_name}"/> # 桥连接号码,直接喊话</condition></extension><extension name="Local_Extension"> # 本地分级<condition field="destination_number" expression="^(10[01][0-9])$"> # 默认分机号<action application="export" data="dialed_extension=$1"/><!-- bind_meta_app can have these args <key> [a|b|ab] [a|b|o|s] <app> --><action application="bind_meta_app" data="1 b s execute_extension::dx XML features"/> # 绑定按键,,*1绑定 features xml分支,可以通过这个转到其他电话线路中。盲转。<action application="bind_meta_app" data="2 b s record_session::$${recordings_dir}/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/> # 用户在通话中按了*2键, 绑定在b上,s开始,recore_session:录音文件路径,进行录音。<action application="bind_meta_app" data="3 b s execute_extension::cf XML features"/> # 转义到会议中<action application="bind_meta_app" data="4 b s execute_extension::att_xfer XML features"/> # 协商转,1,2,3,4 可以协商转也可以三方通话<action application="set" data="ringback=${us-ring}"/> # 电弧接通前的设置回铃音,这是美国回铃音<action application="set" data="transfer_ringback=$${hold_music}"/> # 电话接通后的回铃音,保持通话音<action application="set" data="call_timeout=30"/> # 呼叫超时时间<!-- <action application="set" data="sip_exclude_contact=${network_addr}"/> --><action application="set" data="hangup_after_bridge=true"/> # bridge成功后就挂机。<!--<action application="set" data="continue_on_fail=NORMAL_TEMPORARY_FAILURE,USER_BUSY,NO_ANSWER,TIMEOUT,NO_ROUTE_DESTINATION"/> --> # 默认呼叫失败的状态<action application="set" data="continue_on_fail=true"/> # <action application="hash" data="insert/${domain_name}-call_return/${dialed_extension}/${caller_id_number}"/> # 插入主叫号码<action application="hash" data="insert/${domain_name}-last_dial_ext/${dialed_extension}/${uuid}"/> # 插入最后呼叫分机号<action application="set" data="called_party_callgroup=${user_data(${dialed_extension}@${domain_name} var callgroup)}"/> # 获取被叫的组<action application="hash" data="insert/${domain_name}-last_dial_ext/${called_party_callgroup}/${uuid}"/> # 插入uuid<action application="hash" data="insert/${domain_name}-last_dial_ext/global/${uuid}"/> # 插入globaluuid<!--<action application="export" data="nolocal:rtp_secure_media=${user_data(${dialed_extension}@${domain_name} var rtp_secure_media)}"/>--><action application="hash" data="insert/${domain_name}-last_dial/${called_party_callgroup}/${uuid}"/> # 给组插入uuid<action application="bridge" data="user/${dialed_extension}@${domain_name}"/> # 产生一条channel,user/1000为呼叫字符串,从location中获取context被叫地址。此时bridge为阻塞的,直到被叫挂机或其他情况,才关闭阻塞(受上面hangup_after_bridge和continue_on_fail影响)如果hangup_after_bridge挂机,那么都结束,如果b不在线或没正常接听,continue_on_fail=true=true那么继续往下走。<action application="answer"/> # 如果B接听失败,freeswitch自动接通<action application="sleep" data="1000"/><action application="bridge" data="loopback/app=voicemail:default ${domain_name} ${dialed_extension}"/> # 用户无法接听后,进入当前用户语音信箱,进行留言。 # voicemail是一个app,default是其中一个配置</condition></extension><extension name="Local_Extension_Skinny"> # 思科是瘦客户端,每拨一个号码都会传到freeswitch。上面的就是胖客户端,只有拨完号才会传个freeswitch。<condition field="destination_number" expression="^(11[01][0-9])$"><action application="set" data="dialed_extension=$1"/><action application="export" data="dialed_extension=$1"/><action application="set" data="call_timeout=30"/><action application="set" data="hangup_after_bridge=true"/><action application="set" data="continue_on_fail=true"/><action application="bridge" data="skinny/internal/${destination_number}"/><action application="answer"/><action application="sleep" data="1000"/><action application="bridge" data="loopback/app=voicemail:default ${domain_name} ${dialed_extension}"/></condition></extension><extension name="group_dial_sales"> # directoryu中有sales,support,billing这些组。通过呼叫组号,来呼叫组内全部,这些组是静态加的,而之前的81系列是动态加的。<condition field="destination_number" expression="^2000$"><action application="bridge" data="${group_call(sales@${domain_name})}"/></condition></extension><extension name="group_dial_support"><condition field="destination_number" expression="^2001$"><action application="bridge" data="group/support@${domain_name}"/></condition></extension><extension name="group_dial_billing"><condition field="destination_number" expression="^2002$"><action application="bridge" data="group/billing@${domain_name}"/></condition></extension><!-- voicemail operator extension --># 语音信箱<extension name="operator"><condition field="destination_number" expression="^(operator|0)$"><action application="set" data="transfer_ringback=$${hold_music}"/><action application="transfer" data="1000 XML features"/></condition></extension><!-- voicemail main extension --> <extension name="vmain"><condition field="destination_number" expression="^vmain$|^4000$|^\*98$"><action application="answer"/><action application="sleep" data="1000"/><action application="voicemail" data="check default ${domain_name}"/> # 检查voicemain,会进入语音信箱应用。</condition></extension><!--This extension is used by mod_portaudio so you can pa call sip:someone@example.commod_portaudio will pass the entire string to the dialplan for routing.--> 直接呼叫sip的地址<extension name="sip_uri"><condition field="destination_number" expression="^sip:(.*)$"><action application="bridge" data="sofia/${use_profile}/$1"/></condition></extension><!--start a dynamic conference with the settings of the "default" conference profile in conference.conf.xml--> 进入会议<extension name="nb_conferences"><condition field="destination_number" expression="^(30\d{2})$"><action application="answer"/><action application="conference" data="$1-${domain_name}@default"/></condition></extension><extension name="wb_conferences"><condition field="destination_number" expression="^(31\d{2})$"><action application="answer"/><action application="conference" data="$1-${domain_name}@wideband"/></condition></extension><extension name="uwb_conferences"> # 32k语音<condition field="destination_number" expression="^(32\d{2})$"><action application="answer"/><action application="conference" data="$1-${domain_name}@ultrawideband"/></condition></extension><!-- MONO 48kHz conferences --> # 48k语音<extension name="cdquality_conferences"><condition field="destination_number" expression="^(33\d{2})$"><action application="answer"/><action application="conference" data="$1-${domain_name}@cdquality"/></condition></extension><!-- STEREO 48kHz conferences / Video MCU --> 视频会议<extension name="cdquality_stereo_conferences"><condition field="destination_number" expression="^(35\d{2}).*?-screen$"> # 共享桌面-screen.<action application="answer"/><action application="send_display" data="FreeSWITCH Conference|$1"/><action application="set" data="conference_member_flags=join-vid-floor"/><action application="conference" data="$1@video-mcu-stereo"/></condition></extension><extension name="conference-canvases" continue="true"> # 都是通过canvases实现画布来实现视频会议,多方容屏<condition field="destination_number" expression="(35\d{2})-canvas-(\d+)"><action application="push" data="conference_member_flags=second-screen"/> # 进来,把自己贴到哪个画布<action application="set" data="video_initial_watching_canvas=$2"/> # 进来看哪个画布<action application="transfer" data="$1"/></condition></extension><extension name="conf mod"> # 会议管理员,只设置了标志<condition field="destination_number" expression="^6070-moderator$"> <action application="answer"/><action application="set" data="conference_member_flags=moderator"/><action application="conference" data="$1-${domain_name}@video-mcu-stereo"/></condition></extension><!-- dial the FreeSWITCH conference via SIP--><extension name="freeswitch_public_conf_via_sip"><condition field="destination_number" expression="^9(888|8888|1616|3232)$"><action application="export" data="hold_music=silence"/><!--This will take the SAS from the b-leg and send it to the display on the a-leg phone.Known working with Polycom and Snom maybe others.--><!--<action application="set" data="exec_after_bridge_app=${sched_api(+4 zrtp expand uuid_display ${uuid} \${uuid_getvar(\${uuid_getvar(${uuid} signal_bond)} zrtp_sas1_string )} \${uuid_getvar(\${uuid_getvar(${uuid} signal_bond)} zrtp_sas2_string )} )}"/><action application="export" data="nolocal:zrtp_secure_media=true"/>--><action application="bridge" data="sofia/${use_profile}/$1@conference.freeswitch.org"/></condition></extension><!--This extension will start a conference and invite a group.At anytime the participant can dial *2 to bridge directly to the boss.All other callers are then hung up on.--><extension name="mad_boss_intercom"> # 疯狂的老板,boss 控制会议<condition field="destination_number" expression="^0911$"><action application="set" data="conference_auto_outcall_caller_id_name=Mad Boss1"/><action application="set" data="conference_auto_outcall_caller_id_number=0911"/><action application="set" data="conference_auto_outcall_timeout=60"/><action application="set" data="conference_utils_auto_outcall_flags=mute"/><action application="set" data="conference_auto_outcall_prefix={sip_auto_answer=true,execute_on_answer='bind_meta_app 2 a s1 transfer::intercept:${uuid} inline'}"/><action application="set" data="sip_exclude_contact=${network_addr}"/><action application="conference_set_auto_outcall" data="${group_call(sales)}"/> # 整个组中都响应呼叫<action application="conference" data="madboss_intercom1@default+flags{endconf|deaf}"/> # flags boss退出,整个会议结束</condition></extension><!--This extension will start a conference and invite a few of people.At anytime the participant can dial *2 to bridge directly to the boss.All other callers are then hung up on.--><extension name="mad_boss_intercom"><condition field="destination_number" expression="^0912$"><action application="set" data="conference_auto_outcall_caller_id_name=Mad Boss2"/><action application="set" data="conference_auto_outcall_caller_id_number=0912"/><action application="set" data="conference_auto_outcall_timeout=60"/><action application="set" data="conference_utils_auto_outcall_flags=mute"/><action application="set" data="conference_auto_outcall_prefix={sip_auto_answer=true,execute_on_answer='bind_meta_app 2 a s1 transfer::intercept:${uuid} inline'}"/><action application="set" data="sip_exclude_contact=${network_addr}"/><action application="conference_set_auto_outcall" data="loopback/9664"/><action application="conference" data="madboss_intercom2@default+flags{endconf|deaf}"/></condition></extension><!--This extension will start a conference and invite several people upon entering --><extension name="mad_boss"><condition field="destination_number" expression="^0913$"><!--These params effect the outcalls made once you join--><action application="set" data="conference_auto_outcall_caller_id_name=Mad Boss"/><action application="set" data="conference_auto_outcall_caller_id_number=0911"/><action application="set" data="conference_auto_outcall_timeout=60"/><action application="set" data="conference_utils_auto_outcall_flags=none"/><!--<action application="set" data="conference_auto_outcall_announce=say:You have been called into an emergency conference"/>--><!--Add as many of these as you need, These are the people you are going to call--><action application="conference_set_auto_outcall" data="loopback/9664"/><action application="conference" data="madboss3@default"/></condition></extension><!-- a sample IVR --><extension name="ivr_demo"><condition field="destination_number" expression="^5000$"><action application="answer"/><action application="sleep" data="2000"/><action application="ivr" data="demo_ivr"/></condition></extension><!-- Create a conference on the fly and pull someone in at the same time. --><extension name="dynamic_conference"># 参加会议,可以拉另外一个人进来<condition field="destination_number" expression="^5001$"><action application="conference" data="bridge:mydynaconf:sofia/${use_profile}/1234@conference.freeswitch.org"/></condition></extension><extension name="rtp_multicast_page"> # 广播应用,拨打7243进行广播<condition field="destination_number" expression="^pagegroup$|^7243$"><action application="answer"/><action application="esf_page_group"/></condition></extension><!--Parking extensions... transferring calls to 5900 will park them in a queue.--># 有人在队列,可以一个一个获取出来<extension name="park"> # 队列中加入一个人<condition field="destination_number" expression="^5900$"><action application="set" data="fifo_music=$${hold_music}"/><action application="fifo" data="5900@${domain_name} in"/></condition></extension><!--Parking pickup extension. Calling 5901 will pickup the call.--> # 队列中去除一个人<extension name="unpark"><condition field="destination_number" expression="^5901$"><action application="answer"/><action application="fifo" data="5900@${domain_name} out nowait"/></condition></extension><!--Valet park retrieval, works with valet_park extension below.Retrieve a valet parked call by dialing 6000 + park number + #--> 有人呼叫进来,放到一个位置,如果又有一个人进来,那就放到同一个位置<extension name="valet_park"><condition field="destination_number" expression="^(6000)$"><action application="answer"/><action application="valet_park" data="valet_parking_lot ask 1 11 10000 ivr/ivr-enter_ext_pound.wav"/></condition></extension><!--Valet park 6001-6099. Blind x-fer to 6001, 6002, etc. to valet park the call.Dial 6001, 6002, etc. to retrieve a call that is already valet parked.After call is retrieved, park extension is free for another call.--><extension name="valet_park"><condition field="destination_number" expression="^((?!6000)60\d{2})$"><action application="answer"/><action application="valet_park" data="valet_parking_lot $1"/></condition></extension># 传真<extension name="fax_receive"><condition field="destination_number" expression="^9178$"><action application="answer" /><action application="playback" data="silence_stream://2000"/><action application="rxfax" data="$${temp_dir}/rxfax.tif"/> # 收传真<action application="hangup"/></condition></extension><extension name="fax_transmit"><condition field="destination_number" expression="^9179$"><action application="txfax" data="$${temp_dir}/txfax.tif"/> # 发传真<action application="hangup"/></condition></extension># 视频录制和回放,older了。<extension name="video_record"><condition field="destination_number" expression="^9193$"><action application="answer"/><action application="record_fsv" data="$${temp_dir}/testrecord.fsv"/></condition></extension><extension name="video_playback"><condition field="destination_number" expression="^9194$"><action application="answer"/><action application="play_fsv" data="$${temp_dir}/testrecord.fsv"/></condition></extension># 回声设置<extension name="delay_echo"> # 延迟回声,通常用于测试<condition field="destination_number" expression="^9195$"><action application="answer"/><action application="delay_echo" data="5000"/></condition></extension><extension name="echo"><condition field="destination_number" expression="^9196$"><action application="answer"/><action application="echo"/></condition></extension><extension name="milliwatt"><condition field="destination_number" expression="^9197$"><action application="answer"/><action application="playback" data="{loops=-1}tone_stream://%(251,0,1004)"/></condition></extension><extension name="tone_stream"><condition field="destination_number" expression="^9198$"><action application="answer"/><action application="playback" data="{loops=10}tone_stream://path=${conf_dir}/tetris.ttml"/></condition></extension><!-- install zrtp_agent.lua into scripts (ZRTP == 9787) --><extension name="zrtp_enrollement"><condition field="destination_number" expression="^9787$"><action application="lua" data="zrtp_agent.lua"/></condition></extension><!--You will no longer hear the bong tone. The wav file is playing stating the call is secure.The file will not play unless you have both TLS and SRTP active.--><extension name="hold_music"><condition field="destination_number" expression="^9664$"/><condition field="${rtp_has_crypto}" expression="^(AES_CM_128_HMAC_SHA1_32|AES_CM_128_HMAC_SHA1_80)$"><action application="answer"/><action application="execute_extension" data="is_secure XML features"/><action application="playback" data="$${hold_music}"/><anti-action application="set" data="zrtp_secure_media=true"/><anti-action application="answer"/><anti-action application="playback" data="silence_stream://2000"/><anti-action application="execute_extension" data="is_zrtp_secure XML features"/><anti-action application="playback" data="$${hold_music}"/></condition></extension><extension name="laugh break"><condition field="destination_number" expression="^9386$"><action application="answer"/><action application="sleep" data="1500"/><action application="playback" data="phrase:funny_prompts"/><action application="hangup"/></condition></extension>dialplan三要素 extension dialplan类型 contextoriginate 内部主动发起呼叫 originate user/1000 9196 # 9196 默认是9196 XML default, 这句话指从freeswitch内部主动给1000用户发起会话,使用9196的dialplan规则。originate user/1000 &echo # 使用&标识直接执行application originate user/1000 echo inline # inline dialplan 是可以直接执行application originate user/1000 playback:/1.wav,record:/2.wav inline # inline可以指定多个application;application之间用逗号分割,application与参数之间用冒号分割。uuid_transfer <uuid> playback:/1.wav,record:/2.wav inline # 将任意会话转接到当前dialplan中电话路由怎么走? 找context, 电话拨通使用user下的user_context指定,sip网关下,使用context指定。 transfer 被叫号码 使用跟哪个dialplan(XML,enum,inline) context uuid_transfer <uuid> 9196 XML default呼叫字符串示例: originate user/1000 &bridge(user/1001) 先呼叫1000,再呼叫1001,那么1000和1001就通了 originate user/1000 1001 先呼叫1000,1001进入路由表先查再拨 originate loopback/1000 1001 伪造假的channle,进入dialplan先查再拨。bridge 不能answer,1000-->freeswitch bridge --> 1001,answer是给freeswitch的。 conference 会议自己内部有answer5、directory 用户管理
default目录下,配置用户,新增,修改
每个用户中,可以修改默认密码,不然会被警告
6、chatplan 聊天模块
注册:是用于被叫用的,用于freeswitch找到被叫用户。主叫其实不需要。
7、api 和 app
api:freeswitch 命令
app: application
7.1 APP
使用fs_client
8、呼叫字符串
sofia 电话@网关 &echo
user/1000 # user 类型,1000 用户,呼叫1000用户 sofia/gateway/gw1/186xxxxxx # sofia 网关类型, gw1网关名称, 186 电话;注册网关 sofia/external/186xxxx@192.15.. external profile名称;这是中级对接 sofia/internal/186xxx@ip:port 不同于external,是端口不一致 sofia/internal/1000%10.0.0.1 # %后接域,通过域找号码 user/1000@10.0.0.1 originate freeswitch内部发起呼叫 originate user/1000 &echo originate user/1000 &bridge(user/10001)bridge 桥app
<action application='bridgge' data='user/1000'/>conference 会议
conference 3000 dial user/1000 originate {local_addr=192.168.1.1,local_port=4444,remote_addr=xxx,remote_port=xxxx,codec=PCMU,pt=0,rate=8000 }rtp &playback(tmp/xxx)show endpoint 查看呼叫字符串
文件:directory/default.xml
<params><param name="dial-string" value="{^^:sip_invite_domain=${dialed_domain}:presence_id=${dialed_user}@${dialed_domain}}${sofia_contact(*/${dialed_user}@${dialed_domain})},${verto_contact(${dialed_user}@${dialed_domain})}"/><!-- These are required for Verto to function properly --><param name="jsonrpc-allowed-methods" value="verto"/><!-- <param name="jsonrpc-allowed-event-channels" value="demo,conference,presence"/> --> </params>origination_caller_id_number=1100 设置主叫号码,freeswitch默认为00000000
origination_caller_id_name = 'gaofei' 设置主叫名称
hupall 关闭所有的电话
9、安装部署
git clone xxx.git
make samples # 编译默认配置文件
/user/local/freeswitch/bin/freeswitch -nonat -nc # 启动freeswitch,nonat无网络,nc后台启动(用于生产环境)
status 查看状态
|------------------------------------------------------------ UP 0 years, 0 days, 0 hours, 0 minutes, 22 seconds, 794 milliseconds, 26 microseconds FreeSWITCH (Version 1.10.7 883d2cb662 64bit) is ready 0 session(s) since startup 0 session(s) - peak 0, last 5min 0 # peak表示最大多少个session, last 5min 最后5分钟多少个 0 session(s) per Sec out of max 30, peak 0, last 5min 0 1000 session(s) max # 默认支持多少个session min idle cpu 0.00/85.44 |-----------------------------------------------------------sofia status 查看sofia当前的状态
!-----------------------------Name Type Data State =================================================================================================external-ipv6 profile sip:mod_sofia@[::1]:5080 RUNNING (0)192.168.123.197 alias internal ALIASEDexternal profile sip:mod_sofia@*.*.*.*:5080 RUNNING (0)external::example.com gateway sip:joeuser@example.com NOREGinternal-ipv6 profile sip:mod_sofia@[::1]:5060 RUNNING (0)internal profile sip:mod_sofia@*.*.*.*:5060 RUNNING (0) 4 profiles 1 alias !------------------------------10、启动
10.1 生产环境启动
/usr/local/freeswitch/bin/freeswitch -u freeswitch -g freeswitch -nonat -ncwait
/usr/local/freeswitch/bin/fs_cli 进行控制台介入
10.2 测试环境启动
/usr/local/freeswitch/bin/freeswitch
11、变量
freeswitch中有一套变量规则,调用变量使用${变量名}, ${方法名()}
在xml配置文件中,可以通过set来进行变量的设置
变量相关命令:
eval $${变量名} # 获取全局变量值,eg:eval $${sound_prefix}
show interfaces # 获取全局接口
global_setvar 变量名=变量值 设置全局变量
global_getvar 变量名 获取全局变量值
11.1 主叫配置变量
在extension 下的 condition 中,对于 主叫配置变量 来说,可以直接使用了,并不用$符号来修饰。
username dialplan caller_id_name 主叫名称 caller_id_number 主叫号码 callee_id_name callee_id_number network_addr ani aniii rdnis destination_number source uuid context11.2 普通变量
Freeswitch的变量基本上可以用 ${变量名} 来表示。通过app-set来进行变量的赋值,创建。
注:app set中左侧变量名也不需要使用$符号,右侧需要。
上图中,$1表示正则匹配到的第一个括号中的值。
11.3 预处理变量
预处理变量的引用,使用$${变量名}来表示,他们不是真正的变量,而是只读的变量。它们由一个FreeSWITCH配置文件(/usr/local/freeswitch/conf/vars.xml)分配,然后在启动时替换。
注:如果修改了vars.xml里的预处理变量值,你必须重启FreeSWITCH才能让它生效(只是重载XML配置而没有重启FreeSWITCH是不够的)。
此类变量有(还有更多):
Hostname local_ip_v4 local_mask_v4 local_ip_v6 switch_serial base_dir recordings_dir sound_prefix sounds_dir conf_dir log_dir run_dir db_dir mod_dir htdocs_dir script_dir temp_dir grammar_dir certs_dir storage_dir cache_dir core_uuid zrtp_enabled nat_public_addr nat_private_addr nat_type12 拨打流程
12.1 originate user/1000 &echo
查找user/1000,直接呼叫用户,并执行app echo
12.2 originate user/1000 9196 XML default
查找user/1000, 直接呼叫用户,并执行 路由表,context 为default,diaplan为XML,extension-destination_number=9196(也代表extension)的内容。
注:originate 参数列表
其实call_url 这儿user/1000, fs会去用户下找context=default。然后去dialplan中找context值为default的路由。
如果call_url为一个sip路径,那么需要去找对应sip_profiles/internal 或者 external,在里面找对应的context。如下:sofia status中查找data路径,然后对应profile的name,再去dialplan中找context值为public的路由。
总结
以上是生活随笔为你收集整理的【Freeswitch从入门到精通】二、初识Freeswitch的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 三天学会MySQL - MySQL数据库
- 下一篇: C语言生成n个随机坐标,c语言如何生成随