esl
api/bgapi调用逻辑
应用程序以普通方式对api的调用,是顺序、阻塞的,直到api执行完成才返回。
应用程序以bgapi的方式调用,是异步的,mod_event_sockt收到请求后,启动执行线程,直接返回。
如下所示,是api普通方式调用的时序图:
Application调用逻辑
应用程序调用dialplan相关的应用,都是异步模式,mod_event_socket收到请求之后,将请求放入到session的私有队列,接口直接返回。
获取事件
1. mod_event_socket启动的时候会订阅FreeSWITCH的所有事件,产生一个NODE_EVENT_QUEUE,mod_event_socket会根据不同的客户端订阅,给不同的客户端返回需要的事件;
2. 平台产生事件之后,会将事件放到mod_event_socket的NODE_EVENT_QUEUE队列,mod_event_socket会遍历每个连接,将每个事件推送给订阅该事件的客户端;
3. 客户端调用esl接口获取事件,esl库首先根据check_q变量的设置,判断是否优先从自己的race_event队列(调用esl相关接口esl_send_recv执行程序的时候,为了获取相关api的返回值,esl需要从服务端等待消息,此过程中可能获取到了事件,则esl会将事件放入到race_event中)中获取,如果race_event没有,则首先从自己的缓存packet_buf中取数据处理,如果取到合适的数据直接返回,否则调用socket函数recv,按固定超时时间从mod_event_socket上获取事件,将获取到的内容放入到packet_buf。
媒体应用处理
同步
典型application/api:playback、play_and_get_digist、read、record、park
以上这些应用,内部会循环调用switch_ivr_parse_all_events处理所有的dptool的请求,直到放音、录音、unpark等操作完成,因此不要在这些应用没有执行完的时候,继续执行其他应用。
如:在上次playback未完成的时候,又进行一次playback,这样会优先进行第二次playback,然后再进行第一次playback,形成了递归;playback和record未完成操作直接调用,操作也类似,下图描述了一个递归的调用(在放音的过程中,调用record,如果record不被打断,则放音永远无法放出声音):
异步/订阅
典型application/api:uuid_record、record_session、start_dtmf。
以上这些应用,会给媒体流的read,增加hook(media_bug),不会阻塞媒体流。
典型场景
客户呼入
1) 客户呼入,mod_sofia会受到invite消息;
2) Mod_sofia获取一个session,启动session处理线程(session状态机);
3) Mod_sofia收到状态改变消息,设置session未INIT状态,后转为ROUTING状态;
4) Session状态机,根据规则找到对应的dialplan定义,session状态变迁为EXECUTE;
5) 状态机根据dialplan的定义,执行对应的application。
平台外呼
1) 程序调用esl的接口发送外呼命令;
2) Mod_event_socket收到命令之后,调用mod_command的originate;
3) Originate调用switch_ivr定义的函数,创建session,启动session处理线程(状态机),同时状态变迁未INIT;
4) Mod_sofia发起invite请求,同时设置session状态为ROUTING;
5) 外部应答,session状态机变迁未CONSUME_MEDIA;
6) 程序通过esl接口,发送执行application命令,同时session的状态变迁未EXECUTE。
阅读(4569) | 评论(0) | 转发(1) |