代码分析 Asterisk11.5.0

 

sip配置解析

                            //解析配置

load_module->reload_config->build_peer

sip_settings保存全局配置

sip_peer            保存帐号配置

 

 

rtp

 

 

重要的接口函数

chan_sip.c/ struct ast_channel_techsip_tech = {

chan_sip.c/ static struct ast_rtp_gluesip_rtp_glue = {

res_rtp_asterisk.c/static struct ast_rtp_engineasterisk_rtp_engine = {//定义了处理ast_rtp结构体的回调函数。

 

 

/*! Structure that represents an RTPsession (instance) */

struct ast_rtp_instance {

         /*!Engine that is handling this RTP instance */

         struct ast_rtp_engine *engine;

         /*!Data unique to the RTP engine */

         void *data;//sometimes is structast_rtp

         /*!RTP properties that have been set and their value */

         intproperties[AST_RTP_PROPERTY_MAX];

         /*!Address that we are expecting RTP to come in to */

         structast_sockaddr local_address;

         /*!Address that we are sending RTP to */

         structast_sockaddr remote_address;

         /*!Alternate address that we are receiving RTP from */

         structast_sockaddr alt_remote_address;

         /*!Instance that we are bridged to if doing remote or local bridging */

         structast_rtp_instance *bridged;

         /*!Payload and packetization information */

         structast_rtp_codecs codecs;

         /*!RTP timeout time (negative or zero means disabled, negative value meanstemporarily disabled) */

         inttimeout;

         /*!RTP timeout when on hold (negative or zero means disabled, negative value meanstemporarily disabled). */

         intholdtimeout;

         /*!RTP keepalive interval */

         int keepalive;

         /*!Glue currently in use */

         struct ast_rtp_glue *glue;

         /*!Channel associated with the instance */

         struct ast_channel *chan;

         /*!SRTP info associated with the instance */

         struct ast_srtp *srtp;

};

 

extern struct ast_srtp_res *res_srtp;

 

 

 

 

 

 

res_rtp_asterisk.c/ static structast_rtp_engine asterisk_rtp_engine//设置回调函数

 

rtp_engine.c/ ast_rtp_engine_init

 

 

收到一个invite时的处理函数:

 

 

收到一个invite时的处理函数:

sipsock_read-> ast_recvfrom

                     -> handle_request_do

 

handle_request_do->parse_request//解析了消息的头部和体部,解析方法名

                      -> find_sip_method//找到方法名对应的ID

                      -> find_call->sip_alloc//找不到/不存在,就分配一个,这里的是主叫的sip_pvt

                                                                 //当收到响应消息时,会调用handle_response

->handle_incoming->handle_response->handle_response_refer

                                                                      -> handle_response_publish

                                                                      -> handle_response_info

                                                                      -> handle_response_message

                                                                      -> handle_response_notify

                                                                             //收到被叫回的200 ok

                                                                      -> handle_response_invite-> find_sdp

                                                                                                                            ->process_sdp

                                                                                                                            ->ast_rtp_instance_activate

                                                                                                                            ->ast_queue_control//seewait_for_answer

                                                                                                                            ->transmit_request//回ACK

                                                                                                                            ->check_pendingstransmit_reinvite_with_sdp//这里是第三次发送reinvite

                               -> handle_request_options

                               -> handle_request_refer

                               -> handle_request_cancel

                               -> handle_request_bye

                               -> handle_request_message

                               -> handle_request_subscribe

                               -> handle_request_register

                               -> handle_request_info

                               -> handle_request_notify

                                        //SIP_UPDATE

                               -> handle_request_update

                              //SIP_ACK

                               -> __sip_ack

                               -> check_pendings-> transmit_request(SIP_CANCEL)

                                                                     -> transmit_request_with_auth(SIP_BYE)

->transmit_reinvite_with_sdp//这里是第二次发送reinvite,主叫的针对200OK消息的ack来的时候。

                               //当收到invite时,会调用handle_request_invite

->handle_request_invite->check_user_full-> check_peer_ok-> check_auth//如果没有鉴权,asterisk会发送401

                                                                                  ->dialog_initialize_rtp-> ast_rtp_instance_new-> ast_rtp_new(instance->engine->new)

                                                                                                                         -> do_setnat

->find_sdp

->process_sdp->get_sdp_iterate

                          ->process_sdp_c

                          ->process_sdp_a_audio

                          ->process_sdp_a_ice

                          ->process_crypto-> setup_srtp//分配主叫的structsip_srtp。但是当被叫回的200运行到这里时,不会再为被叫分配。

->sdp_crypto_setup//产生主叫的Srtp的密钥,并存入srtp-> crypto,asterisk200消息中回给主叫。

                                                         -> sdp_crypto_process->sdp_crypto_activate

                                                                                                     -> sdp_crypto_offer

                          ->ast_queue_control(AST_CONTROL_UNHOLD)

                          ->ast_queue_control_data(AST_CONTROL_HOLD)

                          ->ast_rtp_instance_stop

                          ->ast_queue_frame(ast_null_frame)

                          ->change_hold_state

-> ast_queue_control-> ast_queue_frame-> __ast_queue_frame

->get_destination

-> build_contact

->sip_new//分配主叫的ast_channel,这里会确定跟主叫之间的codec

-> build_route

->ast_pbx_start创建一个线程运行pbx_thread,第一次收到invite才会运行到这里。

//收到reinvite,holdunhold

-> transmit_response_with_sdp(200)

->ast_queue_control(AST_CONTROL_UPDATE_RTP_PEER)//然后看ast_generic_bridge或者remote_bridge_loop

 

pbx_thread-> __ast_pbx_run->ast_exists_extension-> pbx_extension_helper

                                  -> ast_spawn_extension->pbx_extension_helper-> pbx_exec->执行到Dial时,调用回调函数dial_exec,这个是通过load_module->ast_register_application注册的

                                                  -> ast_pbx_start

 

 

                                                                                                                //这里是被叫的sip_pvt

dial_exec->dial_exec_full->ast_request(sip_request_call)->sip_alloc-> do_setnat

                                                                                                                                   ->build_via

                                                                                                         -> create_addr

                                                                                                         -> ast_sip_ouraddrfor->ast_ouraddrfor

                                                                                                         -> check_for_nat

                                                                                                         -> do_setnat

                                                                                                         -> build_via

                                                                                                                //分配被叫的ast_channel,codec nego,这里会确定跟被叫之间的codec

                                                                                                         ->sip_new->ast_format_cap_is_empty

                                                                                                                           ->ast_codec_choose

                                                                                                                           ->ast_format_cap_remove_bytype

                                                                                                                           ->ast_format_cap_add

                                                                                                                           ->ast_getformatname_multiple

                                                                                                                           ->ast_getformatname

                                                                                                                           ->enable_dsp_detect

                                                                                                                           ->ast_channel_set_fd

                                                                                                                           -> ast_rtp_instance_set_write_format

                                                                                                                           -> ast_rtp_instance_set_read_format

                                                                                                                           -> ast_exists_extension->pbx_extension_helper

                                               ->ast_rtp_instance_early_bridge_make_compatible

                                               //sip_call函数在发出invite后返回,这里是把重新生成的invite发给被叫,被叫是指上面使用ast_request分配资源的那个刚刚创建的被叫

                                         -> ast_call(sip_call)-> transmit_invite->build_via

                                                                                                                  -> initreqprep

                                                                                                                  -> reqprep

                                                                                                                  -> try_suggested_sip_codec

                                                                                                                  -> add_sdp-> get_our_media_address

                                                                                                                                                                                 //产生被叫的Srtp的密钥,并存入srtp-> crypto,在asteriskinvite消息中发给被叫。

                                                                                                                                   ->get_crypto_attrib-> sdp_crypto_setup->res_srtp/get_random

                                                                                                                                                                                 ->sdp_crypto_offer

                                                                                                                  -> initialize_initreq

                                                                                                                  -> send_request

                                                 // wait_for_answer,收到被叫回的200 OK后,这个函数才返回

                                               -> wait_for_answer

                                               ->ast_bridge_call->ast_raw_answer-> set_config_flags

->sip_answer-> try_suggested_sip_codec

                                                                                                                                            ->ast_rtp_instance_update_source//下一个package打上marker bit

                                                                                                                                                     //向主叫回200 ok

                                                                                                                                            ->transmit_response_with_sdp-> ast_rtp_codecs_packetization_set

->ast_rtp_instance_activate(ast_rtp_activate)-> SSL_do_handshake

                                                                                        -> dtls_srtp_check_pending->__rtp_sendto

                                                                                                                                                                                                    ->add_sdp-> get_crypto_attrib//这里不再产生Srtp的密钥,因为主叫的密钥之前已经产生。

                                                                                                                                                                                                    ->send_response

                                                                                    //ast_channel_bridge是被循环调用的。下面也是循环调用。

                                                                             ->channel.c /ast_channel_bridge-> ast_indicate->ast_indicate_data-> sip_indicate

->bridge_play_sounds

->rtp_engine.c/ast_rtp_instance_bridge-> get_rtp_info(chan_sip.c/sip_get_rtp_peer)

                                                                                                                                                                                                                                //查看主被叫是否都配置了directmedia=yes

                                                                                                                                                                                                                        ->allow_rtp_remote(chan_sip.c/sip_allow_rtp_remote)

                                                                                                                                                                                                                        ->local_bridge_loop

                                                                                                                                                                                                                                这个就是p2p                                                                                                         //这里是第一次发送reinvite

->remote_bridge_loop->update_peer(chan_sip.c/sip_set_rtp_peer)->transmit_reinvite_with_sdp

                                                                                                                                                                                                                                                                      //事件处理,下面是循环,直到呼叫结束

                                                                                                                                                                                                                                                                       // AST_CONTROL_HOLD//向被叫发出invite,rtp ipastip

                                                                                                                                                                                                                                                                       -> update_peer (chan_sip.c/sip_set_rtp_peer)->transmit_reinvite_with_sdp

                                                                                                                                                                                                                                                                       ->ast_indicate_data(AST_CONTROL_HOLD)->sip_indicate-> ast_moh_start

                                                                                                                                                                                                                                                                      -> update_peer (chan_sip.c/sip_set_rtp_peer)->transmit_reinvite_with_sdp

                                                                                                                                                                                                                                                                      -> ast_indicate_data(AST_CONTROL_UNHOLD)-> sip_indicate->ast_moh_stop

                                                                                                                                            //但不需要发送reinvite时,会运行到这里,媒体经asterisk中转都会运行到这里

                                                                                                                                           ->ast_generic_bridge->ast_indicate_data(AST_CONTROL_HOLD)->sip_indicate-> ast_moh_start

                                                                                                                                                                                           -> ast_indicate_data(AST_CONTROL_UNHOLD)->sip_indicate-> ast_moh_stop

 

 

上面的rtp_engine.c/ast_rtp_instance_bridge,是主要的判断是否发送reinvite的函数:

首先判断主被叫是否配置了srtp,如果是就不会发送reinvite。

然后判断主被叫的标志位SIP_DIRECT_MEDIA是否置位(即是否都配置了directmedia=yes或者nonat等),如果有一个不置位就不发送reinvite。

然后判断音视频的rtp流中,如果有一个不可以p2p,就都不p2p。

然后判断地址族是否一样。

然后判断是否需要截取dtmf,比如dialplan中有Tt(Dial(SIP/${EXTEN},30,Tt),表示呼叫转移),就表示需要截取dtmf以获取转移的第三方的号码。如果需要截取DTMF,就不发reinvite。

然后判断codec是否一样,打包间隔是否一样。

上面有一个不满足,就会调用ast_generic_bridge,不会发送reinvite。如果都满足的话,就会调用remote_bridge_loop,发出reinvite。

 

 

 

ast_indicate_dataast_queue_frame

 

ast_indicate_data是用于对远端的操作,比如AST_CONTROL_HOLD时,是播放背景音乐。一般是用户线程使用这个函数。

ast_queue_frame(ast_queue_control、ast_queue_control_data)是主线程向用户线程发送事件。一般是主线程使用这个函数。

 

 

 

flag用法

#define SIP_REINVITE         (7 << 20) /*!< DP: foursettings, uses three bits */

#define SIP_REINVITE_NONE    (0 << 20) /*!< DP: no reinviteallowed */

#define SIP_DIRECT_MEDIA     (1 << 20) /*!< DP: allow peers tobe reinvited to send media directly p2p */

#define SIP_DIRECT_MEDIA_NAT (2 <<20) /*!< DP: allow media reinvite when new peer is behind NAT */

#define SIP_REINVITE_UPDATE  (4 << 20) /*!< DP: use UPDATE(RFC3311) when reinviting this peer */

//2 << 20 = 1 << 21、4 << 20 = 1 << 22,所以下面就直接用了1 << 23,没有用1 <<21、1 << 22,不然就重了。

 

 

ast_clear_flag(&flags[0],SIP_REINVITE);

ast_set_flag(&flags[0],SIP_DIRECT_MEDIA | SIP_DIRECT_MEDIA_NAT);

ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA_NAT)

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值